小売業者と在庫のある商品について、2つのモデルを定義しました。製品は別のアプリで定義されています。在庫アイテムを取得および追加するための2つのモデルメソッドを定義しました。コードの関連部分は次のとおりです。
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を呼び出すと、在庫に追加された最初の製品のみが表示されます。シェルを再起動しても状況は変わらないので、関数が評価されたときのせいではないと思います。
なぜこれが発生し、どうすれば修正できますか?