【问题标题】:Model methods stop working correctly after first call模型方法在第一次调用后停止正常工作
【发布时间】:2013-01-10 10:24:06
【问题描述】:

我为零售商及其库存中的商品定义了两种模型。产品在另一个应用程序中定义。我定义了两个模型方法来获取和添加库存项目。这是代码的相关部分:

class Retailer(models.Model):
    name = models.CharField(max_length=100)
    @property
    def stock_items(self):
        return StockItem.objects.filter(retailer__id=F('id'))

    def add_stock_item(self, product_id):
        try:
            print "Checking if it's already in stock"
            self.stock_items.get(product__id=product_id)
            print "It's already in stock"
        except ObjectDoesNotExist:
            try:
                print "Adding item to stock"
                product = Product.objects.get(pk=product_id)
                StockItem.objects.create(retailer=self, product=product)
                print "Added to stock"
            except Product.DoesNotExist:
                print "Such product doesn't exist"
    def __unicode__(self):
        return self.name


StockItem(models.Model):
    retailer = models.ForeignKey(Retailer)
    product = models.ForeignKey(Product)
    def __unicode__(self):
        return "%s - %s %s" % (self.retailer, self.product.brand, self.product)

当我想使用这些模型方法时,会发生一些奇怪的事情。添加第一项后,它们会停止正常工作(在这些示例中,产品 1 是 16 GB iPhone,产品 2 是 32 GB iPhone)。

首先让我们将一些产品添加到我们的库存中:

>>> r = Retailer.objects.get(pk=1)
>>> r.stock_items
[]
>>> r.add_stock_item(1)
Checking if it's already in stock
Adding item to stock
Added to stock
>>> r.add_stock_item(2)
Checking if it's already in stock
Adding item to stock
Added to stock

到目前为止一切顺利。现在让我们再次尝试添加产品,看看它是如何处理错误的:

>>> r.add_stock_item(1)
Checking if it's already in stock
It's already in stock
>>> r.add_stock_item(2)
Checking if it's already in stock
Adding item to stock
Added to stock

什么?为什么又添加了产品 2。它应该显示类似于产品 1 的消息。让我们看看我们的库存:

>>> r.stock_items
[<StockItem: hh - Apple iPhone 4S 16GB>]

产品 2 发生了什么?是否添加到数据库失败?

[<StockItem: hh - Apple iPhone 4S 16GB>, <StockItem: hh - Apple iPhone 4S 32GB>, <StockItem: hh - Apple iPhone 4S 32GB>]

显然不是。它已添加到数据库中,但不知何故我们的程序无法正确检查它。调用 r.stock_items 仅显示添加到库存的第一个产品。重启shell也不会改变这种情况,所以我猜原因不可能是因为函数被评估的时候。

为什么会发生这种情况,我该如何解决?

【问题讨论】:

  • 在保存之前尝试在 except 函数中进行第二次检查。

标签: python django django-models model


【解决方案1】:

尝试删除@property并将方法更改为:

def stock_items(self):
    return self.stockitem_set.all()

【讨论】:

  • 谢谢,只需将其更改为 self.stockitem_set.all() 已唤醒。但为什么呢?
  • 如果您使用 self.pk 而不是 F('id'),那么它也可以。但实际上stock_items必须是StockItem类方法,而不是Retailer类方法。
  • 我觉得这样比较好,因为现在view可以通过调用request.user.retailer.stock_items来获取当前用户的库存(Retailer和User是一对一的关系,我没有'不要在我的问题中包含类定义的那部分)
【解决方案2】:

您的方法失败的原因是该表达式没有按照您的想法执行。 F() 语法用于比较同一行中的值:因此该表达式检查相关零售商 ID 是否与当前行的 ID 相同。碰巧这对于第一个项目是正确的,但对于任何后续项目都不会是这样,因为行 ID 随着新项目的增加而增加,但零售商 ID 保持不变。

【讨论】:

  • 现在说得通了。谢谢。
猜你喜欢
  • 2018-01-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-03-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-03-26
相关资源
最近更新 更多