【问题标题】:How to query database with conditional expression in Django?如何在 Django 中使用条件表达式查询数据库?
【发布时间】:2018-02-12 10:20:16
【问题描述】:

我有三个模型: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 表中当天的报价可能有多个计时,但我想查询(过滤、排除)在该工作日编号上什至只有一个条目的企业。

这是我的列表视图:

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)

【问题讨论】:

    标签: django django-models django-queryset django-1.8


    【解决方案1】:
    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
    

    有一个繁重的查询,但它有效。

    【讨论】:

    • 谢谢,但请查看我的update 1 并告诉我这是否也是一个好方法?
    • @Maverick 是的,我和你的查询错误:D 在您的查询修复中:最后一个过滤器应该是“filter(count_entry__gte=1)”
    • @Maverick 修复了我的查询(只是忘记在末尾添加“distinct”)。
    • 我的即使不添加gte也可以工作,因为我只是在寻找大于1,大于等于没关系,怎么说? :)
    • @Maverick 如果企业今天有 1 个报价计划,它将不在查询结果中
    【解决方案2】:

    这里没有条件表达式 - 您的注释太复杂了。你只需要一个额外的过滤器。

    queryset.filter(business_offer__business_offer_plan__weekday=self.request.GET['weekday'])
    

    【讨论】:

    • 谢谢,但这不会按预期工作,除非你这样称呼它,queryset.filter(business_offer__business_offer_plan__weekday=self.request.GET['weekday']).distinct(),否则它将返回同一业务和优惠的多个实例。
    猜你喜欢
    • 2016-11-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-27
    • 1970-01-01
    • 1970-01-01
    • 2017-07-07
    • 1970-01-01
    相关资源
    最近更新 更多