Запросы к БД можно делать прямо из кода Python. Для этого в Django ORM есть специальный синтаксис. Вместо того чтобы писать громоздкие запросы, информацию из БД можно получить одной строкой.
Главная страница
В файле posts/views.py
измените view-функцию index()
:
# posts/views.py
from django.http import HttpResponse
# Импортируем модель, чтобы обратиться к ней
from .models import Post
def index(request):
# Одна строка вместо тысячи слов на SQL:
# в переменную posts будет сохранена выборка из 10 объектов модели Post,
# отсортированных по полю pub_date по убыванию (от больших значений к меньшим)
posts = Post.objects.order_by('-pub_date')[:10]
# В словаре context отправляем информацию в шаблон
context = {
'posts': posts,
}
return render(request, 'posts/index.html', context)
В функции index()
переменная posts
получает выборку записей модели Post из БД. После имени модели и специальной точки входа .objects
указаны условия запроса. В запросе:
- сортируем записи по свойству
pub_date
по убыванию, от больших значений к меньшим (об этом говорит знак-
): новые записи оказываются вверху выборки; - в выборку попадут только первые 10 элементов из полученного списка.
Конструкция написана на безупречном языке Python, никакого SQL. А Django ORM переведёт этот запрос на SQL:
SELECT
'posts_post'.'id',
'posts_post'.'text',
'posts_post'.'pub_date',
'posts_post'.'author_id'
FROM
'posts_post'
ORDER BY
'posts_post'.'pub_date' DESC
LIMIT 10
Полученные записи передаются в код как объекты класса Post, сохраняются в виде списка в переменной posts
и передаются в словаре context
под ключом 'posts'
в шаблон posts/index.html
.В шаблоне список, хранящийся в переменной posts
, перебирается в цикле. На каждой итерации:
- Из каждого объекта извлекаются значения необходимых полей:
post.author.get_full_name
— в полеauthor
модели Post передан объект модели User, из него извлекается поле, содержащее имя автора;post.pub_date
— дата публикации;post.text
— полный текст поста.
- Значения полей выводятся в нужные места шаблона.
- Если обрабатывается не последняя итерация цикла (
not forloop.last
) — после вывода данных объекта будет добавлен тег<hr>
— horizontal rule, горизонтальная линия.
{% for post in posts %}
<ul>
<li>
Автор: {{ post.author.get_full_name }}
</li>
<li>
Дата публикации: {{ post.pub_date|date:"d E Y" }}
</li>
</ul>
<p>{{ post.text }}</p>
<a href="">все записи группы</a>
{% if not forloop.last %}<hr>{% endif %}
{% endfor %}
После рендеринга страница отправляется пользователю ответом на его HTTP-запрос.
Вот ещё несколько примеров, как можно получить данные из базы:
Post.objects.all()
— получить все записи модели Post.Post.objects.get(id=1)
— получить запись модели Post, у которой значение поляid
равно 1. Поскольку полеid
— это первичный ключ, а Django автоматически создаёт у модели свойствоpk
, то другой вариант этого же запроса будет таким:Post.objects.get(pk=1)
.Post.objects.filter(pub_date__year=1854)
— запрос вернёт объекты, у которых значение года в полеpub_date
равно 1854. Обратите внимание на синтаксис фильтрации: двойное нижнее подчёркивание между названиями поля и фильтра. Подробнее о функцииfilter()
— в документации.Post.objects.filter(text__startswith='Писать не хочется')
— пример фильтра по текстовому полю, он вернёт записи, начинающиеся с указанной в фильтре строки.