Для проекта я использую 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 () - мой менеджер, и он не имеет ничего общего с полем пассажира.
@Alan Дело в том, что моя модель была alredy blank = True, null = True, и в этом случае нет разницы, она все еще не работала, поэтому я изменил ее на blank = True, чтобы она не работала разрешить null и None. А в БД это "мобильный": null






Согласно этому 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".
Итак, в Django 2.1 это будет возможно, но сейчас я могу справиться, если ticket.passenger ['mobile'] не равен None:
Вы уверены, что в базе данных есть записи с нулевыми значениями?
blank=Trueдопускает пустые значения в форме, но я считаю, что вам также понадобитсяnull = True, чтобы разрешить нули через django.