Январь 2018

Этот курс закончился

Cписок курсов

Домашнее задание. Приложение «Гостевая Книга»

20 февраля 2018

Требуется создать приложение «Гостевая книга». Приложение должно поддерживать возможность публикации сообщений, отображения их в хронологическом порядке, вход и регистрацию пользователей с возможностью восстановления и смены пароля. Кроме того, нужно обеспечить интерфейс администратора.

Дополнительные материалы к сайту

Скачайте вот это архив и распакуйте его. Внутри вы найдёте модуль reg_view.py и каталог с шаблонами templates. Описание этих файлов см. ниже.

Модели данных

В этой задаче только одна модель данных: Сообщение (Message). У сообщения должны быть следующие поля:

  • автор (author) — пользователь, который отправил сообщение. Тип поля — ForeignKey от модели django.contrib.auth.models.User. Если мы хотим разрешить оставлять сообщения без регистрации, то это поле может содержать None: задайте полю параметр null=True.
  • тема (subject или subj) — тема сообщения. Тип поля — строка, то есть CharField. Максимальная длина — скажем, 250 знаков.
  • текст (text) — текст сообщения. Ради простоты и безопасности не будем разрешать пользователям вводить теги HTML или другую разметку. Тип поля — TextField.
  • дата публикации (скажем, pub_date) — дата и время публикации сообщения. Тип поля — DateTimeField. Установку даты публикации можно автоматизировать: задайте у этого поля параметр auto_now=True, и в него будет автоматически заноситься дата и время создания сообщения. Сообщения будут сортироваться по этому полю по убыванию (то есть новые сверху).

Обязательно нужно зарегистрировать модель в файле admin.py. Создайте там администативный класс MessageAdmin, отнаследованный от admin.ModelAdmin и воспользуйтесь декоратором @admin.register. В классе MessageAdmin задайте параметры list_display, ordering, а так же любые другие параметры, управляющие отображением админки, какие сочтёте нужными.

Структура адресов

На сайте будут доступны следующие URL:

  • Главная страница (шаблон "") — соответствующее представление (view) будет выводить все сообщения, отсортированные по убыванию даты публикации.
  • Адрес add/ — форма публикации нового сообщения. Соответсвующее представление выводит и обрабатывает форму публикации сообщения. В форме два поля: тема сообщения (subj) и текст сообщения (text). Оба поля обязательны. В обычной ситуации представление показывает пустую форму. Если же форма была отправлена на обработку (это можно проверить через свойство request.method, см. про обработку форм ниже), то представление проверяет, все ли поля заполнены. Если да, то представление создаёт новое сообщение, сохраняет его и перенаправляет (см. ниже) пользователя обратно на главную страницу. Если хоть одно поле не заполнено, или заполнено только пробелами, то предствление снова показывает форму, а так же сообщение о том, что надо заполнить поля.
  • Адрес register/ — форма регистрации пользователя. К сожалению, приложение django.contrib.auth не содержит готового view для этой цели. Я взял на себя смелость реализовать недостающую функцию — это функция register_new_user в модуле reg_views. Для подключения этого модуля поместите файл reg_views.py из архива в ваше приложение, и добавьте в urls.py следующие строки:
# 1. Импорт функции
from guest_book.reg_views import register_new_user

# 2. Подключение view к адресу
urlpatterns = [
    # ... всё остальное

    path('register/', register_new_user, name='register'),
]
  • Адреса из приложения django.contrib.auth. Для этого добавьте в urls.py
# 1. Импорт функции include
from django.conf.urls import url, include # include дописано к уже имеющейся строке

#2. Подключение адресов
urlpatterns = [
    # ... всё остальное

    path('', include("django.contrib.auth.urls")),
]
  • Кроме того, ещё должна быть подключена панель администрирования (она подключена по умолчанию, если вы специально её не удаляли).
from django.contrib import admin

urlpatterns = [
    # ... всё остальное
    path('admin/', admin.site.urls),
]

Обработка формы публикации сообщения

Работать с формой можно двумя путями. Во-первых, напрямую, во-вторых, с помощью модуля django.forms. Далее рассмотрена работа с формой через django.forms.

Форма состоит из двух полей и одной кнопки. Кроме того, поскольку форма отправляется методом POST, необходимо добавить в неё CSRF-токен (это делается с помощью django-тега {% csrf_token %}. Показывает и обрабатывает форму одно и то же представление, как обычно.

Соответственно, представление может запуститься в одной из двух ситуаций:

  1. Пользователь перешёл по ссылке «НАПИСАТЬ» и собирается ввести текст сообщения.
  2. Пользователь нажал «Опубликовать сообщение» в форме, и нужно обработать форму.

Отличить эти ситуации можно по методу запроса. В первом случае, при обычном переходе по ссылке, браузер использует метод по-умолчанию — метод GET. При отправке формы на обработку используется указанный в форме метод — в нашем случае POST. Таким образом, следующий код различит эти ситуации:

def add_message_view(request):
    if request.method == 'POST':
        # Обработка формы
    else:
        # Показ страницы с формой

Проверка корректности формы производится средствами django.forms:

if request.method == 'POST':
    form = MessageForm(request.POST)
    if form.is_valid(): # Всё в порядке
        #... Извлекаем данные из form.cleaned_data
        # обрабатываем данные и перенаправляем пользователя
else:
    form = MessageForm()

Если форма некорректна, мы просто снова показываем страницу с ней.

Если же форма корректна, нужно обработать её содержимое (сохранить в БД, например), а затем либо отобразить страницу с сообщением об успешной обработке, либо перенаправить пользователя на другую страницу сайта.

Перенаправление пользователя

В протоколе HTTP предусмотрена возможность перенаправления браузера от адреса к адресу. В Django это реализует специальный HTTP Response (ответ HTTP): класс HttpResponseRedirect. Он находится в модуле django.http, не забудьте импортировать перед использованием.

В следующем примере view перенаправляет пользователя на главную страницу сайта:

from django.shortcuts import render
from django.http import HttpResponseRedirect

def process_view(request, data):
    if data and data.is_valid(): # Это просто пример, data – это некий объект
        process_data(data)
        return HttpResponseRedirect("/") # Параметр — URL
    else:
        return render(request, "error_bad_data.html", context={"data": data})

Оформление сайта

Чтобы верстать веб-страницы красиво, требуются специфические знания и опыт. Однако есть такая штука, как CSS-фрэймворки. Это готовые таблицы стилей, которые задают вашему сайту некоторое современно выглядещее оформление — пусть и немного однообразное, но симпатичное. Этого бывает достаточно, чтобы сделать прототип сайта, который не стыдно показать, а для проектов, ориентированных на содержание (вроде сайтов-библиотек) этого оформления может быть достаточно в принципе.

Один из таких фрэймворков — W3.CSS.

Сайт http://www.w3schools.com оформлен полностью с помощью этого фрэймворка. Примеры его работы показаны на странице W3.CSS Intro.

Пользоваться им просто. Он включает в себя множество CSS-классов, которые влияют на разные аспекты оформления элементов — цвета, границы, отступы и т.д. В документации на сайте это всё расписано по разделам. В каждом разделе есть примеры использования. Основная идея такая: делаете в HTML-коде элемент (например, <div>), и указываете у него атрибут class. Например, блок с голубым фоном, отсутпами и рамкой:

<div class="w3-blue w3-container w3-border">
    Привет, мир!
</div>

Класс w3-blue задаёт голубой фон и белый текст, w3-container добавляет стандартные оступы, а w3-border добавляет стандартную серую рамку. Вот так классы можно комбинировать.

Существуют и другие фрэймворки - Bootstrap, Skeleton и прочие. Альтернатива фрэймворкам — готовые шаблоны сайтов, которые включают в себя и CSS, и HTML, и даже JavaScript. Например, бесплатные шаблоны на сайте HTML5 UP.

Как задать стиль элементам формы

При создании формы для каждого поля можно указать виджет, а у виджета можно задать его атрибуты. Например, если мы хотим указать у текстового поля классы из W3.CSS, мы можем сделать это так:

class MessageForm(forms.Form):
    name = forms.CharField(widget=forms.TextField(attrs={"class": "w3-input w3-border"}), ...)
    # ...и так далее

Шаблоны в архиве

В каталоге templates в архиве находятся готовые свёрстанные шаблоны. Они реализованы с помощью W3.CSS. Те, что в подкаталоге registration, относятся к приложению django.contrib.auth — это шаблоны страниц входа на сайт, регистрации пользователя, смены и восстановления пароля, и так далее. Подробнее см. документацию Django.

Остальные шаблоны:

  • base.html — базовый шаблон. В нём находится панель навигации. От этого шаблона отнаследованы все остальные, включая те, что в подкаталоге registration.
  • main.html — шаблон главной страницы. Выводит список сообщений messages. Выделяет сообщения от обычных и анонимных пользователей разным цветом.
  • add.html — шаблон формы публикации нового сообщения.

Вы можете использовать эти шаблоны, переделав их под свои модели и view. Так же вы можете, экспериментируя со стилями W3.CSS, добиться собственного оформления сайта.

Настройка сайта в settings.py

Обязательно внесите в ваш файл settings.py следующие настройки:

  • LOGIN_REDIRECT_URL = "\" — этот параметр задаёт, на какой адрес будет перенаправлен пользователь сразу после входа на сайт

А так же задайте параметры отправки e-mail (вам понадобится отдельно зарегистрировать почтовый ящик для сайта, или использовать существующий). Сайт на хостинге PythonAnywhere будет работать только с GMail. Для GMail-ящика укажите следующие настройки:

EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_PORT = 587
EMAIL_HOST_USER = 'ВАШ-ЛОГИН@gmail.com'
EMAIL_HOST_PASSWORD = 'ВАШ-ПАРОЛЬ-ОТ-ПОЧТЫ'
EMAIL_USE_TLS = True
DEFAULT_FROM_EMAIL = 'ВАШ-ЛОГИН@gmail.com'

Теперь система восстановления пароля будет работать. Если всё же письма не отправляются, проверьте на локальном сервере (python manage.py runserver). Если с локального сервера всё работает, а на PythonAnywhere — нет, обратитесь к справочной информации тут.