我有这样的模型
class Authority(models.Model):
name=models.CharField(max_length=100)
country=models.ForeignKey(Country)
category=models.ForeignKey(Category)
competitors=models.ManyToManyField("self",related_name="competitors")
我希望拥有相同国家和类别的权威机构能够自动提供M2M关系,所以我这样做了
def save(self,*args,**kwargs):
z=Authority.objects.filter(country=self.country).filter(category=self.category)
this_authority=Authority.objects.get(id=self.id)
for a in z:
this_authority.competitors.add(a)
super(Authority,self).save(*args,**kwargs)
它没有工作,没有带来任何错误,我也在下面试试
def save(self,*args,**kwargs):
z=Authority.objects.filter(country=self.country).filter(category=self.category)
this_authority=Authority.objects.get(id=self.id)
self.competitors=z
super(Authority,self).save(*args,**kwargs)
我的代码可能出现什么问题?提前致谢。
答案 0 :(得分:0)
这不符合您的预期的原因是因为Django如何处理在数据库中创建m2m关系。长话故事非常简短,当您将类似新Authority
的内容保存到数据库时,Django首先编写新对象然后返回并为该新对象写入m2m关系。因此,在自定义save
方法中对m2m关系执行任何有用的操作都很困难。
post-save signal可以在这里解决问题。 kwargs['created'] = True
如果我们正在创建一个新对象,kwargs['instance']
是保存从信号接收器发出的实例。
@receiver(post_save, sender = Authority)
def update_m2m_relationships(sender, **kwargs):
if kwargs['created']: #only fire when creating new objects
competitors_to_add = Authority.objects.filter(
country = kwargs['instance'].country,
category = kwargs['instance'].category
)
for c in competitors_to_add:
c.competitors.add(kwargs['instance'])
c.save() #not creating a new object; this receiver does not fire here
kwargs['instance'].competitors.add(c)
#all competitors have been added to the instance's m2m field
kwargs['instance'].save()
在创建新对象时仅启动此项非常重要。如果您不包含该限制,那么当您更新for循环中的其他对象时,接收器将触发自身。
我没有对此进行过测试,但我认为它会起作用。如果没有,请告诉我,我会尽力帮助。