【问题标题】:Django filter with manytomanyfieldDjango过滤器与manytomanyfield
【发布时间】:2020-02-01 22:51:15
【问题描述】:

这是我的模型

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

谁能帮我实现这个目标?

【问题讨论】:

  • 你为什么首先使用is_group_member
  • 我需要使用这个字段来解决一个案例!
  • 我只是在这里展示了一个示例模型,但我的实际模型不是这个

标签: django django-models django-orm django-signals


【解决方案1】:

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

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

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

选项 1:添加属性

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

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

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

选项 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(
            is_group_member=Exists(Group.objects.filter(members=OuterRef('pk')))
        )

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

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

    objects = PersonManager()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-06-12
    • 2022-11-25
    • 1970-01-01
    • 1970-01-01
    • 2019-12-04
    • 2018-07-25
    • 2021-06-16
    • 2011-01-08
    相关资源
    最近更新 更多