简体   繁体   English

使用保存方法扩展M2M关系

[英]Using save method to extend M2M relationship

I have a model like this 我有这样的模特

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

I want authorities having the same country and category and itself to be automatically give an M2M relationship,so i did this 我希望具有相同国家和类别的机构及其本身能够自动建立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)

It wasn't working and not bringing any error,I also tries this below 它没有工作并且没有带来任何错误,我也在下面尝试了

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)

What might be wrong with my code?Thanks in advance. 我的代码可能出了什么问题?

The reason this isn't working the way you expect is because of how Django handles creating m2m relationships in the database. 之所以无法按您预期的方式运行,是因为Django如何处理在数据库中创建m2m关系。 Long story very short, when you save something like a new Authority to the database, Django first writes the new object then goes back in and writes the m2m relationships for that new object. 长话短说,当您将诸如新的Authority类的内容保存到数据库时,Django首先写入新对象,然后返回并为该新对象写入m2m关系。 As a result, it's tough to do anything useful to m2m relationships in a custom save method. 结果,很难使用自定义save方法对m2m关系执行任何有用的操作。

A post-save signal may do the trick here. 保存后的信号可以解决这个问题。 kwargs['created'] = True if we're creating a new object and kwargs['instance'] is the instance whose save fired off the signal receiver. kwargs['created'] = True如果我们正在创建一个新对象,则为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()

It's important to only fire this when creating new objects. 重要的是仅在创建新对象时触发此操作。 If you don't include that restriction, then the receiver will trigger itself as you update other objects in your for loop. 如果不包括该限制,则接收器将在更新for循环中的其他对象时触发自身。

I haven't tested this out but I think it'll work. 我尚未对此进行测试,但我认为它会起作用。 Let me know if it doesn't and I'll do my best to help. 让我知道是否可以,我会尽力提供帮助。

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

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