order_by()
Чтобы переопределить порядок сортировки по умолчанию, вы используете order_by() метод QuerySet. В следующем примере используется метод order_by() для сортировки сотрудников по имени, в порядке возрастания:
Worker.objects.order_by('first_name')
Вы также можете использовать метод order_by() для сортировки сотрудников по имени, в порядке убывания:
Worker.objects.order_by('-first_name')
Также метод order_by() позволяет сортировать результаты по нескольким полям. Например, в следующем примере используется метод order_by() для сортировки сотрудников по имени и фамилии:
Worker.objects.order_by('first_name','last_name')
Чтобы отсортировать случайным образом, вы можете использовать вопросительный знак ?:
Worker.objects.order_by('?')
Метод order_by('?') с параметром случайной сортировки может быть медленным и ресурсозатратным, в зависимости от используемой базы данных.
values()и values_list()
В SQL мы можем использовать SELECT операторы, чтобы определить, какие поля возвращаются запросом. В Django мы можем эмулировать это, используя методы .values() или .values_list().
Оба позволят вам контролировать, какие поля выбираются запросом, метод .values вернет QuerySet словарей, а метод .values_list вернет QuerySet кортежей.
>>> Worker.objects.filter(id=1).values()
<QuerySet [{'id': 1, 'first_name': 'Roger', 'last_name': 'Campbell', 'age': 25, 'created': datetime.datetime(2023, 11, 14, 5, 37, 28, 711550, tzinfo=datetime.timezone.utc), 'work_experience': 5}]>
>>> Worker.objects.filter(id=1).values_list()
<QuerySet [(1, 'Roger', 'Campbell', 25, datetime.datetime(2023, 11, 14, 5, 37, 28, 711550, tzinfo=datetime.timezone.utc), 5)]>
Также вы можете указать, какие поля хотите вернуть:
>>> Worker.objects.filter(last_name='Medina').values_list('first_name', 'last_name')
<QuerySet [('Ryan', 'Medina')]>
dates() и datetimes()
Методы dates() и datetimes() позволяют возвращать из базы данных привязанные к времени записи (например, все события, происходящие в конкретном месяце). Для метода dates() это ограничения времени по году, месяцу, неделе и дню. Для метода datetimes() добавляются ещё и ограничения по часам, минутам и секундам. Например:
>>> Worker.objects.dates('created', 'day')
<QuerySet [datetime.date(2023, 11, 14)]>
defer()
Если в вашей модели Django есть поля, содержащие много данных, и вам не нужны эти поля для определенного запроса, вы можете указать Django не извлекать их с помощью метода defer(). Попробуем вывести первого работника и посмотреть его содержание:
>>> w = Worker.objects.get(id=1)
>>> w.__dict__
Мы видим что у него есть поле 'created'. Попробуем извлечь первого работника используя метод defer чтобы не выводить их дату создания:
w = Worker.objects.defer('created').get(id=1)
w.__dict__
То как мы видим, данное поле не было выведено.
only()
Является противоположностью метода defer() - возвращает только поля, предоставленные в качестве аргументов:
w = Worker.objects.only('first_name', 'last_name').get(id=1)
w.__dict__
Это далеко не все методы по Django ORM, но эти методы самые основные. Очень важно понимать как они работают. Основное преимущество методов которые возвращают QuerySet это их ленивость, тоесть мы можем писать стопку этих запросов, но выполнятся они в самом конце.
>>> w = Worker.objects.filter(first_name='Michael').filter(last_name='Smith').exclude(work_experience=5)
>>> print(w.query)
SELECT "orm_method_worker"."id",
"orm_method_worker"."first_name",
"orm_method_worker"."last_name",
"orm_method_worker"."age",
"orm_method_worker"."created",
"orm_method_worker"."work_experience"
FROM "orm_method_worker"
WHERE ("orm_method_worker"."first_name" = Michael
AND "orm_method_worker"."last_name" = Smith
AND NOT ("orm_method_worker"."work_experience" = 5))
Или так:
>>> a = Worker.objects.filter(first_name='Michael')
>>> b = a.filter(last_name='Smith')
>>> c = b.exclude(work_experience=5)
>>> print(c.query)
SELECT "orm_method_worker"."id",
"orm_method_worker"."first_name",
"orm_method_worker"."last_name",
"orm_method_worker"."age",
"orm_method_worker"."created",
"orm_method_worker"."work_experience"
FROM "orm_method_worker"
WHERE ("orm_method_worker"."first_name" = Michael
AND "orm_method_worker"."last_name" = Smith
AND NOT ("orm_method_worker"."work_experience" = 5))
Для QuerySet можно объединить несколько фильтров, но они не коснутся базы данных, до тех пор пока QuerySet не будет выполнен. А он исполняется в следующих условиях:
- При первой итерации по QuerySet.
- При получении среза, например
Worker.objects.all()[:3]. - При сериализации или кэшировании объектов.
- При вызове
repr()илиlen(). - При прямом вызове
list(). - При проверке QuerySet в других выражениях, например
bool(),or,andилиif.