Исключить набор запросов из набора запросов в отношениях «многие ко многим»

#django #database

#django #База данных

Вопрос:

У меня есть эти модели:

 class Word(models.Model):
    word = models.CharField(max_length=64, primary_key=True)

class Pack(models.Model):
    pack_name = models.CharField(max_length=64, primary_key=True, default='Repository')
    words = models.ManyToManyField(Word)
    number_of_words = models.IntegerField(default=0)
  

У меня есть несколько пакетов, в которых добавлено несколько слов. Я хочу составить список всех слов, кроме тех, которые добавлены внутри определенного пакета, а именно «Другие»; т. Е. я хочу сделать что-то вроде этого:

 otherPackModel = Pack.objects.get(pack_name="Others")
wordModels = Word.objects.all().exclude(otherPackModel.words)
wordlist = wordModels.values_list('word', flat=True)
  

Ответ №1:

Вы можете сделать что-то вроде этого:

 Word.objects.filter(pack__pack_name="some name").exclude(pack__pack_name="others").values('word',flat=True)
  

Я использую обратную связь между Word и Pack model для выполнения этого запроса.

Комментарии:

1. Каждое слово может быть членом нескольких пакетов.

Ответ №2:

Если вам нужны все Word объекты, которые не имеют никакого отношения ни к одному Pack объекту, вы можете использовать набор запросов, подобный следующему:

 words_list = Word.objects.exclude(pack_set__isnull=False).values_list('word', flat=True) # or words_list = Word.objects.filter(pack_set__isnull=True).values_list('word', flat=True)
  

Примечание: pack_set в queryset указано ваше имя связанного запроса по умолчанию, поэтому не забудьте изменить его на ваше связанное имя, если вы измените это связанное имя в поле вашей модели.
Но если вы хотите перечислить все Word объекты, которые не являются общими для определенного Pack объекта (или группы Pack объектов), вы можете использовать следующие коды:

Один объект пакета:

 otherPackModel = Pack.objects.get(pack_name="Others")
wordModels = Word.objects.exclude(pack_set=otherPackModel)
wordlist = wordModels.values_list('word', flat=True)
  

Группа объектов пакета:

 otherPackModel = Pack.objects.filter(pack_name="some random name")
wordModels = Word.objects.exclude(pack_set__in=otherPackModel)
wordlist = wordModels.values_list('word', flat=True)