Я работаю над созданием приложения рецепта коктейля в качестве учебного упражнения.
Я пытаюсь создать фильтр через Rest Framework Django, который принимает строку идентификаторов ингредиентов через параметр запроса (? = Ингридиенты_эксклюзив = 1,3,4), а затем ищет все рецепты, содержащие все эти ингредиенты. Я хотел бы найти «Все коктейли с ромом и гренадином», а затем отдельно «Все коктейли с ромом и все коктейли с гренадином».
Три модели в моем приложении - Recipes, RecipeIngredients и IngredientTypes. Рецепты (старомодные) имеют несколько ингредиентов RecipeIngredients (2 унции виски), а все ингредиенты RecipeIngredients имеют тип ингредиента (виски). В конце концов я изменю RecipeIngredient на через модель в зависимости от того, как далеко я решу это сделать.
Список может быть переменной длины, поэтому я не могу просто соединить вместе функции фильтра. Я должен пройтись по списку идентификаторов, а затем построить Q ().
Однако у меня есть некоторые проблемы. С помощью Django Shell я сделал это:
>>> x = Recipe.objects.all()
>>> q = Q(ingredients__ingredient_type=3) & Q(ingredients__ingredient_type=7)
>>> x.filter(q)
<QuerySet []>
>>> x.filter(ingredients__ingredient_type=3).filter(ingredients__ingredient_type=7)
<QuerySet [<Recipe: Rum and Tonic>]>
Итак, вот мой вопрос: почему объект Q, который И выполняет два запроса, отличается от сцепленных фильтров одного и того же объекта?
Я прочитал " Сложные поиски с объектами Q " в документации Django, и, похоже, это не помогло.
Просто для справки, вот мои фильтры в Filters.py.
Версия этой команды «ИЛИ» работает правильно:
class RecipeFilterSet(FilterSet):
ingredients_inclusive = django_filters.CharFilter(method='filter_by_ingredients_inclusive')
ingredients_exclusive = django_filters.CharFilter(method='filter_by_ingredients_exclusive')
def filter_by_ingredients_inclusive(self, queryset, name, value):
ingredients = value.split(',')
q_object = Q()
for ingredient in ingredients:
q_object |= Q(ingredients__ingredient_type=ingredient)
return queryset.filter(q_object).distinct()
def filter_by_ingredients_exclusive(self, queryset, name, value):
ingredients = value.split(',')
q_object = Q()
for ingredient in ingredients:
q_object &= Q(ingredients__ingredient_type=ingredient)
return queryset.filter(q_object).distinct()
class Meta:
model = Recipe
fields = ()
Я также включил мои модели ниже:
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models
class IngredientType(models.Model):
name = models.CharField(max_length=256)
CATEGORY_CHOICES = (
('LIQUOR', 'Liquor'),
('SYRUP', 'Syrup'),
('MIXER', 'Mixer'),
)
category = models.CharField(
max_length=128, choices=CATEGORY_CHOICES, default='MIXER')
def __str__(self):
return self.name
class Recipe(models.Model):
name = models.CharField(max_length=256)
def __str__(self):
return self.name
class RecipeIngredient(models.Model):
ingredient_type = models.ForeignKey(IngredientType, on_delete=models.CASCADE, related_name="ingredients")
quantity = models.IntegerField(default=0)
quantity_type = models.CharField(max_length=256)
recipe = models.ForeignKey(Recipe, on_delete=models.CASCADE, related_name="ingredients")
@property
def ingredient_type_name(self):
return self.ingredient_type.name
@property
def ingredient_type_category(self):
return self.ingredient_type.category
def __str__(self):
return f'{self.quantity}{self.quantity_type} of {self.ingredient_type}'
Любая помощь будет принята с благодарностью!