简体   繁体   English

如何使用信号来更新Django中的另一个对象?

[英]How to use signals to update another object in Django?

What I'd like to do is to increase the points of a card when a ScanEvent instance is created. 我想做的是在创建ScanEvent实例时增加卡的点数。 I have the following models: 我有以下型号:

class Card(models.Model):
    # some attributes

class Points(models.Model):
    benef_card = models.ForeignKey(Card, related_name='points')
    at_owner = models.ForeignKey(OwnerProfile)
    nb_current_points = models.PositiveIntegerField(default=0)

class ScanEvent(Event):
    scanned_card = models.ForeignKey(Card)
    scanned_at_owner = models.ForeignKey(OwnerProfile)
    won_points = models.PositiveIntegerField(default=1)

    # This method is called with a post_save signal to add points to a card
    def add_points_to_card(sender, instance, **kwargs):
        pts = instance.scanned_card.points.get(at_owner=instance.scanned_at_owner)
        pts.nb_current_points += instance.won_points
        pts.save()

# At the end of models.py
signals.post_save.connect(ScanEvent.add_points_to_card,
        sender=ScanEvent)

In a simple Django shell, when I try this: 在一个简单的Django shell中,当我尝试这样做时:

card = Card.objects.get(pk=2)
event = ScanEvent(scanned_card=card)
ownr = OwnerProfile.objects.get(pk=1);
event.save() # will call add_points_to_card()

I get no error but points are not updated (this is because the signal is not called) (it works when I override the save() method thought) 我没有错误,但是点没有更新(这是因为未调用信号)(当我重写save()方法时,它可以工作)

Thanks. 谢谢。

Not sure if your models are correct. 不确定您的模型是否正确。 With a ForeignKey from Points to Card, that means each Card has multiple Points instances. 使用从点到卡的外键,这意味着每个卡都有多个点实例。 So when you have a Card object, you can't access the points directly: card.points is a queryset of all the Points objects that are related to this card. 因此,当您拥有Card对象时,就不能直接访问这些点: card.points是与此卡相关的所有Points对象的查询集。

Either you need to determine somehow which related Points is the one you mean, or change your models. 您需要以某种方式确定要关联的相关点,或者更改模型。 Probably using a OneToOne field instead of a ForeignKey would be more appropriate: then you do only have a single Points instance, and card.points will refer to that instance as you expect and you will then be able to access its nb_current_points value. 可能更适合使用OneToOne字段而不是ForeignKey:然后,您只有一个Points实例,而card.points将按您的期望引用该实例,然后您就可以访问其nb_current_points值。

Edit 编辑

The recursion error is because you have attached your handler to the save signal for all classes, not just ScanEvent. 递归错误是因为您已将处理程序附加到所有类的保存信号上,而不仅仅是ScanEvent。 You should be sure to specify the sender parameter when registering it: 注册时,请务必指定sender参数:

signals.post_save.connect(add_points_to_card, sender=ScanEvent)

Note that you'll need to move those out of the ScanEvent class otherwise you'll get name errors. 请注意,您需要将其移出ScanEvent类,否则会出现名称错误。

In your models, a Card may have several Points associated. 在您的模型中,一张卡可能具有多个关联点。 That is why instance.scanned_card.points is a RelatedManager, not a Point. 这就是为什么instance.scanned_card.points是RelatedManager而不是Point的原因。 Try this: 尝试这个:

def add_points_to_card(sender, instance, **kwargs):
    for points in instance.scanned_card.points.all():
      points.nb_current_points += instance.won_points

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM