Модель фильтра Django в списке обратной связи - PullRequest
0 голосов
/ 10 апреля 2020

У меня есть две Django модели следующим образом:

class Event(models.Model):
    name = models.CharField()

class EventPerson(models.Model):
    event = models.ForeignKey('Event',on_delete='CASCADE',related_name='event_persons')
    person_name = models.CharField()

Если событие существует в базе данных, оно будет иметь ровно два связанных с ним объекта EventPerson.

Что Я хочу сделать, это определить, существует ли Событие с данным именем И, которое имеет данный набор из двух человек (EventPersons) в этом событии. Возможно ли это сделать в одном Django запросе?

Я знаю, что мог бы написать python код, подобный этому, чтобы проверить, но я надеюсь на что-то более эффективное:

def event_exists(eventname,person1name,person2name):
    foundit=False
    for evt in Event.objects.filter(name=eventname):
        evtperson_names = [obj.person_name in evt.event_persons.all()]
        if len(evtperson_names) == 2 and person1name in evtperson_names and person2name in evtperson_names:
            foundit=True
            break
    return foundit

Или было бы лучше провести рефакторинг моделей таким образом, чтобы Event имел в качестве своих полей поля person1name и person2name, такие как:

class Event(models.Model):
    name = models.CharField()
    person1name = models.CharField()
    person2name = models.CharField()

Проблема в том, что не существует естественного порядка для person1 и person2, ie если это "Боб" и "Салли", то у нас могут быть person1name = "Bob" и person2name = "Sally" или у нас могут быть person1name = "Sally" и person2name = "Bob".

Предложения

Ответы [ 2 ]

0 голосов
/ 10 апреля 2020

Я слегка изменил ответ @blhsing, добавив фильтр по именам.

def event_exists(eventname, person1name, person2name):
    event_people = EventPerson.objects.select_related('event').filter(person_name__in=[person1name, person2name], event__name=eventname)
    return set(event_people.values_list('person_name', flat=True)) person1name, person2name}

Я бы предложил передавать объекты EventPerson или их идентификаторы в эту функцию вместо просто имен, что бы упростило фильтрацию (вы бы не стали нужен набор и фильтрация по идентификаторам) и более эффективный (с использованием индексов БД ... или вам также придется индексировать person_name)

0 голосов
/ 10 апреля 2020

Вы можете запросить объекты EventPerson, в которых вместо этого указано имя события, используйте values_list, чтобы извлечь поле person_name и преобразовать возвращаемый список значений в набор для неупорядоченного сравнения:

def event_exists(eventname, person1name, person2name):
    return set(EventPerson.objects.filter(event__name=eventname).values_list(
        'person_name', flat=True)) == {person1name, person2name}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...