Фильтр Джанго со множеством полей - PullRequest
1 голос
/ 03 октября 2019

Это мои модели

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

Может ли кто-нибудь помочь мне достичь этого?

1 Ответ

0 голосов
/ 03 октября 2019

Вы можете сделать это, но обычно не по сигналам, поскольку группа создается до добавления членов. Таким образом, триггер будет срабатывать до того, как появятся члены.

Более того, вероятно, не хорошая идея вообще определить такое поле. Если вы позже удалите участника из группы или добавите других участников, будет сложно обновить всех участников соответствующим образом. Человек все еще может быть членом другой группы. Это форма дублирования данных , и оказывается, что синхронизация данных, как правило, сложнее, чем кажется.

Поэтому лучше либо добавить свойство к вашему 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 manager

Мы можем комментировать objects manager,так что он будет запускать подзапрос для каждого 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 Person(models.Model):
    name = models.CharField(max_length=50)

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