Фильтровать объекты или (если найдено 0) получить все объекты в Django одним ударом по БД - PullRequest
1 голос

Есть ли способ в Django добиться следующего за один удар по БД (панель инструментов отладки показывает 2 запроса)?

q = SomeModel.objects.filter(name=name).order_by(some_field)
if q.count() == 0:
    q = SomeModel.objects.all().order_by(some_field)

Я хочу проверить, существуют ли объекты с заданным именем.Если да, то верните их.Если нет, верните все объекты.Все сделано в одном запросе.

Я проверил подзапрос, Q, условные выражения, но все еще не вижу, как вписать его в один запрос.

Ответы [ 2 ]

1 голос
/ 09 мая 2019

Хорошо, несмотря на то, что я сопротивлялся (я все еще думаю, что это преждевременная оптимизация), любопытство одолело меня. Это не красиво, но делает трюк:

from django.db.models import Q, Exists

name_qset = SomeObject.objects.filter(name=name)
q_func = Q(name_exists=True, name=name) | Q(name_exists=False)
q = SomeModel.objects.annotate(
    name_exists=Exists(name_qset)
).filter(q_func).order_by(some_field)

Попробовал и определенно только один запрос. Интересно посмотреть, действительно ли это значительно быстрее для больших наборов данных ...

0 голосов
/ 09 мая 2019

Лучше всего использовать .exists(), иначе ваш код в порядке

q = SomeModel.objects.filter(name=name).order_by(some_field)
if not q.exists():
    q = SomeModel.objects.all().order_by(some_field)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...