Фильтрация данных
В этой статье мы будем работать с моделями данных. Если вам не знаком этот термин, обратитесь к этой статье.
Итак, допустим, у вас есть модель Post, которая описывает статью в блоге:
from django.db import models
class Post(models.Model):
title = models.CharField(max_length=200)
text = models.TextField()
is_deleted = models.BooleanField()
is_published = models.BooleanField()
У модели есть 2 интересных поля: is_deleted и is_published. Эти поля хранят 2 вида значений: либо True, либо False.
Фильтрация
На главной странице блога обычно показывают все опубликованные статьи. То есть не все, а те, у которых is_published == True. Вот так можно получить их список:
posts = Post.objects.all()
published_posts = []
for post in posts:
if post.is_published:
published_posts.append(post)
Здесь мы достаём все посты из БД, а затем выбираем из них опубликованные.
Оказывается, в Django ORM можно сразу попросить прислать только опубликованные посты:
published_posts = Post.objects.filter(is_published=True)
is_published — это название поля из модели данных Post. В filter можно указать название любого поля, из тех, что есть у модели данных:
deleted_posts = Post.objects.filter(is_deleted=True)
non_published_posts = Post.objects.filter(is_published=False)
non_deleted_posts = Post.objects.filter(is_deleted=False)
Если подходящие объекты не найдутся, вам вернётся пустой QuerySet. Он ведёт себя как пустой список.
Фильтрация по нескольким полям
Кажется, мы совсем забыли про поле is_deleted. Если пост удалён, то его не нужно показывать на главной. Получается, нужно показать опубликованные посты и скрыть все удалённые. Можно сделать это так:
posts_to_show = Post.objects.filter(is_published=True, is_deleted=False)
filter умеет комбинировать несколько условий
Операции сравнения
Если пользователь ищет на вашем сайте статьи со словом "питон", то привычный способ фильтрации вам не поможет:
search_phrase = "питон"
searched_posts = Post.objects.filter(title="питон")
Здесь база данных будет искать посты, у которых заголовок в точности равен строке "питон". А нам нужны статьи со словом "питон" в заголовке:
Питон для новичков
Джаваскрипт vs Питон
Питон в естественной среде обитания
Поможет операция сравнения contains. Она позволит вам проверить, что заголовок содержит строку "питон":
searched_posts = Post.objects.filter(title__contains="питон")
Все операции сравнения начинаются с двух подчёркиваний и прямо “приписываются” к полям. Есть и другие операции сравнения, например, __gt и __lt:
__gt — (greater then, в переводе, “больше чем”) проверяет, что поле больше, чем то, что передадут справа. Пример: filter(likes__gt=10) — фильтруем посты, у которых больше 10 лайков.
__lt — (less then, "меньше чем) аналогично, проверяет, что поле меньше.
Чтобы проверить условие “больше или равно”, есть операция сравнения __gte, а “меньше ли равно” — __lte.
Операции сравнения — фича Django ORM
Операции сравнения с двумя подчёкиваниями работают только в методах filter, exclude и get из Django ORM и нигде больше. Не пытайтесь использовать это в работе с другими библиотеками и функциями, они не поймут.