Djangoについて質問があります。
ここにManyToManyモデルがあります
class Product(models.Model):
name = models.CharField(max_length=255)
price = models.DecimalField(default=0.0, max_digits=9, decimal_places=2)
stock = models.IntegerField(default=0)
def __unicode__(self):
return self.name
class Cart(models.Model):
customer = models.ForeignKey(Customer)
products = models.ManyToManyField(Product, through='TransactionDetail')
t_date = models.DateField(default=datetime.now())
t_sum = models.FloatField(default=0.0)
def __unicode__(self):
return str(self.id)
class TransactionDetail(models.Model):
product = models.ForeignKey(Product)
cart = models.ForeignKey(Cart)
amount = models.IntegerField(default=0)
作成された1つのカートオブジェクトに対して、新しいTransactionDetailオブジェクト(製品と金額)を挿入できます。私の質問は。トリガーを実装するにはどうすればよいですか?私が欲しいのは、取引の詳細が作成されるたびに、商品の在庫の金額が取引の詳細の金額で差し引かれることです。
Post_save()について読んだことがありますが、実装方法がわかりません。多分こんな感じ
いつ:
post_save(TransactionDetail,
Cart) #Cart object where TransactionDetail.cart= Cart.id
Cart.stock -= TransactionDetail.amount
本当に信号を使用してこれを達成したい場合、以下に簡単に説明します。
from Django.db.models.signals import post_save
from Django.dispatch import receiver
class TransactionDetail(models.Model):
# ... fields here
# method for updating
@receiver(post_save, sender=TransactionDetail, dispatch_uid="update_stock_count")
def update_stock(sender, instance, **kwargs):
instance.product.stock -= instance.amount
instance.product.save()
個人的にはTransactionDetailのsave()メソッドをオーバーライドし、そこで新しいTransactionDetailを保存してから実行します
self.product.stock -= self.amount
self.product.save()
maximum recursion depth exceeded
、シグナルハンドラー内で保存する前に、シグナルをdisconnectする必要があります。上記の例(Kenny Shenの答え)は、次のようになります。
from Django.db.models.signals import post_save
from Django.dispatch import receiver
class TransactionDetail(models.Model):
# ... fields here
# method for updating
@receiver(post_save, sender=TransactionDetail, dispatch_uid="update_stock_count")
def update_stock(sender, instance, **kwargs):
instance.product.stock -= instance.amount
post_save.disconnect(update_stock, sender=TransactionDetail)
instance.product.save()
post_save.connect(update_stock, sender=TransactionDetail)
これについては、 モデルの信号を切断し、Djangoで再接続する で詳細に説明し、より抽象的な有用な例を示します。
参照: https://docs.djangoproject.com/en/2.0/topics/signals/#disconnecting-signals Django docs 。
実際、Signals
を説明するドキュメントはDjango.dispatch.Signal.connect
:
def connect(self, receiver, sender=None, weak=True, dispatch_uid=None):
Connect receiver to sender for signal.
Arguments:
receiver
A function or an instance method which is to receive signals.
Receivers must be hashable objects.
If weak is True, then receiver must be weak referenceable.
Receivers must be able to accept keyword arguments.
If a receiver is connected with a dispatch_uid argument, it
will not be added if another receiver was already connected
with that dispatch_uid.
sender
The sender to which the receiver should respond. Must either be
a Python object, or None to receive events from any sender.
weak
Whether to use weak references to the receiver. By default, the
module will attempt to use weak references to the receiver
objects. If this parameter is false, then strong references will
be used.
dispatch_uid
An identifier used to uniquely identify a particular instance of
a receiver. This will usually be a string, though it may be
anything hashable.