Reputation: 81
For project I'm using Python 3.6.3, Django 2.0 and Postgre 9.4. In my class Ticket, a have JSONField passenger
passenger = JSONField(blank=True)
and my passenger JSON looks like this:
{
"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"
}
Now I have django command where I want to filter tickets that have mobile that is not null or None, and sms_sent is False.
tickets = Ticket.objects.filter(
date=tomorrow, trip__bus_company=bus_company,
passenger__sms_sent=False
).not_cancelled()
Now passenger__sms_sent=False filter is working, and is giving my only Tickets with sms_sent=False. But passenger__mobile filter is not working. I tried everyone of this:
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=''))
and also puting passenger__mobile in first filter, but I can not filter out(exclude) tickets where passenger__mobile is null, I either get all tickets, or empty queryset.
Now I can do this:
for ticket in tickets:
if ticket.passenger['mobile'] is not None:
print(ticket.passenger['mobile'])
but that is not what I'm looking for. I want to use filter or exclude to get those tickets. What I'm I doing wrong? P.S. not_cancelled() is my manager and it does not have anything to do with passenger field.
Upvotes: 8
Views: 11958
Reputation: 6173
According to this https://code.djangoproject.com/ticket/25718 (see the last, closing comment) the following should work model.objects.filter(field__key=None)
(But obviously you should use the Django version with the fix).
The django docs https://docs.djangoproject.com/en/2.0/ref/contrib/postgres/fields/#querying-jsonfield
warn that
Since any string could be a key in a JSON object, any lookup other than those listed below will be interpreted as a key lookup. No errors are raised. Be extra careful for typing mistakes, and always check your queries work as you intend.
and here they are https://docs.djangoproject.com/en/2.0/ref/contrib/postgres/fields/#containment-and-key-operations
Upvotes: 9