Django 通过匹配布尔值进行条件查询

Posted

技术标签:

【中文标题】Django 通过匹配布尔值进行条件查询【英文标题】:Django conditional query by matching boolean values 【发布时间】:2017-01-28 09:23:50 【问题描述】:

我知道有几种方法可以实现,即 if/else 查询集、条件查询集、Q、聚合等。我基于这些提出了一些选项,但想知道最佳方法和建议.

Sudo 代码在我想要实现的目标下方。应用程序将传递布尔值的查询字符串,如下所示,即 True 或 False,如果一个用户根据查询字符串值和数据库数据有更多匹配项,则他们的排序将高于其他用户。

SELECT * from userdetails

    if sun_morn is true then match_count++
    if sun_day is true then match_count++
    if sun_afternoon is true then match_count++
    if sun_afternoon is true then match_count++

order_by match_count LIMIT by 10;

结果是显示匹配任何一个布尔值的所有用户,然后将匹配最多的用户排序在查询集的顶部。

在@Aison 代码的帮助下,关闭但无法正常工作:

    """ /endpoint?sunmorn=1&sunday=0&sunafternoon=0&sunnight=1&monmorn=1&monday=0&monafternoon=0&monnight=1
    &tuesmorn=1&tuesday=0&tuesafternoon=0&tuesnight=1&wedmorn=1&wedday=0&wedafternoon=0&wednight=1
    &thursmorn=1&thursday=0&thursafternoon=0&thursnight=1&frimorn=1&friday=0&friafternoon=0&frinight=1
    &satmorn=1&satday=0&satafternoon=0&satnight=1 """
    queryset = queryset.aggregate(match_count=Sum(
        Case(When(sun_morn | sun_day | sun_afternoon | sun_night,
                  then=1), output_field=IntegerField())
    ),
    )

models.py

from django.conf import settings
from django.db import models

class userdetail(models.Model):
    username = models.OneToOneField(settings.AUTH_USER_MODEL)
    # removed extra fields as not needed for example
    sun_morn = models.BooleanField(default=False, null=False, blank=False)
    sun_day = models.BooleanField(default=False, null=False, blank=False)
    sun_afternoon = models.BooleanField(default=False, null=False, blank=False)
    sun_night = models.BooleanField(default=False, null=False, blank=False)
    mon_morn = models.BooleanField(default=False, null=False, blank=False)
    mon_day = models.BooleanField(default=False, null=False, blank=False)
    mon_afternoon = models.BooleanField(default=False, null=False, blank=False)
    mon_night = models.BooleanField(default=False, null=False, blank=False)
    tues_morn = models.BooleanField(default=False, null=False, blank=False)
    tues_day = models.BooleanField(default=False, null=False, blank=False)
    tues_afternoon = models.BooleanField(default=False, null=False, blank=False)
    tues_night = models.BooleanField(default=False, null=False, blank=False)
    wed_morn = models.BooleanField(default=False, null=False, blank=False)
    wed_day = models.BooleanField(default=False, null=False, blank=False)
    wed_afternoon = models.BooleanField(default=False, null=False, blank=False)
    wed_night = models.BooleanField(default=False, null=False, blank=False)
    thurs_morn = models.BooleanField(default=False, null=False, blank=False)
    thurs_day = models.BooleanField(default=False, null=False, blank=False)
    thurs_afternoon = models.BooleanField(default=False, null=False, blank=False)
    thurs_night = models.BooleanField(default=False, null=False, blank=False)
    fri_morn = models.BooleanField(default=False, null=False, blank=False)
    fri_day = models.BooleanField(default=False, null=False, blank=False)
    fri_afternoon = models.BooleanField(default=False, null=False, blank=False)
    fri_night = models.BooleanField(default=False, null=False, blank=False)
    sat_morn = models.BooleanField(default=False, null=False, blank=False)
    sat_day = models.BooleanField(default=False, null=False, blank=False)
    sat_afternoon = models.BooleanField(default=False, null=False, blank=False)
    sat_night = models.BooleanField(default=False, null=False, blank=False)

    def __unicode__(self):
        return u'%s' % self.username

【问题讨论】:

还有你的问题吗? 【参考方案1】:

你需要的是Conditional aggregation

userdetails.objects.aggregate(
    match_count =Sum(
        Case(When(sun_morn | sun_day | sun_afternoon | sun_afternoon,
            then=1),output_field=IntegerField())
    ),
)

编辑

如果你在字段中存储 unicode 或 str,你可以使用:

userdetail.objects.aggregate(
    match_count=Sum(
        Case(
            When(sun_morn=True, then=1),
            When(sun_day=True, then=1), 
            When(sun_afternoon=True, then=1),
            output_field=IntegerField())))

userdetail.objects.aggregate(
    match_count=Sum(
        Case(When(
            Q(sun_morn=True) | Q(sun_day=True) | 
            Q(sun_afternoon=True), then=1),              
            output_field=IntegerField())))

【讨论】:

感谢 Aison,看起来不错,但我看到一个错误:|: 'unicode' and 'unicode' 的操作数类型不受支持 感谢 Windsor,但我现在看到错误:__init__() 将 Q 对象或查找作为关键字参数 感谢 Windsooon,现在我看到错误:'bool' 对象不可迭代 如果我查询数据库字段,我也会收到错误:unhashable type 请参阅上面的更多编辑。 请添加你的model.py

以上是关于Django 通过匹配布尔值进行条件查询的主要内容,如果未能解决你的问题,请参考以下文章

使用 ComboBox 作为查询条件 - 布尔值

Elasticsearch (DSL 布尔查询 过滤器 排序 高亮显示

无法将“查询”类型的值转换为预期的条件类型“布尔”

多值模糊查询报表的制作

Hive查询:根据条件选择一列,另一列值匹配某些特定值,然后将匹配结果创建为新列

朋友,您好,我想问Django分页后查询条件丢失的问题