Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django JSONField filtering Queryset

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.

like image 579
Irfan Dzankovic Avatar asked Apr 21 '18 12:04

Irfan Dzankovic


People also ask

What is Django filter queryset?

Django Filter Queryset Introduction of Django Filter Queryset When the database connectivity is been established in Django, there is always a need of extracting the needed columns alone from the database and their corresponding rows, basically, the filter query set in django model filters is used for achieving this.

What is the data structure of a jsonfield in Django?

As per the Django JSONField docs, it explains that that the data structure matches python native format, with a slightly different approach when querying. If you know the structure of the JSON, you can also filter on keys as if they were related fields: Your contains example is almost correct, but your data is in a list and requires:

Can you stack filters in a queryset?

QuerySets are lazy – the act of creating a QuerySet doesn’t involve any database activity. You can stack filters together all day long, and Django won’t actually run the query until the QuerySet is evaluated. Take a look at this example:

What is the best alternative to filters in Django?

The djangorestframework-word-filter developed as alternative to filters.SearchFilter which will search full word in text, or exact match. django-url-filter provides a safe way to filter data via human-friendly URLs.


1 Answers

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

like image 93
Bob Avatar answered Oct 13 '22 16:10

Bob