Django-尝试更新模型对象时出现ValueError

时间:2020-09-07 02:53:09

标签: python django

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

以下是两个相关模型:

    @UI.facet: [{
           label : 'General Information',
           id : 'GeneralInfo',
           isSummary:true,
           purpose: #STANDARD,
           type : #COLLECTION,
           position: 10
       },
       {
           label: 'Basic Data',
           id : 'BasicData',
           purpose: #STANDARD,
           parentId : 'GeneralInfo',
           type : #FIELDGROUP_REFERENCE,
           targetQualifier : 'BasicData',
           position: 20
       }]

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.

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

    @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)

因此,我认为我对ForiegnKey的理解和使用存在缺陷。我将如何正确执行此操作?

此外,如果我的格式设置已关闭,我深表歉意,这是我第一次在这里发布。

1 个答案:

答案 0 :(得分:0)

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

使用实际项目而不是其ID的整数值创建监视列表:

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

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

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

这看起来有些奇怪:虽然您可能习惯于将外键称为item_id,但最好以实际关系命名外键。因此,在这种情况下,您应该将item_id类中的watchlist更改为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)