【问题标题】:Django JSONField filtering QuerysetDjango JSONField 过滤查询集
【发布时间】:2018-10-02 00:18:43
【问题描述】:

对于项目,我使用的是 Python 3.6.3、Django 2.0 和 Postgre 9.4。 在我的班级 Ticket 中,有一个 JSONField 乘客

    passenger = JSONField(blank=True)

我的乘客 JSON 看起来像这样:

{
    "email": null, 
    "mobile": "21312", 
    "passport": "2141241", 
    "sms_sent": false, 
    "full_name": "something"
},
{
    "email": null, 
    "mobile": null, 
    "passport": "1231231", 
    "sms_sent": false, 
    "full_name": "Irfan"
},
{
    "email": null, 
    "mobile": null, 
    "passport": "1231231", 
    "sms_sent": true, 
    "full_name": "Irfan"
}

现在我有 django 命令,我想在其中过滤具有不为 null 或 None 的移动设备的票证,并且 sms_sent 为 False。

    tickets = Ticket.objects.filter(
        date=tomorrow, trip__bus_company=bus_company,
        passenger__sms_sent=False
    ).not_cancelled()

现在,passenger__sms_sent=False 过滤器正在工作,并且正在提供我唯一的带有 sms_sent=False 的票。但是passenger__mobile 过滤器不起作用。 我尝试了所有这些:

    tickets = tickets.exclude(passenger__mobile=None)
    tickets = tickets.exclude(passenger__mobile=None).exclude(passenger__mobile='')
    tickets = tickets.exclude(passenger__mobile__isnull=True)
    tickets = tickets.exclude(passenger__exact={'mobile': None})
    tickets = tickets.exclude(passenger__mobile__isnull=True).exclude(passenger__mobile='')
    tickets = tickets.exclude(passenger__mobile__isnull=False).exclude(passenger__mobile='')
    tickets = tickets.exclude(Q(passenger__mobile__isnull=True) | Q(passenger__mobile=''))

并且还将passenger__mobile放在第一个过滤器中,但我无法过滤掉(排除)passenger__mobile为空的票,我要么得到所有票,要么空查询集。

现在我可以这样做了:

for ticket in tickets:
            if ticket.passenger['mobile'] is not None:
                print(ticket.passenger['mobile'])

但这不是我想要的。我想使用过滤器或排除来获取这些票。我做错了什么? 附: not_cancelled() 是我的经理,它与乘客字段没有任何关系。

【问题讨论】:

  • 你确定数据库中有空值的记录吗? blank=True 将允许表单中的空值,但我相信您还需要 null = True 以允许通过 django 使用空值。
  • @Alan 问题是我的模型已经是空白=True,null=True,在这种情况下没有区别,它仍然不起作用,所以我将它改为只有空白=是的,所以它不会允许 null 和 None。在 db 中它是 "mobile": null

标签: python django postgresql


【解决方案1】:

根据https://code.djangoproject.com/ticket/25718(请参阅最后的结束评论),以下内容应该可以工作model.objects.filter(field__key=None)(但显然您应该使用带有修复程序的 Django 版本)。

django 文档https://docs.djangoproject.com/en/2.0/ref/contrib/postgres/fields/#querying-jsonfield

警告

由于任何字符串都可以是 JSON 对象中的键,因此任何查找其他 比下面列出的那些将被解释为键查找。没有错误 被提出。输入错误要格外小心,并经常检查 您的查询按您的意愿工作。

他们是https://docs.djangoproject.com/en/2.0/ref/contrib/postgres/fields/#containment-and-key-operations

【讨论】:

  • 问题是,如果我理解你的话, filter(passenger__mobile=None) 会起作用,但在我的情况下它不会。它给了我两张票(第三张已经被 sms_sent=True 过滤掉了)。它给了我票,其中“mobile”:null,“mobile”:'“21312”。
  • 好的,所以在 Django 2.1 中这是可能的,但是现在,如果 ticket.passenger['mobile'] 不是 None,我可以管理:
猜你喜欢
  • 2020-10-08
  • 2019-07-12
  • 2016-07-23
  • 2020-08-22
  • 2019-04-15
  • 2011-09-29
相关资源
最近更新 更多