Skip to content
Permalink
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
91 lines (57 sloc) 3.31 KB

О выборке данных в Django ORM

Принцип обработки основных методов

Важное примечание по работе кеша:

  1. Выборка данных из БД кешируется.
  2. Кеш для queryset'а не устаревает и никуда не девается.
  3. Методы, изменяющие запрос (типа filter или only), возвращают новый queryset с пустым кешем.

И ещё кое-что: принцип работы описан для Django 2.0. Об этом чуть ниже.

queryset.get()

  1. Вызывает queryset.filter с переданными параметрами.
  2. Проверяет len(queryset).
  3. Возвращает первый объект из кеша.

len(queryset)

  1. Выбирает данные из БД
  2. Возвращает размер закешированных данных

Аналогичен len(list(queryset))

bool(queryset)

  1. Выбирает данные из БД
  2. Возвращает bool от закешированных данных

Аналогичен bool(list(queryset))

queryset[n]

  1. Устанавливает для запроса LIMIT n, n+1.
  2. Выбирает данные из БД.
  3. Возвращает первый объект из кеша.

queryset[start:stop:step]

  1. Устанавливает для запроса LIMIT start, stop.
  2. Выбирает данные из БД.
  3. Возвращает список объектов из кеша с примененным к ним step (list(qs)[::k.step]).

queryset.first()

  1. Если queryset не отсортирован, сортирует его по pk.
  2. Берет срез до первого элемента от queryset (queryset[:1])
  3. Возвращает первый объект из queryset'а, если он там есть, иначе -- None.

Как быстро выбрать первый элемент?

Вопрос, какзалось, простой, однако из версии к версии в Django многое менялось, и ответ сильно зависит от используемой версии.

Django 1.8 и выше

queryset.first()

Также важно отметить, что в Django срез с шагом возвращает список, а без шага -- queryset. Устанавливать LIMIT для queryset'а можно несколько раз, и это даже будет работать.

Django 1.6 и 1.7

В этой версии Django метод first работает не оптимально. Он выбирает весь queryset из БД. Поэтому сначала его нужно ограничить.

queryset[:1].first()

Django 1.5 и младше

В этой версии Django метод first отсутствует.

Через условия:

q = queryset[:1]
return q[0] if q else None

Либо через исключения:

try:
    return queryset[:1].get()
except ModelName.DoesNotExist:
    return
You can’t perform that action at this time.