2014-03-31 25 views
1

我想要做的是在创建ScanEvent实例时增加卡的点数。 我有以下型号:如何使用信号更新Django中的另一个对象?

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) 

在一个简单的Django壳,当我试试这个:

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

我没有得到任何错误,但不会更新点(这是因为信号不叫) (它工作时,我重写save()方法思想)

谢谢。

+0

请出示您所使用的连接信号到底是什么代码。 –

+0

完成。不知道它是连接信号的正确位置(但错误似乎与此无关)。 –

回答

1

不确定您的模型是否正确。通过指向卡的外键,这意味着每个卡都有多个点实例。所以当你有一个Card对象时,你不能直接访问这些点:card.points是与这张卡相关的所有Points对象的查询集。

要么你需要确定哪个相关点是你的意思,或者改变你的模型。可能使用OneToOne字段而不是ForeignKey会更合适:那么您只有一个Points实例,并且card.points将按照您的预期引用该实例,然后您将能够访问它的nb_current_points值。

编辑

递归错误是因为你连接你的处理程序,以保存信号所有类,而不仅仅是ScanEvent。注册时,您应该确保指定sender参数:

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

请注意,您必须搬完了ScanEvent类的,否则你会得到错误的名称。

+0

哦,我的错误对不起:我删除了一些字段,以使它更容易在StackOverflow,但ForeignKey是故意的,因为每个现有ownerProfile(请参阅更新的代码)存在一个Points实例。 –

+0

感谢您的编辑。递归的另一个原因是因为我保存了“实例”而不是“点”。添加ScanEvent作为发件人使我有一个'NameError:名称'ScanEvent'没有定义':( –

1

在您的模型中,卡片可能有几个关联点。这就是为什么instance.scanned_card.points是一个RelatedManager,而不是一个Point。 试试这个:

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

感谢renobryce和@Daniel Roseman这帮助我明白,我调用了queryset而不是对象的方法。不同(请参阅更新后的文章) –

相关问题