Розширте ваш додаток
Ми вже завершили усі кроки необхідні для створення нашого сайту: знаємо як написати модель, url, відображення та шаблон. А також знаємо про те, як зробити наш сайт гарнішим.
Час попрактикуватись!
Перша потрібна для нашого блогу річ це, очевидно, сторінка для відображення одного посту, чи не так?
У нас вже є модель Post
, отже не треба нічого додавати до models.py
.
Створимо посилання в шаблоні
Почнемо із додавання посилання в blog/templates/blog/post_list.html
. Таким чином, матимемо:
{% extends 'blog/base.html' %}
{% block content %}
{% for post in posts %}
<div class="post">
<div class="date">
{{ post.published_date }}
</div>
<h1><a href="">{{ post.title }}</a></h1>
<p>{{ post.text|linebreaks }}</p>
</div>
{% endfor %}
{% endblock content %}
Ми хочемо мати посилання на сторінку із деталями про окремий пост, яке міститиметься в заголовку поста. Змінимо <h1><a href="">{{ post.title }}</a></h1>
на посилання:
<h1><a href="{% url 'blog.views.post_detail' pk=post.pk %}">{{ post.title }}</a></h1>
Час пояснити містичне {% url 'blog.views.post_detail' pk=post.pk %}
. Як можна було очікувати, {% %}
означає, що ми використовуємо шаблонні теги Django. Цього разу скористаємось таким, що створить для нас URL!
blog.views.post_detail
- це шлях до відображення post_detail
, яке ми бажаємо створити. Зауважте, будь ласка: blog
-- це ім'я нашого додатку (папка blog
), views
взято з імені файлу views.py
і остання частина - post_detail
- це ім'я відображення.
Тепер коли ми зайдемо на: http://127.0.0.1:8000/ то отримаємо помилку (як і очікувалось, оскільки у нас немає URL або відображення для post_detail
). Це буде виглядати як:
Давайте створимо URL в urls.py
для нашого відображення post_detail
!
URL: http://127.0.0.1:8000/post/1/
Ми бажаємо створити URL щоб направляти Django до відображення, що називається post_detail
, що в свою чергу має відобразити введений пост. Додамо рядок url(r'^post/(?P<pk>[0-9]+)/$', views.post_detail),
у файл blog/urls.py
. Це буде виглядати наступним чином:
from django.conf.urls import include, url
from . import views
urlpatterns = [
url(r'^$', views.post_list),
url(r'^post/(?P<pk>[0-9]+)/$', views.post_detail),
]
Виглядає жахливо, але не хвилюйтесь - ми пояснимо вам: - усе починається із ^
знову -- "початок" - post/
лише означає, що після початку, URL має містити слово post і /. Все йде добре. - (?P<pk>[0-9]+)
- ця частина хитріша. Це означає, що Django візьме усе, що ви тут розмістите і передасть це до відображення як змінну із ім'ям pk
. [0-9]
також повідомляє нас про те, що це може бути лише цифрою, не літерою (будь-яке значення між 0 та 9). +
означає, що тут має бути один або більше символів. Таким чином, щось на зразок http://127.0.0.1:8000/post//
є неприйнятним, однак http://127.0.0.1:8000/post/1234567890/
цілком! - /
- далі нам потрібно знову/ - $
- "кінець"!
Це означає, що якщо ви введете http://127.0.0.1:8000/post/5/, Django зрозуміє, що ви шукаєте відображення із назвою post_detail
і передає цьому відображенню інформацію, що pk
дорівнює 5
.
pk
-- скорочення для первинного ключа - primary key
. Це ім'я часто використовується в Django проектах. Однак, можете назвати вашу змінну як вам до вподоби (пам'ятайте: маленькі літери і _
замість пробілів!). Наприклад, замість (?P<pk>[0-9]+)
можемо мати змінну post_id
, і, таким чином, ця частина буде виглядати як: (?P<post_id>[0-9]+)
.
Гаразд! Давайте перезавантажимо сторінку: http://127.0.0.1:8000/
Бум! Ще одна помилка! Як і варто було очікувати!
Пам'ятаєте яким є наступний крок? Звісно: треба додати відображення!
post_detail view
Цього разу наше відображення отримує ще додатковий параметр - pk
. Наше відображення має вилучити його, правда ж? Отже, визначимо нашу функцію як def post_detail(request, pk):
. Зауважте, що треба використовувати точно таке ж ім'я як ми визначили в urls (pk
). Неправильно нехтувати цією змінною, це призведе до помилки!
А тепер, ми би хотіли додати один-єдиний пост. Щоб зробити це можемо скористатися наступним запитом до бази даних:
Post.objects.get(pk=pk)
Однак, цей код містить проблеми. Якщо немає жодного поста із заданим первинним ключем (pk
), ми отримаємо мега жахливу помилку!
Ми цього не хочемо! Але, звичайно, Django надає деякі інструменти, що будуть обробляти це для нас: get_object_or_404
. У випадку, якщо немає постів із заданим pk
, виведеться більш приємна сторінка (так звана сторінка Page Not Found 404
).
Хороші новини полягають в тому, що можна створити свою власну сторінку Page not found
і зробити її настільки гарною, наскільки ви захочете. Однак, це не є надто важливим на даний момент, отже, пропустимо цей крок.
Добре, час додати відображення у наш файл views.py
!
Нам треба відкрити blog/views.py
і додати наступний код:
from django.shortcuts import render, get_object_or_404
Поряд із іншими рядками from
. А вкінці файлу додаймо наше відображення:
def post_detail(request, pk):
post = get_object_or_404(Post, pk=pk)
return render(request, 'blog/post_detail.html', {'post': post})
Так. Настав час перезавантажити нашу сторінку: http://127.0.0.1:8000/
Спрацювало! Але що ж трапиться коли ви клікните на посилання в заголовку поста?
О ні! Інша помилка! Але ж ми вже знаємо як із цим поводитись, чи не так? Потрібно додати шаблон!
Створимо файл в blog/templates/blog
і назвемо його post_detail.html
.
Це буде виглядати так:
{% extends 'blog/base.html' %}
{% block content %}
{% if post.published_date %}
<div class="date">
{{ post.published_date }}
</div>
{% endif %}
<h1>{{ post.title }}</h1>
<p>{{ post.text|linebreaks }}</p>
{% endblock %}
Знову розширюємо base.html
. Всередині блоку content
ми хотіли б відобразити такі параметри як: published_date (якщо існує), title і text. Але, мусимо обговорити певні важливі речі, правда ж?
{% if ... %} ... {% endif %}
-- це шаблонний тег, який можна використовувати, коли ми бажаємо перевірити дещо (пам'ятаєте if ... else ..
з розділу Вступ до Python?). В цьому сценарії ми хотіли б дізнатися чи параметр published_date
не пустий.
Ok, можемо перезавантажити нашу сторінку і побачити чи Page not found
зникло тепер.
Йой! Працює!
Ще одне: розгортання!
Було б непогано побачити чи ваш сайт все ще працює на Heroku, чи не так? Давайте спробуємо розгорнути його знову. Якщо ви вже забули як це зробити, зверніться до кінцевої частини розділу Розгортання:
$ git status
...
$ git add -A .
$ git status
...
$ git commit -m "Added more views to the website."
...
$ git push heroku master
І це все! Вітання :)