Как применить поиск в запросе фильтра django в соответствии с условиями?
Я хочу сделать запрос, в котором я могу применять поиск только при выполнении некоторых условий. например
Покупатель может выбрать только ту еду из киоска, за которую он заплатил
class Customer(models.Model):
food_type = models.CharField()
fruit_id = models.ForeignKey(Fruit, null=True)
vegetable_id = models.ForeignKey(Vegetable, null=True)
is_paid = models.BooleanField()
class Food(models.Model):
fruit_id = models.ForeignKey(Fruit, null=True)
vegetable_id = models.ForeignKey(Vegetable, null=True)
Итак, мне нужно сделать что-то вроде:
q = Food.objects.all()
if Customer.objects.filter(id=(id of customer), food_type='fruit', is_paid=True).exists():
q = q.filter(fruit_id__in=Customer.objects.filter(id=(id of customer), food_type='fruit', is_paid=True).values_list('fruit_id', flat=True))
if Customer.objects.filter(id=(id of customer), food_type='vegetable', is_paid=True).exists():
q = q.filter(vegetable_id__in=Customer.objects.filter(id=(id of customer), food_type='vegetable', is_paid=True).values_list('vegetable_id', flat=True))
Как я могу оптимизировать это, поскольку это небольшой пример, в моем случае есть гораздо больше условий. Я хочу уменьшить количество обращений к базе данных. Также есть ли способ использовать здесь условные выражения? Например, When()
Любая помощь будет оценена по достоинству.
Вы можете использовать Q.
from django.db.models import Q
q = Food.objects.all()
q = q.filter(
Q(
vegetable_id__in=Customer.objects.filter(id=(id of customer), food_type='vegetable', is_paid=True).values_list('vegetable_id', flat=True)
)|Q(
fruit_id__in=Customer.objects.filter(id=(id of customer), food_type='fruit', is_paid=True).values_list('fruit_id', flat=True)
)
)
Причина сложности заключается в структуре ваших моделей - у вас клиент связан с фруктами и/или овощами, а продукты питания также связаны с фруктами/овощами, поэтому клиент и продукты питания потенциально связаны только через фрукты/овощи - очень запутанно и долго.
Это также объясняет, почему у вас есть 'food_type' в модели Customer, чтобы попытаться компенсировать это. Я бы предложил гораздо более простую структуру, но с одной дополнительной моделью:
class Customer(models.Model):
food = models.ManyToManyField(Food, ... # customer can have many Food
is_paid = models.BooleanField()
# create a new food type model that stores Fruit, Vegetable, etc.
class FoodType(models.Model):
name = models.CharField(...
class Food(models.Model):
# food now connects to the food type
food_type = models.ForeignKey(FoodType, ...
Теперь вы можете делать свои запросы гораздо более краткими:
# get food that the customer has paid for
Food.objects.filter(customer__is_paid=True)
# get fruit that the customer has paid for
Food.objects.filter(customer__is_paid=True, food_type__name="Fruit")