【问题标题】:Django - ValueError when trying to update a model objectDjango - 尝试更新模型对象时出现 ValueError
【发布时间】:2020-09-07 02:53:09
【问题描述】:

我正在为一个班级编写一个 Django 程序。我知道错误与外键分配有关,但我不明白我的逻辑缺陷在哪里。

以下是两个相关的模型:

    class listing(models.Model):    
        title = models.CharField(max_length=100)
        description = models.TextField()
        url = models.URLField(default="", null=True, max_length=100)
        category = models.CharField(default="", max_length=50)
        user_name = models.CharField(max_length=100)
        date = models.DateTimeField(auto_now_add=True)
        is_active = models.BooleanField(default=True)
        min_bid = models.DecimalField(max_digits=8, decimal_places=2)


    class watchlist(models.Model):
        item_id = models.IntegerField(null=False)
        user_id = models.IntegerField(null=False)
        
        #item_id = models.ForeignKey("auctions.listing", on_delete=models.CASCADE, related_name="item_watchlist")
        #user_id = models.ForeignKey("auctions.User", on_delete=models.CASCADE, related_name="user_watchlist")

watchlist Class 中的最后两行已被注释掉,使代码能够正常工作。但是,我想了解如何按照我最初的意图进行这项工作。如下:(以下代码在对象创建部分失败,带有ValueError, cannot assign <value>: item_id must be an instance of listings.

    @login_required
    def item_listing(request, id):
        itemID = id
    
        # GET call coming in from clicking a title link
        if request.method == "GET":
            item = listing.objects.filter(id=id)
            
            # Check if the item is on the user's watchlist
            if watchlist.objects.filter(item_id=id, user_id=request.user.id).exists():
                watch = True
            else:
                watch = False
    
            return render(request, "auctions/ItemPage.html", {
                "item": item,
                "name": item[0].title,
                "url": item[0].url,
                "description": item[0].description,
                "user_name": item[0].user_name,
                "price": item[0].min_bid,
                "category": item[0].category,
                "watch": watch
            })
    
        # POST call coming in from clicking the watchlist button
        if request.method == "POST":
            
            q = request.POST.get('wl')
            
            # Remove from watchlist. Delete entry in database.
            if q == "Remove from Watchlist":
                watchlist.objects.filter(item_id=id, user_id=request.user.id).delete()
    
            # Add to watchliset. Create entry.
            else:
                watchlist.objects.create (
                    item_id=id, 
                    user_id=request.user.id
                )
    
        # Redirect back to thet page
        pathname = "/" + str(itemID)
        return redirect(pathname)

我的假设是在 watchlist 模型上创建外键会将选择限制为 listing PK。删除对象没问题,它工作正常。即使我可以查询列表并且确实存在 7 的 ID,但使用 7 的 Item_id 创建对象未能添加到监视列表:

listing.objects.all()
<QuerySet [<listing: Japanese Tea pot>, <listing: Kindle paperwhite>]>
>>> listing.objects.filter(id=7)
<QuerySet [<listing: Japanese Tea pot>]>

所以我认为我对 ForiegnKey 的理解和使用是有缺陷的。我该如何正确地做到这一点?

另外,如果我的格式关闭,我深表歉意,这是我第一次在这里发帖。

【问题讨论】:

标签: python django


【解决方案1】:

我认为这是一个很常见的错误。创建ForeignKey 字段时,它充当实际数据库外键关系的抽象。这意味着调用(在您的情况下)watchlist.item_id 不会返回id,而是实际的listing 对象。创建对象时也是如此。

使用实际项目创建您的关注列表,而不是其 id 的整数值:

 watchlist.objects.create (
                    item_id=item, 
                    user_id=request.user.id
                )

我不确定将键而不是实例传递给模型的过滤方法是否有效,但最好也将实际对象也传递给那里:

watchlist.objects.filter(item_id=item, user_id=request.user)

这看起来有点奇怪:虽然您可能习惯将外键称为 item_id,但最好在实际关系之后命名外键。因此,在这种情况下,您应该将 watchlist 类中的 item_id 更改为 item

此外,Django 类应该用大写字母书写,所以你的类应该是这样的:

class Listing(models.Model):    
        ...

class WatchList(models.Model):
    item = models.ForeignKey("auctions.listing", on_delete=models.CASCADE, related_name="item_watchlist")
    user = models.ForeignKey("auctions.User", on_delete=models.CASCADE, related_name="user_watchlist")

然后你的代码当然应该改为:

 WatchList.objects.create (
                    item=item, 
                    user=request.user.id
                )

和:

WatchList.objects.filter(item=item, user=request.user)

【讨论】:

  • 感谢您抽出时间来回答这个问题。我已经成功地让这个与你的答案一起工作。
  • 别担心!很高兴帮助:)
猜你喜欢
  • 2019-10-27
  • 2020-02-14
  • 2019-07-07
  • 2020-11-30
  • 2021-08-05
  • 2021-09-14
  • 1970-01-01
  • 2018-09-30
  • 1970-01-01
相关资源
最近更新 更多