我们想在ManyToManyField方法中访问相关的Model.save数据预保存,但是该数据尚无法通过Django ORM获得,因为它与相关的ManyToManyField数据有关,并且只有在post-save个主要记录。

这是关系的一些示例代码,并且在ManyToMany中访问相关的Model.save记录

class Friend(models.Model):
    name = models.CharField(max_length=50)

class Person(models.Model):
    name = models.CharField(max_length=50)
    friends = models.ManyToManyField(Friend)

    def save(self, *args, **kwargs):
        friends = self.friends.all()

        # 'friends' is an empty QuerySet at this point
        # I'd like to do something with friends here,
        # but it gets set after save

        super(Friend, self).save(*args, **kwargs)


friends上传递save的示例用例:

friend = Friend.objects.all()[0]
friend2 = Friend.objects.all()[1]
friends = [friend, friend2]
Person.objects.create(friends=friends)

最佳答案

m2m关系是在实例保存后建立并获得其自己的ID,因此无法在覆盖保存方法中访问它,两种存档方式:

一:在django 1.9之后,交易工具提供了侦听数据库通信的新方法,doc为here。演示代码为:

from django.db import transaction

class Person(models.Model):
    name = models.CharField(max_length=50)
    friends = models.ManyToManyField(Friend)

    def save(self, *args, **kwargs):
        instance = super(Person, self).save(*args, **kwargs)
        transaction.on_commit(self.update_friend)
        return instance

    def update_friend(self):
        for friend in self.friends.all():
            print(friend.__str__())


第二种方法是使用信号,这里是演示:

from django.db.models.signals import m2m_changed
@receiver(m2m_changed, sender=Person.friends.through)
def friends_change(sender, action, pk_set, instance=None, **kwargs):
    if action in ['post_add', 'post_remove']:
        queryset = instance.friends.all()
        for friend in queryset:
            print(friend.__str__())

10-06 16:16
查看更多