Набор запросов фильтрации Django JSONField

Для проекта я использую Python 3.6.3, Django 2.0 и Postgre 9.4. В моем билете класса есть пассажир 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, в которой я хочу отфильтровать билеты, у которых мобильный телефон не равен нулю или None, а sms_sent имеет значение False.

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

Теперь фильтр пассажира__sms_sent = False работает и выдает мои единственные билеты с sms_sent = False. Но фильтр "пассажир_мобильный" не работает. Я пробовал все это:

    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=''))

а также добавление пассажира__mobile в первый фильтр, но я не могу отфильтровать (исключить) билеты, в которых пассажир__mobile имеет значение null, я либо получаю все билеты, либо пустой набор запросов.

Теперь я могу это сделать:

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

но я не это ищу. Я хочу использовать фильтр или исключить, чтобы получить эти билеты. Что я делаю не так? P.S. not_cancelled () - мой менеджер, и он не имеет ничего общего с полем пассажира.

Вы уверены, что в базе данных есть записи с нулевыми значениями? blank=True допускает пустые значения в форме, но я считаю, что вам также понадобится null = True, чтобы разрешить нули через django.

Alan 21.04.2018 15:15

@Alan Дело в том, что моя модель была alredy blank = True, null = True, и в этом случае нет разницы, она все еще не работала, поэтому я изменил ее на blank = True, чтобы она не работала разрешить null и None. А в БД это "мобильный": null

Irfan Dzankovic 21.04.2018 15:41
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
7
2
5 274
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 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

предупредить что

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.

и вот они https://docs.djangoproject.com/en/2.0/ref/contrib/postgres/fields/#containment-and-key-operations

Дело в том, что если я вас понимаю, filter (пассажира__mobile = None) будет работать, но в моем случае это не так. Он дает мне оба билета (третий уже отфильтрован sms_sent = True). Он дает мне билет, где "mobile": null и "mobile": '"21312".

Irfan Dzankovic 21.04.2018 15:53

Итак, в Django 2.1 это будет возможно, но сейчас я могу справиться, если ticket.passenger ['mobile'] не равен None:

Irfan Dzankovic 21.04.2018 16:14

Другие вопросы по теме