Как отфильтровать набор запросов Django после его изменения в цикле

Я недавно работаю с Django, и он меня сильно смущает (хотя он мне и нравится).

Проблема, с которой я сталкиваюсь сейчас, заключается в том, что когда я выполняю цикл и в цикле изменяю querryset, в следующем цикле .filter не работает.

Рассмотрим следующий упрощенный пример:

У меня есть словарь, который создается из набора запросов следующим образом animal_dict = {курица: 6, коровы: 7, рыба: 1, овцы: 2}

Кверисет называется self.animals

for key in dict:
    if dict[key] < 3:
        remove_animal = max(dict, key=dict.get)
        remove = self.animals.filter(animal = remove_animal)[-2:]
        self.animals = self.animals.difference(remove)
        key[replaced_industry] = key[replaced_industry] - 2

Я пытаюсь сделать следующее: моя цель состоит в том, что должен быть баланс между животными. Так как рыб не хватает, 2 животных с наибольшим n должны уйти (коровы). И затем во втором цикле - поскольку не хватает овец, 2 из животных с наибольшим n должны идти снова (курица).

Теперь при первом цикле (с fish) .filter делает все так, как нужно. Однако, когда я делаю цикл во второй раз (для овец), remove = self.animals.filter(animal = remove_animal)[-2:] выдает ошибку, не соответствующую фильтру animal =. Когда я печатаю remove во втором цикле, он возвращает список всех различных животных (вместо только 1).

После циклов dict должен выглядеть следующим образом: {курица: 4, коровы: 5, рыба: 1, овца: 2} Это потому, что сначала корова спустится на 2 и будет max, а затем курица спустится на 2, так как будет max

Я определенно не понимаю логики Django, но мне это кажется очень странным. Надеюсь, что вопрос понятен, в противном случае буду рад дальнейшим разъяснениям.

Отвечаю на свой собственный вопрос. Очевидно, это не сработало, потому что разрешены только count(), order_by(), values(), values_list() и нарезка union queryset. Вы не можете фильтровать по union queryset, и то же самое относится к .difference,

Подробнее об этом здесь: Django: Filter a Queryset made of unions not working

Поскольку во втором цикле он превращается в union queryset, функция фильтрации просто не работает. Странно то, что это не показывает ошибку, а просто не фильтрует, что затрудняет обнаружение.

Как отмечали другие, каждый раз, когда вы вызываете self.animals.filter, вы делаете запрос к базе данных, и это не должно выполняться в цикле.

Не очень понятно, чего вы пытаетесь достичь, но похоже, что вы хотите, чтобы количество каждого вида животных было (почти?) одинаковым, и что единственная операция, которую вы можете выполнить над ним - это уменьшение количества животных.

Всегда лучше избегать циклов, если это возможно.

Если вы хотите, чтобы их было одинаковое количество, и вы можете только уменьшить количество животных, то лучшим решением будет

fewest_number = min(self.animals.values())
self.animals = {animal: fewest_number for animal in self.animals.keys()}

Если вы хотите, скажем, разрешить допуск +1 от наименьшего количества животных

fewest_number = min(self.animals.values()) + 1
self.animals = {animal: fewest_number for animal in self.animals.keys()}

Если увеличить количество каждого вида животных, то можно найти среднее значение:

average_number = sum(self.animals.values()) / len(self.animals)
self.animals = {animal: average_number for animal in self.animals.keys()}
Вернуться на верх