【问题标题】:How to ignore or skip null values of table when filtering in Django?在 Django 中过滤时如何忽略或跳过表的空值?
【发布时间】:2021-01-01 17:19:03
【问题描述】:

当该子句的数据在数据库中为空时,我想忽略或跳过该过滤子句,在我的情况下,有时 digital_exp_score 变量为空,但我需要按该变量进行过滤,正常的过滤器是这样的:

review = Review.objects.get(id=review_id)
offers = OfferGeneric.objects.filter(
                is_personalized=True,
                digital_exp_score__gte=review.digital
)

但是当 digital_exp_score 为 Null 时它不起作用,我想忽略这些情况并通过那个条件,我该怎么做?

我尝试过使用 When 子句:

offers = OfferGeneric.objects.filter(
                is_personalized=True,
                When(digital_exp_score__isnull=False ,
                     then=(digital_exp_score__gte=review.digital)
                     ),
)

offers = OfferGeneric.objects.filter(
                is_personalized=True,
                digital_exp_score__gte=When(
                    digital_exp_score__isnull=False,
                    then=review.digital
                ),
)

但两者都不起作用,我得到语法错误,这些方法仅适用于条件右侧的值?有什么方法可以检查条件左侧的值(数据库值)吗?

这样的事情会很理想:

offers = OfferGeneric.objects.filter(
                is_personalized=True,
                digital_exp_score__gte=review.digital if digital_exp_score is not None else pass
)
    

【问题讨论】:

  • 所以如果digital_exp_scoreNULL,你不想检查digital_exp_score。如果不为null,是否要在查询集中保留该对象?
  • 是的,就是这样,有可能吗?

标签: python django datatable filtering isnull


【解决方案1】:

您可以使用Q objects [Django-doc] 对析取进行编码。 a → b 的逻辑等价是 ¬ a ∨ b

from django.db.models import Q

review = Review.objects.get(id=review_id)

offers = OfferGeneric.objects.filter(
    Q(digital_exp_score=None) |
    Q(digital_exp_score__gte=review.digital),
    is_personalized=True,
)

或者我们可以简单地过滤掉digital_exp_score不小于review.digital. Django will then automatically include NULL`本身的对象:

from django.db.models import Q

review = Review.objects.get(id=review_id)

offers = OfferGeneric.objects.filter(
    ~Q(digital_exp_score__lt=review.digital),
    is_personalized=True,
)

这里的波浪号 (~) 是条件的否定

【讨论】:

  • 谢谢!这完美!并且是一个很好的解释,反转查询非常有用!最后一个问题,在过滤器中,| 是 OR 对吗?所以每个“,”逗号都是 AND?所以我可以用& 代替逗号?
  • @OOSS:如果你使用Q对象,你可以使用&,如果我们使用命名参数,就像最后一个一样,你不能使用&(或@987654333) @),因为这正是 Python 解析参数的方式。但在内部.filter(..) 确实会创建Q 对象,执行& 逻辑来构造一个对象,然后将该Q 对象转换为它正在构建的SQL 查询的一部分。
【解决方案2】:

我觉得这样就可以了

OfferGeneric.objects.exclude(digital_exp_score__isnull=true) \
                    .filter(is_personalized=Treu,digitial_score__gte=review.digital)

虽然我想它会与你的其他查询一起工作......因为我认为 NULL 不会通过大于测试......也许我误解了你想要做的事情

根据您的评论,正确的查询是

from django.models import Q
OfferGeneric.objects.filter(Q(OfferGeneric.digital_score__gte=review.digital) | 
                            Q(OfferGeneric.digital_score__isnull=True)).all()

【讨论】:

  • 不,它不会起作用,因为它将排除所有具有 digital_exp_score 为 Null 的报价,我想要的是获得满足此条件的所有报价 digitial_exp_score__gte=review.digital,但是当 digital_exp_score 为 Null我只想跳过该过滤器,这样我也可以获得该字段为空的报价。那我该怎么做呢?
  • 是的,它现在可以这样工作,但为什么最后是.all()
  • 我猜你不需要它......这只是习惯
猜你喜欢
  • 1970-01-01
  • 2017-08-31
  • 2020-05-18
  • 2017-11-03
  • 1970-01-01
  • 1970-01-01
  • 2016-04-21
  • 2018-06-16
  • 1970-01-01
相关资源
最近更新 更多