如何在 Django 中使用条件表达式查询数据库?
How to query database with conditional expression in Django?
我有三个模型:Business、Offers 和 OfferPlan:
企业:
class Business(models.Model):
name_of_business = models.CharField(max_length=255)
优惠:
class Offers(models.Model):
business = models.ForeignKey(Business, related_name="business_offer",
on_delete=models.CASCADE)
title = models.CharField(max_length=255)
subtext = models.CharField(max_length=255)
优惠计划:
class OfferPlan(models.Model):
WEEKDAYS = [
(1, _("Monday")),
(2, _("Tuesday")),
(3, _("Wednesday")),
(4, _("Thursday")),
(5, _("Friday")),
(6, _("Saturday")),
(7, _("Sunday")),
]
offer = models.ForeignKey(Offers, related_name="business_offer_plan",
on_delete=models.CASCADE)
weekday = models.IntegerField(
choices=WEEKDAYS,
)
from_hour = models.TimeField()
to_hour = models.TimeField()
我有一个 ListView,它根据不同的参数(例如城市、类别等)搜索营业的商家。我现在还想按工作日搜索,说哪些商家周一营业,哪些不营业当天显示。工作日信息存储在 OfferPlan 中,OfferPlan table 中当天的报价可能有多个时间安排,但我想查询(过滤、排除)在该工作日编号上什至只有一个条目的企业。
这是我的 ListView:
class SearchListView(ListView):
template_name = 'search/search.html'
model = Business
def get_queryset(self):
# queryset = Business.objects.filter(business_address__city=AppLocations.objects.first().city)
if 'city' in self.request.GET:
queryset = Business.objects.filter(business_address__city=self.request.GET.get('city'))
if 'category' in self.request.GET:
queryset = queryset.filter(category__code=self.request.GET.get('category'))
# if 'date' not in self.request.GET:
# queryset = B
raise
return queryset
这怎么可能?还查看了 https://docs.djangoproject.com/en/1.8/ref/models/conditional-expressions/ 但无法弄清楚。
谢谢
更新 1
在网络上进行了更多研究后,我发现这是如何实现的,但需要从这里的其他 Django 爱好者那里确定它是正确的。
queryset.filter(business_offer__business_offer_plan__weekday=1).annotate(count_entry=Count('business_offer__business_offer_plan__weekday')).filter(count_entry__gt=1)
解决方案
Jefferson 的解决方案被标记为正确答案,因为它提供了更多见解,关于哪个查询更快以及我之前的更新有什么问题,所以这是我们都同意的正确解决方案:
queryset.filter(business_offer__business_offer_plan__weekday=1).annotate(count_entry=Count('business_offer__business_offer_plan__weekday')).filter(count_entry__gte=1)
这里没有条件表达式 - 你的注释太复杂了。你只需要一个额外的过滤器。
queryset.filter(business_offer__business_offer_plan__weekday=self.request.GET['weekday'])
def get_query(weekday):
businesses = Business.objects.filter(business_offer__in=Offers.objects.filter(
business_offer_plan__in=OfferPlan.objects.filter(weekday=weekday))).distinct()
return businesses
有一个繁重的查询,但它有效。
我有三个模型:Business、Offers 和 OfferPlan: 企业:
class Business(models.Model):
name_of_business = models.CharField(max_length=255)
优惠:
class Offers(models.Model):
business = models.ForeignKey(Business, related_name="business_offer",
on_delete=models.CASCADE)
title = models.CharField(max_length=255)
subtext = models.CharField(max_length=255)
优惠计划:
class OfferPlan(models.Model):
WEEKDAYS = [
(1, _("Monday")),
(2, _("Tuesday")),
(3, _("Wednesday")),
(4, _("Thursday")),
(5, _("Friday")),
(6, _("Saturday")),
(7, _("Sunday")),
]
offer = models.ForeignKey(Offers, related_name="business_offer_plan",
on_delete=models.CASCADE)
weekday = models.IntegerField(
choices=WEEKDAYS,
)
from_hour = models.TimeField()
to_hour = models.TimeField()
我有一个 ListView,它根据不同的参数(例如城市、类别等)搜索营业的商家。我现在还想按工作日搜索,说哪些商家周一营业,哪些不营业当天显示。工作日信息存储在 OfferPlan 中,OfferPlan table 中当天的报价可能有多个时间安排,但我想查询(过滤、排除)在该工作日编号上什至只有一个条目的企业。
这是我的 ListView:
class SearchListView(ListView):
template_name = 'search/search.html'
model = Business
def get_queryset(self):
# queryset = Business.objects.filter(business_address__city=AppLocations.objects.first().city)
if 'city' in self.request.GET:
queryset = Business.objects.filter(business_address__city=self.request.GET.get('city'))
if 'category' in self.request.GET:
queryset = queryset.filter(category__code=self.request.GET.get('category'))
# if 'date' not in self.request.GET:
# queryset = B
raise
return queryset
这怎么可能?还查看了 https://docs.djangoproject.com/en/1.8/ref/models/conditional-expressions/ 但无法弄清楚。
谢谢
更新 1
在网络上进行了更多研究后,我发现这是如何实现的,但需要从这里的其他 Django 爱好者那里确定它是正确的。
queryset.filter(business_offer__business_offer_plan__weekday=1).annotate(count_entry=Count('business_offer__business_offer_plan__weekday')).filter(count_entry__gt=1)
解决方案
Jefferson 的解决方案被标记为正确答案,因为它提供了更多见解,关于哪个查询更快以及我之前的更新有什么问题,所以这是我们都同意的正确解决方案:
queryset.filter(business_offer__business_offer_plan__weekday=1).annotate(count_entry=Count('business_offer__business_offer_plan__weekday')).filter(count_entry__gte=1)
这里没有条件表达式 - 你的注释太复杂了。你只需要一个额外的过滤器。
queryset.filter(business_offer__business_offer_plan__weekday=self.request.GET['weekday'])
def get_query(weekday):
businesses = Business.objects.filter(business_offer__in=Offers.objects.filter(
business_offer_plan__in=OfferPlan.objects.filter(weekday=weekday))).distinct()
return businesses
有一个繁重的查询,但它有效。