具有 manytomanyfield 的 Django 过滤器

Django filter with manytomanyfield

这是我的模型

class Person(models.Model):
    name = models.CharField(max_length=50)
    is_group_member = models.BooleanField(default=False)

class Group(models.Model):
    members = models.ManyToManyField(Person)


@receiver(post_save, sender=Group)       
def set_group_member_type(sender, instance, created, **kwargs):
    if created:
        # change the all group members' type

我正在尝试用信号更新 is_group_member 字段。

当创建一个包含成员的群组时,我将过滤并检索所有群组成员,然后我将 is_group_member 值更改为 True

谁能帮我实现这个目标?

您可以这样做,但通常 不是 通过信号,因为该组是在添加成员之前 创建的 。因此,触发器将在 有成员之前被触发。

此外,定义这样的字段可能不是一个好主意。如果您稍后从组中删除某个成员,或添加其他成员,则很难相应地更新所有成员。一个人可能仍然是不同群体的成员。它是一种数据复制,事实证明,同步数据通常是一个比看起来更难的问题。

因此,最好将 属性 添加到您的 Person 模型,或者注释您的 objects 查询集。

选项 1:添加 属性

我们可以添加一个 属性 来检查 Person 是否是组的成员。这将对数据库执行查询,对于我们查询的每个人:

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

    @property
    def is_group_member(self):
        return <b>Group.objects.filter(members=self).exists()</b>

选项 2:自定义 objects 管理器

我们可以注释 objects 管理器,这样它将 运行 查询集中每个 Person 的子查询。例如,我们可以将此添加到 objects 管理器:

from django.db.models import Exists, OuterRef

class PersonManager(models.Manager):

    def get_queryset(self):
        from app.models import Group
        return super().get_queryset().annotate(
            <b>is_group_member=Exists(Group.objects.filter(members=OuterRef('pk')))</b>
        )

然后我们可以将经理添加到 Person class:

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

    <b>objects = PersonManager()</b>