Академический Документы
Профессиональный Документы
Культура Документы
William S. Vincent
© 2018 William S. Vincent
Группа в ВК "Django_Python"
Содержание
Введение 1
Почему Django 1
Почему эта книга 3
Структура книги 3
Макет книги 5
Вывод 7
Глава 1: Первоначальная Настройка 8
Командная строка 8
Установка Python 3 на Mac OS X 11
Установка Python 3 на Windows 13
Установка Python 3 на Linux 14
Установка Виртуальных Среды 15
Джанго 16
Установить Git 20
Текстовой редактор 21
Вывод 21
Глава 2: Hello World приложение 22
Начальная настройка 22
Создание приложения 25
Views и URL конфигурация 27
Привет мир! 30
Git 31
Bitbucket 33
Вывод 37
Глава 3: Страницы приложения 39
Начальная настройка 39
Шаблоны 41
Основа Классов 44
Views URLs 45
Добавление страницы 47
Группа в ВК "Django_Python"
ОГЛАВЛЕНИЕ
Расширение Шаблонов 49
Тесты 52
Git и Bitbucket 54
Local vs Production 56
Heroku(облачная PaaS-платформа) 57
Дополнительный файл 58
Deploy(развертывание) 61
Вывод 64
Глава 4: Приложение Доска Объявлений 65
Начальная настройка 65
Создание модели базы данных 68
Активация моделей 69
Джанго Админ 70
Views/Templates/URLs 77
Добавление новых записей 81
Тесты 85
Bitbucket 90
Heroku конфигурация 91
Heroku развертывание 93
Выводы
95
Глава 5: Приложение Блог 96
Начальная настройка 96
Модель базы данных 98
Админ 100
URLs 105
Views 107
Templates 108
Static files 111
Отдельные страницы блога 116
Тесты 122
Git 125
Выводы 125
Глава 6: Формы 127
Формы 127
Обновление форм 138
Удаление View 145
Тесты 151
Выводы 155
Глава 7: Учетные Записи Пользователей 156
Группа в ВК "Django_Python"
ОГЛАВЛЕНИЕ
Вход 156
Обновление Домашней страницы 159
Ссылка "выход" 161
Регистрация 164
Bitbucket 170
Конфигурация Heroku 171
Развертывание на Heroku 173
Выводы 177
Глава 8: Пользовательская Модель 178
Установка 178
Пользовательская User Model 180
Формы 182
Суперпользователь 185
Выводы 187
Глава 9: Аутентификация Пользователя 188
Templates 188
URLs 192
Admin 197
Выводы 203
Глава 10: Bootstrap 204
Приложение Страницы 204
Тесты 208
Bootstrap 211
Форма Регистрации 219
Дальнейшие действия 224
Глава 11: смена и сброс пароля 226
Изменение пароля 226
Настройка изменения пароля 228
Сброс пароля 231
Пользовательские шаблоны 235
Вывод 240
Глава 12: Электронная Почта 241
SendGrid 241
Пользовательская эл.почта 246
Вывод 250
Глава 13: Приложение газета 251
Приложение Статьи 251
Группа в ВК "Django_Python"
ОГЛАВЛНИЕ
Группа в ВК "Django_Python"
Введение
Добро пожаловать в Django для начинающих, проектный подход к обучению веб-разработке
с помощью веб-платформы Django. В этой книге вы создадите пять все более сложных веб-
приложений, начиная с простого приложения "Привет, мир", переходя к приложению блога
с формами и учетными записями пользователей, и, наконец, приложение газеты, используя
пользовательскую модель, интеграцию электронной почты, внешние ключи, авторизацию,
права доступа и многое другое.
К концу этой книги вы должны чувствовать себя уверенно, создавая свои собственные
проекты Django с нуля, используя лучшую современную практику.
Эта книга регулярно обновляется и содержит последние версии Django (2.0) и Python (3.6 x).
Он также использует Pipenv, который теперь официально Рекомендуемый менеджер
пакетов Python.org для управления пакетами Python и виртуальными средами. На всем
протяжении мы будем использовать лучшие современные практики сообщества Django,
Python и веб-разработки, особенно тщательное использование тестирования.
Почему Django
Группа в ВК "Django_Python"
Introduction 2
• Аутентификация пользователя
• Шаблоны, маршруты и представления
• Интерфейс администратора
• Надежная безопасность
• Поддержка нескольких серверных баз данных
• И многое другое
Группа в ВК "Django_Python"
Introduction 3
Я написал эту книгу, не смотря на то, что Django очень хорошо документирован потому что
существует серьезная нехватка доступных учебников для начинающих. Когда я впервые
узнал Django несколько лет назад, я выбивался из сил пытаясь выполнять по официальному
учебнику. По этому я так хорошо помню, что думал.
Моя цель состоит в том, что бы эта книга заполняла пробелы и демонстрировала насколько
дружелюбен к новичкам Django.
Вам не нужен прошлый опыт Python или веб-разработки для завершения этой книги. Она
специально написан так, что даже новичок может следовать по ней и почувствовать магию
написания собственных веб-приложений с нуля. Однако, если вы серьезно относитесь к
карьере в веб-разработке, вам в конечном итоге нужно будет потратить время, чтобы
изучить Python, HTML и CSS должным образом. В заключение приводится перечень
рекомендуемых ресурсов для дальнейшего изучения.
Структура Книги
Группа в ВК "Django_Python"
Introduction 4
Django (2.0), Python (3.6) и Pipenv для управления нашими виртуальными средами. Мы также
пройдем введение в командную строку и обсудим как работать с современным текстовым
редактором.
В Главе 2 мы создадим наш первый проект, минимальное Hello, World приложение, которое
демонстрирует, как настроить новые проекты Django. Так как создание хорошего
программного обеспечения важно, мы также сохраним нашу работу в git и загрузим копию в
удаленный репозиторий кода на Bitbucket.
В Главе 3 мы создадим, протестируем и развернем Приложение Pages, которое
представляет шаблоны и view на основе классов. Шаблоны это то, как Django позволяет
создавать (Не Повторяйтесь - принцип разработки программного обеспечения, нацеленный
на снижение повторения информации различного рода) разработку с помощью HTML и CSS,
в то время как view на основе классов требуют минимального количества кода для
использования и расширения основной функциональности в Django. Они потрясающие, вы
это скоро увидите. Мы также добавим наши первые тесты и развернем в Heroku, который
имеет свободный уровень и который мы будем использовать на протяжении всей этой
книги. Использование таких поставщиков услуг, как Heroku, превращает разработку из
болезненного, трудоемкого процесса во что-то, что занимает всего несколько щелчков
мыши.
В Главе 4 мы создадим наш первый проект с базой данных, приложение для доски
объявлений. Django предоставляет мощный ORM, который позволяет нам писать сжатый
Python для наших таблиц базы данных. Мы рассмотрим встроенное приложение
администратора, которое обеспечивает графический способ взаимодействия с нашими
данными и может быть даже использовано в качестве системы управления контентом (CMS),
аналогичной Wordpress. Также мы напишем тесты для всего нашего кода, сохраним
удаленную копию на Bitbucket и развернем в Heroku. Наконец, в Главах 5-7 мы готовы к
нашему финальному проекту: надежному приложению для блога, которое демонстрирует,
как выполнять функциональность CRUD (Create-Read-Update-Delete)(Создание-Чтение-
Обновление-Удаление) в Django. Мы обнаружим, что общие view на основе классов Django
означают, что для этого нам нужно написать лишь небольшое количество реального кода!
Затем мы добавим формы и интегрируем встроенную систему аутентификации
пользователей Django (login, logout, signup).
Группа в ВК "Django_Python"
Introduction 5
проекты должны использовать пользовательскую модель, и в этой главе вы узнаете, как это
сделать. Глава 9 охватывает аутентификацию пользователей, Глава 10 добавляет Bootstrap
для стилизации, а главы 11-12 реализуют сброс пароля и изменение по электронной почте.
В главах 13-15 мы добавляем статьи и комментарии к нашему проекту, а также
соответствующие разрешения и полномочия. Мы даже узнаем некоторые приемы для
настройки администратора, чтобы отобразить наши растущие данные.
Макет книги
В этой книге есть много примеров кода, которые обозначаются следующим образом:
Code
Для краткости будем использовать точки ... для обозначения существующего кода, который
остается неизменным, например, в функции, которую мы обновляем.
Группа в ВК "Django_Python"
Introduction 6
Code
def make_my_website:
...
print("All done!")
Command Line
Command Line
"hello, world"
Command Line
hello, world
Полный исходный код всех примеров можно найти в официальном репозитории github.
Группа в ВК "Django_Python"
Introduction 7
Заключение
Группа в ВК "Django_Python"
Глава 1 : Начальная настройка
В этой главе описывается, как правильно настроить компьютер для работы с Django
проектом. Мы начнем с обзора командной строки и используем ее для установки последних
версий Django (2.0) и Python (3.6 x). Затем мы обсудим виртуальные среды, git и работу с
текстовым редактором.
К концу этой главы вы будете готовы создавать и изменять новые проекты Джанго за
несколько кликов.
Командная строка
Группа в ВК "Django_Python"
Chapter 1: Initial Setup 9
Хотя есть много возможных команд, которые мы можем использовать, на практике есть
шесть наиболее часто используемых в разработке Django.
• cd (изменить каталог)
• cd .. (перейти в верх)
• ls (список файлов в текущем каталоге)
• pwd ( вывести текущий каталог)
• mkdir (создать каталог)
• touch (создать новый файл)
Откройте командную строку и попробуйте их. Знак $ dollar-это наша командная строка: все
команды в этой книге предназначены для ввода после $.
Например, предположим, что вы находитесь на Mac, давайте перейдем в каталог рабочего
стола.
Command Line
$ cd ~/Desktop
Command Line
~/Desktop $ pwd
/Users/wsv/desktop
На моем компьютере Mac это показывает, что я использую пользователя wsv и нахожусь на
рабочем столе для этой учетной записи.
Давайте создадим новую папку каталога с mkdir, cd и добавим в нее новый файл index.html.
Группа в ВК "Django_Python"
Chapter 1: Initial Setup 10
Command Line
~/Desktop $ cd new_folder
Теперь используйте ls для вывода списка всех текущих файлов в нашем каталоге. Вы увидите
только что созданный index.html.
Command Line
~/Desktop/new_folder $ ls
index.html
В качестве последнего шага вернитесь в каталог рабочего стола cd .. и используйте pwd для
подтверждения местоположения.
Command Line
~/Desktop/new_folder $ cd ..
~/Desktop $ pwd
/Users/wsv/desktop
Группа в ВК "Django_Python"
Chapter 1: Initial Setup 11
Хотя Python 2 установлен по умолчанию на компьютерах Mac, Python3 в нем нет. Вы можете
подтвердить это, набрав python --version в консоли командной строки и нажав Enter:
Command Line
$ python --version
Python . .
Command Line
$ python --version
Если ваш компьютер выводит �.�.x ((любая версия 3.6 или выше), то у вас все в порядке,
однако, скорее всего, вы увидите сообщение об ошибке, так как нам нужно установить
Python 3 непосредственно.
Наш первый шаг-установить пакет Xcode от Apple, поэтому выполните следующую
команду, чтобы установить его:
Группа в ВК "Django_Python"
Chapter 1: Initial Setup 12
Command Line
$ xcode-select --install
Щелкните по всем командам подтверждения (Xcode - это большая программа, поэтому для
установки может потребоваться некоторое время, в зависимости от вашего интернет-
соединения).
Command Line
all/master/install)"
Command Line
$ brew doctor
Command Line
Группа в ВК "Django_Python"
Chapter 1: Initial Setup 13
Command Line
$ python --version
Python . .
Чтобы открыть интерактивную оболочку Python 3 (это позволит нам запускать команды
Python прямо на нашем компьютере )просто введите python3 :
Command Line
$ python
>>>
Command Line
$ python
Группа в ВК "Django_Python"
Chapter 1: Initial Setup 14
Или вы можете удерживать клавишу SHIFT и щелкнуть правой кнопкой мыши на рабочем
столе, а затем выбрать «Открыть командное окно» здесь или - "Открыть окно PowerShell
здесь" в windows 10.
Command Line
python --version
Python . .
Если вы видите такой вывод, Python уже установлен. Но скорее всего, этого не будет!
Чтобы загрузить Python 3, перейдите в раздел загрузки официального сайта Python.
Загрузите установщик и убедитесь, что вы выбрали опцию Add Python to PATH , которая
позволит использовать python прямо из командной строки. В противном случае мы должны
были бы ввести полный путь нашей системы и изменить наши переменные среды вручную.
После установки Python выполните следующую команду в новой консоли командной
строки:
Command Line
python --version
Python . .
Группа в ВК "Django_Python"
Chapter 1: Initial Setup 15
Виртуальная среда
Pipenv похож на npm и yarn из экосистемы узлов: он создает файл канала, содержащий
зависимости программного обеспечения и Pipfile. Блокировка для обеспечения
детерминированных построений. “Детерминизм” означает, что каждый раз, когда вы
загружаете программное обеспечение в новой виртуальной среде, у вас будет точно такой
же конфигурации. Себастьян Маккензи, создатель Yarn, который впервые представил эту
концепцию для упаковки JavaScript, имеет краткое сообщение в блоге, объясняющее, что
такое детерминизм и почему это имеет значение.
Конечным результатом является то, что мы создадим новую виртуальную среду с pipenv
для каждого нового проекта Django.
Для установки Pipenv мы можем использовать pip , который автоматически установился
для нас вместе с Python 3.
Группа в ВК "Django_Python"
Chapter 1: Initial Setup 16
Command Line
Установка Django
Чтобы увидеть Pipenv в действии, давайте создадим новый каталог и установим Django.
Сначала перейдите на рабочий стол, создайте новый каталог django и введите его с cd.
Command Line
$ cd ~/Desktop
$ mkdir django
$ cd django
Command Line
Если вы посмотрите в наш каталог, есть два новых файла: Popfile и Pipe-file.lock. У нас есть
информация, необходимая для новой виртуальной среды, но мы ее еще не активировали.
Давайте сделаем это с помощью оболочки pip env shell.
Command Line
$ pipenv shell
Группа в ВК "Django_Python"
Chapter 1: Initial Setup 17
Обратите внимание, что из-за открытой ошибки пользователи Windows не будут видеть
визуальную обратную связь виртуальной среды в это время. Но если вы сможете запустить
Django-admin startproject в следующем разделе, то вы узнаете, что в вашей виртуальной
среде установлен Django.
Command Line
(django-JmZ NTQw) $
Это означает, что все работает! Создайте новый проект Django с именем test с помощью
следующей команды. Не забудьте поставить точку в конце через пробел.
Command Line
Стоит остановиться здесь, чтобы объяснить, почему вы должны добавить точку через
пробел к команде. Если вы просто запустите django-admin startproject test_project, то по
умолчанию Django создаст эту структуру каталогов:
└── test_project
├── manage.py
└── test_project
├── __init__.py
├── settings.py
├── urls.py
└── wsgi.py
Посмотрите, как он создает новый каталог test_project, а затем в нем manage.py файл и
каталог test_project? Это кажется мне излишним, так как мы уже создали и перешли в папку
django на нашем рабочем столе. Запустив django-admin startproject test_project . с точкой в
конце-который говорит, установите в текущем каталоге Результат вместо этого будет:
Группа в ВК "Django_Python"
Chapter 1: Initial Setup 18
├── manage.py
└── test_project
├── __init__.py
├── settings.py
├── urls.py
└── wsgi.py
Вывод заключается в том, что на самом деле не имеет большого значения, ставите ли вы
точку или нет в конце команды, но я предпочитаю ставить ее, и именно так мы сделаем в
этой книге.
Теперь давайте проверим, что все работает, запустив локальный веб-сервер Django.
Command Line
Группа в ВК "Django_Python"
Chapter 1: Initial Setup 19
Чтобы остановить наш локальный сервер, введите Control-c. Затем выйдите из нашей
виртуальной среды с помощью команды exit.
Command Line
Мы всегда можем снова активировать виртуальную среду с помощью pipenv shell в любое
время.
Мы получим много практики с виртуальными средами в этой книге, так что не волнуйтесь,
если это
Группа в ВК "Django_Python"
Chapter 1: Initial Setup 20
немного сбивает вас с толку сейчас. Основной шаблон заключается в установке новых
пакетов с pipenv, активируйте их с помощью pipenv shell, а затем выйти, когда закончите
exit.
Стоит отметить, что одновременно на вкладке командной строки может быть активна
только одна виртуальная среда. В следующих главах мы будем создавать совершенно новую
виртуальную среду для каждого нового проекта. Так что либо не забудьте выйти из текущей
среды, либо откройте новую вкладку для новых проектов.
Установка Git
Git является неотъемлемой частью современной разработки программного обеспечения.
Это система контроля версий, которая может рассматриваться как чрезвычайно мощная
версия отслеживания изменений в Microsoft Word или Google Docs. С помощью git вы
можете сотрудничать с другими разработчиками, отслеживать всю вашу работу с помощью
фиксаций и возвращаться к любой предыдущей версии вашего кода, даже если вы случайно
удалили что-то важное!
На Mac, поскольку Homebrew уже установлен, мы можем просто ввести brew install git в
командной строке:
Command Line
В Windows вы должны скачать Git из Git for Windows. Нажмите кнопку «Загрузить» и
следуйте инструкциям по установке. Нажмите «Далее» на всех шагах, кроме пятого,
“Adjusting your PATH environment.” Вместо этого выберите нижнюю опцию: “Use Git and
optional Unix tools from the Windows Command Prompt.”
После установки нам нужно выполнить одноразовую настройку системы, чтобы настроить
ее, объявив имя и адрес электронной почты, которые вы хотите связать со всеми вашими
обязательствами Git (подробнее об этом в ближайшее время).
В консоли командной строки введите следующие две строки. Не забудьте обновить их имя и
адрес электронной почты.
Группа в ВК "Django_Python"
Chapter 1: Initial Setup 21
Command Line
Вы всегда можете изменить эти настройки, если пожелаете, введя те же команды с новым
именем или адресом электронной почты.
Текстовой редактор
Последний шаг это ваш текстовый редактор. В то время как командная строка, где мы
выполняем команды для наших программ по сути текстовый редактор. Компьютеру все
равно, какой текстовый редактор вы используете конечный результат просто код, но
хороший текстовый редактор может предоставить полезные советы и поймать опечатки для
вас.
Опытные разработчики часто предпочитают использовать либо Vim, либо Emacs, оба
десятилетних текстовых редактора с лояльными последователями. Однако каждый из них
имеет крутую кривую обучения и требует запоминания множества различных комбинаций
клавиш. Я не рекомендую их новичкам.
Современные текстовые редакторы сочетают в себе те же мощные функции с
привлекательным визуальным интерфейсом. Мой текущий фаворит это Visual Studio Code,
который является бесплатным, простым в установке и пользуется широкой популярностью.
Если вы еще не используете текстовый редактор, загрузите и установите Visual Studio Code.
Вывод
УФ! Никто на самом деле не любит настраивать локальную среду разработки, но, к счастью,
это одноразовая боль. Теперь мы научились работать с виртуальными средами и
установили последнюю версию Python и git. Все готово для вашего первого приложения на
Django.
Группа в ВК "Django_Python"
Глава 2 : Hello World приложение
В этой главе мы будем строить проект Django, который просто говорит: “Привет, мир” на
главной странице. Это традиционный способ начать новый язык программирования или
фреймворк. Мы также впервые будем работать с git и развертывать наш код в Bitbucket.
Начальная настройка
Для начала перейдите в новый каталог на компьютере. Например, мы можем создать папку
helloworld на рабочем столе с помощью следующих команд.
Command Line
$ cd ~/Desktop
$ mkdir helloworld
$ cd helloworld
Группа в ВК "Django_Python"
Chapter 2: Hello World app 23
Command Line
$ pipenv shell
Если Вы находитесь на Mac, вы должны увидеть скобки в начале командной строки в форме
(helloworld-XXX) где XXX представляет случайные символы. На моем компьютере я вижу
Command Line
Если сейчас вы используете команду tree вы можете увидеть, что наша структура проекта
Django теперь выглядит так. (Примечание: если tree у вас не работает установите его с
Homebrew:: brew install tree.)
Command Line
(helloworld) $ tree
├── helloworld_project
│ ├── __init__.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
└── manage.py
Группа в ВК "Django_Python"
Chapter 2: Hello World app 24
directory, files
Файл settings.py управляет настройками нашего проекта, urls.py сообщает Django какие
страницы для сборки выдать в ответ на запрос браузера или url, и wsgi.py который
обозначает интерфейс шлюза веб-сервера и помогает Django обслуживать наши возможные
веб-страницы. Последний файл manage.py используется для выполнения различных команд
Django, таких как запуск локального веб-сервера или создание нового приложения.
Command Line
Группа в ВК "Django_Python"
Chapter 2: Hello World app 25
Создание приложения
Группа в ВК "Django_Python"
Chapter 2: Hello World app 26
Нам нужно создать наше первое приложение, которое мы назовем pages. Из командной
строки закройте сервер с помощью Control+c. Затем используйте команду startup.
Command Line
Если снова заглянуть в каталог дерева команд вы увидите, что Джанго создал страницы со
следующими файлами:
Command Line
├── pages
│ ├── __init__.py
│ ├── admin.py
│ ├── apps.py
│ ├── migrations
│ │ └── __init__.py
│ ├── models.py
│ ├── tests.py
│ └── views.py
Группа в ВК "Django_Python"
Chapter 2: Hello World app 27
Code
# helloworld_project/settings.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'pages', # new
Views и URLConfs
Другими словами, наша функция из Views выведет текст «Hello, World», в то время как наш
URL будет гарантировать, что когда пользователь посещает главную страницу, он будет
перенаправляется на правильную функцию Views.
Начнем с обновления файла views.py в нашем pages приложении выглядит это следующим
образом:
Группа в ВК "Django_Python"
Chapter 2: Hello World app 28
Code
# pages/views.py
def homePageView(request):
Теперь нам нужно настроить наш URL. В приложении pages создайте новый urls.py файл.
Command Line
Группа в ВК "Django_Python"
Chapter 2: Hello World app 29
Code
# pages/urls.py
urlpatterns = [
В верхней строке мы импортируем path из Django, чтобы использовать наш шаблон url, и на
следующей строке мы импортируем наш файл views. Использованный пробел с точкой
from . import views означает ссылку на текущий каталог, который является нашим
приложением pages, содержащим как views.py, так и urls.py.
Наш шаблон URL состоит из трех частей:
Мы уже почти закончили. Последний шаг это настройка на уровне проекта файла urls.py.
Помните, что обычно в одном проекте Django есть несколько приложений, поэтому
каждому из них нужен свой собственный маршрут.
Группа в ВК "Django_Python"
Chapter 2: Hello World app 30
Code
# helloworld_project/urls.py
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('pages.urls')),
Мы импортировали include во второй строке рядом с path, а затем создали новый шаблон
url-адреса для нашего приложения pages. Теперь, когда пользователь посещает главную
страницу ' ', он сначала будет перенаправлен на приложение pages, а затем на views
домашней страницы.
Это часто путает начинающих, то что нам здесь не нужно импортировать приложение pages,
но мы ссылаемся на него в нашем шаблоне url как pages.urls. Причина, по которой мы
делаем это, заключается в том, что метод django.urls.include () ожидает, что мы перейдем в
модуль или приложение в качестве первого аргумента. Поэтому без использования include
нам нужно будет импортировать наше приложение pages, но поскольку мы используем
include, мы не должны это делать на уровне проекта!
Hello, world!
У нас есть весь код, который нам сейчас нужен ! Чтобы подтвердить, что все работает так,
как и ожидалось, перезагрузите наш сервер Django:
Группа в ВК "Django_Python"
Chapter 2: Hello World app 31
Command Line
Git
В предыдущей главе мы также установили git, который является системой контроля версий.
Давайте используем его здесь. Первый шаг - инициализировать (или добавить) git в наш
репозиторий.
Command Line
Группа в ВК "Django_Python"
Chapter 2: Hello World app 32
Command Line
On branch master
No commits yet
Untracked files:
db.sqlite
helloworld_project/
manage.py
pages/
Pipfile
Pipfile.lock
ничего не добавлено к фиксации, но присутствуют неотслеживаемые файлы (используйте" git add " для отслеживания)
Command Line
Обратите внимание, что пользователи Windows могут получить сообщение об ошибке git
commit error: pathspec ‘commit’ did not match any file(s) known to которая, по-
видимому, связана с использованием одинарных кавычек ' ' и отличается от двойных
кавычек" ". Если вы видите эту ошибку, используйте двойные кавычки для всех сообщений
фиксации в будущем.
Группа в ВК "Django_Python"
Chapter 2: Hello World app 33
Bitbucket
Хорошей привычкой является создание удаленного хранилища кода для каждого проекта.
Таким образом, у вас есть резервная копия на случай, если что-то случится с вашим
компьютером, и, что более важно, она позволяет сотрудничать с другими разработчиками
программного обеспечения. Два самых популярных варианта Bitbucket и Github.
Группа в ВК "Django_Python"
Chapter 2: Hello World app 34
Группа в ВК "Django_Python"
Chapter 2: Hello World app 35
Группа в ВК "Django_Python"
Chapter 2: Hello World app 36
Мы уже в каталоге нашего repo, пропустим Шаг 1 (Step 1). В шаге 2(Step 2) мы используем
две команды для добавления проекта в Bitbucket. Обратите внимание, что ваша команда
будет отличаться от моей, так как у вас другое имя пользователя. Пример общего формата
расположен ниже, где <USER> - Ваше имя пользователя Bitbucket.
Command Line
orld.git
После выполнения этой команды для настройки git с этим репозиторием Bitbucket мы
должны «вставить» наш код в него.
Группа в ВК "Django_Python"
Chapter 2: Hello World app 37
Command Line
(helloworld) $ git push -u origin master
Сейчас, если вы вернетесь на свою страницу Bitbucket и обновите ее, вы увидите, что код
теперь находится в онлайн! Нажмите на вкладку “Source” слева, чтобы увидеть все это.
Bitbucket обзор
Command Line
(helloworld) $ exit
Сейчас в вашей командной строке не должно быть круглых скобок, это указывает на то, что
виртуальная среда больше не активна.
Вывод
Группа в ВК "Django_Python"
Chapter 2: Hello World app 38
Мы начали изучать views, urls и внутренний веб-сервер. А так же мы работали с git, чтобы
отслеживать наши изменения, и поместили наш код в частный репозиторий Bitbucket.
Перейдем к главе 3: Простое приложение, где мы создадим и развернем более сложное
приложение Django с использованием шаблонов(templates) и представлений(views) на
основе классов.
Группа в ВК "Django_Python"
Глава �: Pages приложение
В этой главе мы создадим, протестируем и развернем Приложение Pages с главной
страницей home и страницей about. Мы также узнаем о классовых views и templates Django,
которые являются строительными блоками для более сложных веб-приложений,
построенных в книге позже .
Начальная настройка
Как и в главе 2: Hello World приложение, наша первоначальная настройка включает в себя
следующие шаги:
• создание нового каталога для нашего кода
• установить Django в новой виртуальной среде
• создание нового проекта Django
• создание нового приложения pages
• обновление(настройка) settings.py
Группа в ВК "Django_Python"
Chapter 3: Pages app 40
Command Line
$ cd ~/Desktop
$ mkdir pages
$ cd pages
$ pipenv shell
Code
# pages_project/settings.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'pages', # new
Группа в ВК "Django_Python"
Chapter 3: Pages app 41
Command Line
Templates(Шаблоны)
Каждый веб-фреймворк нуждается в удобном способе создания HTML файлов. В Django,
подход заключается в использовании шаблонов(templates), так что бы отдельные HTML
файлы могли обслуживаться в view веб-страницы, указанным URL.
Группа в ВК "Django_Python"
Chapter 3: Pages app 42
Стоит повторить эту модель, так как вы увидите ее снова и снова в Django разработке :
Templates, Views и URLs. Порядок, в котором вы их создаете, не имеет большого значения,
поскольку все три необходимы и работают в тесном сотрудничестве. URLs управляют
начальным маршрутом, точкой входа на страницу, например /about, views содержат
логику, а шаблон имеет HTML. Для веб-страниц, использующих модели базы данных, views
делает большую часть работы по определению какие данные доступны в шаблоне.
И так: Templates, Views, URLs. Эта модель будет справедлива для каждой веб-страницы
Django которую вы делаете. Однако потребуется некоторая практика, прежде чем вы
усвоите это.
Ок, двигаемся дальше. Вопрос о том, где разместить каталог шаблонов(templates), может
смутить новичков. По умолчанию Django ищет шаблоны в каждом приложении. Наше
pages приложение будет ожидать шаблон home.html который расположен в следующей
директории:
└── pages
├── templates
├── pages
├── home.html
Это означает, что нам нужно будет создать новый каталог шаблонов(templates), новый
каталог с именем приложения, pages, и наконец, сам наш шаблон home.html
Общий вопрос: почему эта повторяющаяся структура? Короткий ответ заключается в том,
что загрузчик шаблонов Django хочет быть действительно уверен, что он найдет
правильный шаблон, и именно так он запрограммирован на их поиск.
К счастью, есть еще один часто используемый подход построения шаблонов Django-
проекта. Вместо этого необходимо создать единый каталог шаблонов на уровне проекта,
доступный для всех приложений. Это тот подход, который мы и будем использовать.
Группа в ВК "Django_Python"
Chapter 3: Pages app 43
Сделав небольшую настройку в файле settings.py, мы можем указать Django также искать в
папке на уровне проекта для шаблонов.
Сначала остановите наш сервер с помощью Control-c. Затем создайте папку на уровне
проекта с именем templates и HTML файл с именем home.html.
Command Line
Далее нам нужно обновить settings.py и указать Django, чтобы он искал шаблоны на уровне
проекта. Для этого изменим строку 'DIRS' под TEMPLATES.
Code
# pages_project/settings.py
TEMPLATES = [
...
...
},
Группа в ВК "Django_Python"
Chapter 3: Pages app 44
Code
<h1>Homepage.</h1>
Ок, наш шаблон готов! Следующий шаг это настройка url и views.
Class-Based Views
Ранние версии Django поставлялись только с функциональными views, но вскоре
разработчики обнаружили что снова и снова повторяли одни и те же действия. Напишите
view со списком всех объектов в модели. Напишите view, в котором отображается только
один подробный элемент модели и так далее.
Группа в ВК "Django_Python"
Chapter 3: Pages app 45
Code
# pages/views.py
class HomePageView(TemplateView):
template_name = 'home.html'
Обратите внимание, что мы капитализировали наш view, так как теперь это класс Python.
Классы, в отличие от функций, всегда должны быть капитализированы. TemplateView уже
содержит всю логику, необходимую для отображения нашего шаблона, нам просто нужно
указать имя шаблона.
URLs
Последним шагом мы обновим наш URLConfs. Вспомним из главы 2, Что нам нужно
внести изменения в двух местах. Сначала мы обновляем на уровене проекта urls.py файл,
чтобы указать на наше pages приложение, а затем в urls.py файле pages приложения мы
сопоставим с маршрутами views .
Группа в ВК "Django_Python"
Chapter 3: Pages app 46
Code
# pages_project/urls.py
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('pages.urls')),
Давайте рассмотрим код на этом этапе. Мы добавили include во второй строке, чтобы
указать существующий URL-адрес приложения pages.
Далее создайте на уровне приложения urls.py файл.
Command Line
Code
# pages/urls.py
urlpatterns = [
Группа в ВК "Django_Python"
Chapter 3: Pages app 47
Этот шаблон почти идентичен тому, что мы сделали в главе 2 с одним существенным
отличием. При использовании Views на основе класса мы всегда добавляем as_view() в
конце имени view.
Домашняя страница
Процесс добавления страницы очень похож на то, что мы только что сделали. Мы создадим
Command Line
Группа в ВК "Django_Python"
Chapter 3: Pages app 48
Code
<h1>About page.</h1>
Создайте новый view для страницы.(подразумевается создать новый класс или функцию в данном случае
классAboutPageView)
Code
# pages/views.py
class HomePageView(TemplateView):
template_name = 'home.html'
class AboutPageView(TemplateView):
template_name = 'about.html'
Группа в ВК "Django_Python"
Chapter 3: Pages app 49
Code
# pages/urls.py
urlpatterns = [
About page
Расширение Шаблонов
Реальная сила шаблонов заключается в их способности расширяться. Если вы сейчас
вспомните то у большинства веб сайтов, которые повторяются на каждой странице
(заголовок, нижний колонтитул, и т.д.). И было бы неплохо, если бы у нас, как
разработчиков, могло быть одно каноническое место для нашего кода заголовка, который
бы наследовался всеми другими шаблонами.
Группа в ВК "Django_Python"
Chapter 3: Pages app 50
Command Line
Django имеет минимальный язык шаблонов для добавления ссылок и базовой логики в
наши шаблоны. Вы можете увидеть полный список встроенных шаблонов здесь в
официальной документации. Теги шаблонов имеют вот такую форму{% что-то %} где “что-
то” - это сам тег шаблона. Вы даже можете создать свои собственные теги шаблонов, хотя
мы не будем делать этого в этой книге.
URL-Адрес нашей домашней страницы называется home, поэтому для настройки ссылки на
нее мы будем использовать следующее: {% url 'home' %}.
Code
<header>
<a href="{% url 'home' %}">Home</a> | <a href="{% url 'about' %}">About</a>
</header>
{% block content %}
{% endblock %}
В нижней части мы добавили тег блока content. Блоки могут быть перезаписаны дочерними
шаблонами с помощью наследования.
Группа в ВК "Django_Python"
Chapter 3: Pages app 51
Давайте обновим наш home.html и about.html для расширения base.html шаблона. Это
означает, что мы можем повторно использовать код из одного шаблона в другой шаблон.
Язык шаблонов Django поставляется с методом extends, который мы можем использовать
для этого.
Code
{% extends 'base.html' %}
{% block content %}
<h1>Homepage.</h1>
{% endblock %}
Code
{% extends 'base.html' %}
{% block content %}
<h1>About page.</h1>
{% endblock %}
Запустите сервер командой python manage.py runserver и снова откройте наш сайт
http://127.0.0.1:8000/ и http://127.0.0.1:8000/about вы увидите, что заголовок
волшебным образом включен в обоих местах.
Правда приятно?
Группа в ВК "Django_Python"
Chapter 3: Pages app 52
Tests
Наконец мы подошли к тестам. Даже в этом базовом приложении важно добавлять тесты и
иметь привычку всегда добавлять их в наши проекты Django. По словам Джейкоба Каплан-
Мосса, одиного из создателей Джанго, “код без тестов нарушен полностью.”
Написание тестов важно, поскольку оно автоматизирует процесс подтверждения того, что
код работает должным образом. В таком приложении, как это, мы можем вручную
посмотреть и увидеть, что страница homepage и страница about page существуют и
содержат предполагаемое содержание. Но как только Django
Группа в ВК "Django_Python"
Chapter 3: Pages app 53
проект начинает расти в размерах и в нем могут быть сотни, если не тысячи отдельных веб-
страниц и идея вручную посетить каждую страницу становится невозможной. Далее,
каждый раз, когда мы вносим изменения в код и добавляем новые функции, обновляем
существующие, или удаляем неиспользуемые области сайта мы хотим быть уверены, что
случайно не сломали какую-то другую часть сайта. Автоматизированные тесты позволяют
нам написать один раз, как мы ожидаем будет работать определенная часть нашего
проекта, а затем пусть компьютер делает проверку за нас.
Если вы посмотрите на наши страницы приложения, Django уже снабжен, tests.py файлом,
который мы можем использовать. Откройте его и добавьте следующий код:
Code
# pages/tests.py
class SimpleTests(SimpleTestCase):
def test_home_page_status_code(self):
response = self.client.get('/')
self.assertEqual(response.status_code, )
def test_about_page_status_code(self):
response = self.client.get('/about/')
self.assertEqual(response.status_code, )
Группа в ВК "Django_Python"
Chapter 3: Pages app 54
для 200 страниц, это стандартный ответ для успешного запроса HTTP. И это
причудливый способ сказать, что гарантированно данная веб-страница реально
существует, но ничего не говорит о содержании указанной страницы.
Для запуска тестов закройте server Control-c и введите python manage.py test в командной
строке:
Command Line
..
----------------------------------------------------------------------
Ran tests in . s
OK
Git и Bitbucket
Группа в ВК "Django_Python"
Chapter 3: Pages app 55
Command Line
Используйте git status, чтобы увидеть все наши изменения кода, а затем git add -A, чтобы
добавить их все. Наконец, мы добавим наше первое сообщение о фиксации.
Command Line
Группа в ВК "Django_Python"
Chapter 3: Pages app 56
Local vs Production
Группа в ВК "Django_Python"
Chapter 3: Pages app 57
Это называется вводом кода в производство (production). Локальный код работает только
на нашем компьютере; производственный код на внешнем сервере.
Есть много доступных поставщиков серверов, но мы будем использовать Heroku, потому
что он бесплатен для небольших проектов, широко используется и имеет относительно
простой процесс развертывания.
Heroku
Вы можете зарегистрировать бесплатный аккаунт на сайте Heroku и после того, как вы
подтвердите свою электронную почту Heroku перенаправит вас в раздел панели
инструментов сайта.
Теперь нам необходимо установить Heroku’s Command Line Interface (CLI), так что мы
можем развернуть его из командной строки. Нам нужно установить Heroku глобально,
чтобы он был доступен на всем нашем компьютере, поэтому откройте новую вкладку
командной строки: Command + t на Mac, Control+ t на Windows. Если бы мы установили
Heroku в нашей виртуальной среде, она была бы доступна только там.
Группа в ВК "Django_Python"
Chapter 3: Pages app 58
Command Line
Для правильной установки 32-разрядной или 64-разрядной версии Windows см. страницу
Heroku CLI.
После завершения установки вы можете закрыть нашу новую вкладку командной строки и
вернуться на начальную вкладку с активной виртуальной средой pages.
Введите команду heroku login и использованную электронную почту и пароль которые вы
указали при регистрации на Heroku.
Command Line
Email: will@wsvincent.com
Password: *********************************
Logged in as will@wsvincent.com
Дополнительный файл
Нам необходимо внести следующие четыре изменения в наш проект Pages, чтобы он был
готов к развертыванию онлайн на Heroku:
• обновить Pipfile.lock
• создать новый файл профиля (Procfile file)
• установить gunicorn как наш веб-сервер
• внести однострочное изменение в settings.py файл
Группа в ВК "Django_Python"
Chapter 3: Pages app 59
Code
# Pipfile
[requires]
Command Line
Command Line
Code
Группа в ВК "Django_Python"
Chapter 3: Pages app 60
Command Line
Code
# pages_project/settings.py
ALLOWED_HOSTS = ['*']
Используйте git status, чтобы проверить наши изменения, добавить новые файлы, а затем
зафиксировать их:
Command Line
И наконец отправим на Bitbucket чтобы у нас была онлайн резервная копия наших изменений кода.
Группа в ВК "Django_Python"
Chapter 3: Pages app 61
Command Line
Deploy (Развертывание)
Заключительный шаг фактически разворачивает на Heroku. Если вы в прошлом
настраивали сервер самостоятельно, то вы будете поражены тем, насколько простой
процесс с провайдером сервис платформы таким как Heroku.
Мы можем сделать первый шаг, создав новое приложение Heroku, из командной строки
heroku create. Heroku создаст случайное имя для нашего приложения, в моем случае это
cryptic-oasis-�����. у вас имя будет другим.
Command Line
s- .git
Теперь нам нужно добавить “hook” для Heroku в git. Это означает, что git сохранит обе
наши настройки для отправки кода на Bitbucket и Heroku. Мое Приложение Heroku
называется cryptic-oasis-����� поэтому моя команда выглядит следующим образом.
Группа в ВК "Django_Python"
Chapter 3: Pages app 62
Command Line
Command Line
Теперь мы можем отправить наш код на Heroku. Потому что ранее мы установили наш
“hook” и он уйдет на Heroku.
Command Line
Если мы просто наберем git push origin master, то код будет перенесен в Bitbucket, а не в
Heroku. Добавив heroku к команде пошлет код на Heroku. Это немного сбивает с толку
первое время.
Наконец, нам необходимо сделать ваше приложение Heroku рабочим. Поскольку веб-сайты
растут в трафике, им нужны дополнительные услуги Heroku, но для нашего основного
примера мы можем использовать самый низкий уровень, web=�, который также является
бесплатным!
Группа в ВК "Django_Python"
Chapter 3: Pages app 63
Command Line
Command Line
Группа в ВК "Django_Python"
Chapter 3: Pages app 64
Вывод
Группа в ВК "Django_Python"
Глава �: Message Board app (Приложение доска объявлений)
В этой главе мы будем использовать базу данных в первый раз, чтобы построить базовое
приложение доска объявлений, где пользователи могут отправлять и читать короткие
сообщения. Мы рассмотрим мощный встроенный интерфейс администратора Django,
который обеспечивает визуальный способ внесения изменений в наши данные. И после
добавления тестов мы будем отправлять наш код в Bitbucket и развернем приложение на
Heroku.
Django предоставляет встроенную поддержку для нескольких типов баз данных. Имея
всего несколько строк в нашем файле settings.py, он может поддерживать PostgreSQL,
MySQL, Oracle или SQLite. Но самым простым на сегодняшний день-является SQLite,
потому что он работает с одним файлом и не требует сложной установки. В отличие от
других, опции которых требуют, чтобы процессы работали в фоновом режиме и могут быть
довольно сложными для настройки. Django использует SQLite по умолчанию и это
идеальный выбор для небольших проектов.
Начальная настройка
Так как мы уже создали несколько проектов Django в этой книге, мы можем быстро
выполнить наши команды, чтобы начать новый проект. Нам необходимо выполнить
следующее:
• создать новый каталог для нашего кода на рабочем столе под названием mb
• установить Django в новой виртуальной среде
• создать новый проект с именем mb_project
• создать новое приложение posts
• обновить settings.py
Группа в ВК "Django_Python"
Chapter 4: Message Board app 66
В новой консоли командной строки введите следующие команды. Обратите внимание, что
я использую здесь (mb) для представления имени виртуальной среды, хотя на самом деле
(mb-XXX), где XXX случайные символы.
Command Line
$ cd ~/Desktop
$ mkdir mb
$ cd mb
$ pipenv shell
Укажите Django о новом приложении posts, добавив его в нижнюю часть раздела
INSTALLED_APPS вашего settings.py файла открыв его в текстовом редакторе.
Code
# mb_project/settings.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'posts', # new
Затем выполните команду migrate, чтобы создать исходную базу данных на основе настроек
Django по умолчанию.
Группа в ВК "Django_Python"
Chapter 4: Message Board app 67
Command Line
Если вы посмотрите в наш каталог с помощью команды ls, вы увидите, что у нас появился
файл db.sqlite� представляющий нашу базу данных SQLite.
Command Line
(mb) $ ls
Отступление: Технически файл db.sqlite� создается при первом запуске migrate или
runserver. Использование runserver формирует базу данных, используя настройки Django
по умолчанию, однако migrate будет синхронизировать базу данных с текущим состоянием
любых моделей баз данных, находящихся в проекте и внесенных в INSTALLED_APPS.
Другими словами, чтобы убедиться, что база данных отражает текущее состояние проекта,
необходимо использовать migrate (а также makemigrations) при каждом обновлении
модели. Более подробно об этом чуть позже.
Чтобы убедиться, что все работает правильно, запустите наш локальный сервер.
Command Line
Группа в ВК "Django_Python"
Chapter 4: Message Board app 68
Группа в ВК "Django_Python"
Chapter 4: Message Board app 69
# posts/models.py
Django импортирует модуль models, чтобы помочь нам построить новые модели баз
данных, которые будут “моделировать” характеристики данных в нашей базе данных. Мы
хотим создать модель для хранения текстового содержимого сообщений в доске
объявлений, которую мы можем выполнить следующим образом:
Code
# posts/models.py
class Post(models.Model):
text = models.TextField()
Обратите внимание, что мы создали новую модель базы данных, которая имеет текстовое поле
данных. Мы также определили тип контента, который он будет содержать, TextField (). Django
предоставляет множество полей модели, поддерживающих общие типы контента, такие как
символы, даты, целые числа, электронные письма и так далее.
Активация моделей
Теперь, когда наша новая модель создана, нам нужно ее активировать. В будущем, когда мы
создаем или изменяем существующую модель необходимо обновлять Django в два этапа.
Группа в ВК "Django_Python"
Chapter 4: Message Board app 70
Command Line
Обратите внимание, что вам не нужно включать имя после makemigrations или migrate.
Если вы просто запустите команды, то они будут применены ко всем доступным
изменениям. Это хорошая привычка, чтобы быть точным. Если бы у нас было два
отдельных приложения в нашем проекте, и мы обновили модели в обоих, а затем запустили
makemigrations, это создало бы файл миграции, содержащий данные об обоих изменениях.
Это усложняет отладку в будущем. Вам потребуется, чтобы каждый файл миграции был как
можно меньше и возможно отдельным. Таким образом, если вам нужно просмотреть
прошлые миграции, есть только одно изменение на миграцию, а не одно, которое
применяется к нескольким приложениям.
Django Admin
Command Line
Email:
Password:
Password (again):
Группа в ВК "Django_Python"
Chapter 4: Message Board app 72
Войдите в систему, введя имя пользователя и пароль, которые вы только что создали. Далее
вы увидите домашнюю страницу администратора Django:
Группа в ВК "Django_Python"
Chapter 4: Message Board app 73
Admin homepage
Группа в ВК "Django_Python"
Chapter 4: Message Board app 74
Code
# posts/admin.py
admin.site.register(Post)
Django теперь знает, что он должен отображать наше posts приложение и его модель базы
данных Post на странице администратора. Если вы обновите свой браузер, вы увидите, что
теперь оно появилось:
Теперь давайте создадим наш первый пост в доске объявлений для нашей базы данных.
Нажмите на кнопку + Add напротив Posts. Введите свой текст в текстовое поле.
Группа в ВК "Django_Python"
Chapter 4: Message Board app 75
Затем нажмите кнопку "Save", которая перенаправит вас на главную страницу Post. Однако,
если вы посмотрите внимательно, то есть проблема: Наша новая запись называется “Post
object”, что не очень полезно.
Группа в ВК "Django_Python"
Chapter 4: Message Board app 76
Давайте изменим эту ситуацию. В файле posts/models.py добавьте новую функцию __str__
как в примере:
Code
# posts/models.py
class Post(models.Model):
text = models.TextField()
def __str__(self):
"""Строковое отображение модели """
return self.text[:��]
Группа в ВК "Django_Python"
Chapter 4: Message Board app 77
Гораздо лучше! Рекомендуется добавлять методы str () ко всем моделям, чтобы улучшить
их читаемость.
Views/Templates/URLs
Для того, чтобы отобразить содержимое нашей базы данных на нашей домашней странице,
мы должны подключить наши views, templates и URLConfs. Сейчас этот образец должен
начать казаться знакомым.
Группа в ВК "Django_Python"
Chapter 4: Message Board app 78
Code
# posts/views.py
class HomePageView(ListView):
model = Post
template_name = 'home.html'
В первой строке мы импортируем ListView, а во второй строке нам нужно явно определить,
какую модель мы используем. В view мы создаем подкласс ListView, указываем название
модели и указываем ссылку на шаблон. Внутри ListView возвращает объект с именем
object_list, который мы хотим отобразить в нашем шаблоне (template).
Наш view готов, что означает, что нам все еще нужно настроить наши URL-адреса и сделать
наш шаблон(template). Начнем с шаблона. Создадим каталог(папку) на уровне проекта с
именем templates и файл шаблона home.html.
Command Line
Затем обновите поле DIRS в settings.py файле, чтобы Django знал, что нужно искать в этой
папке шаблонов.
Группа в ВК "Django_Python"
Chapter 4: Message Board app 79
Code
# settings.py
TEMPLATES = [
...
...
},
Code
<ul>
{% endfor %}
</ul>
Последний шаг заключается в том, чтобы настроить наш URLConfs. Давайте начнем с
файла urls.py на уровне проекта где мы просто подключаем include нашего posts и
добавляем include во вторую строку.
Группа в ВК "Django_Python"
Chapter 4: Message Board app 80
Code
# mb_project/urls.py
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('posts.urls')),
Command Line
Code
# posts/urls.py
urlpatterns = [
Группа в ВК "Django_Python"
Chapter 4: Message Board app 81
http://127.0.0.1:8000/admin/
Группа в ВК "Django_Python"
Chapter 4: Message Board app 82
Admin entry
Группа в ВК "Django_Python"
Chapter 4: Message Board app 83
Admin entry
Группа в ВК "Django_Python"
Chapter 4: Message Board app 84
Все работает так, что самое время инициализировать наш каталог, добавить новый код и
Группа в ВК "Django_Python"
Chapter 4: Message Board app 85
Command Line
Tests
Раньше мы тестировали только статические страницы, поэтому мы использовали
SimpleTestCase(простой тест). Но теперь, когда наша домашняя страница работает с базой
данных, нам нужно использовать TestCase, которая позволит нам создать «тестовую» базу
данных, которую мы можем проверить. Другими словами, нам не нужно запускать тесты в
нашей реальной базе данных, но вместо этого можно создать отдельную тестовую базу
данных, заполнить ее образцами данных, а затем протестировать ее.
Начнем с добавления образца записи в текстовое поле базы данных, а затем проверим,
правильно ли она хранится в базе данных. Важно, чтобы все наши методы тестирования
начинались с test_, чтобы Django знал что тестировать! Код будет выглядеть следующим
образом:
Code
# posts/tests.py
class PostModelTest(TestCase):
def setUp(self):
Post.objects.create(text='just a test')
Группа в ВК "Django_Python"
Chapter 4: Message Board app 86
def test_text_content(self):
post=Post.objects.get(id= )
expected_object_name = f'{post.text}'
В верхней части мы импортируем модуль TestCase, который позволяет нам создать образец
базы данных, а затем импортировать нашу Post модель. Мы создаем новый класс
PostModelTest и добавляем метод setUp для создания новой базы данных, которая имеет
только одну запись: сообщение с текстовым полем, содержащим строку 'just a test'.
Затем мы запускаем наш первый тест, test_text_content, чтобы проверить, что поле базы
данных на самом деле содержит только тест. Мы создаем переменную post, которая
представляет первый идентификатор (id) в нашей модели Post. Запомните, что Django
автоматически устанавливает этот id для нас. Если бы мы создали еще одну запись, у нее
был бы идентификатор 2, следующий был бы 3 и так далее.
Следующая строка использует f strings которая является очень классным дополнением к
Python 3.6. Она позволяет помещать переменные непосредственно в строки, если
переменные окружены фигурными скобками {}. Здесь мы устанавливаем
expected_object_name как строку значения в post.text, который должен быть просто тест.
Группа в ВК "Django_Python"
Chapter 4: Message Board app 87
Command Line
----------------------------------------------------------------------
Ran test in . s
OK
Прошло!
Время для нашего второго теста. Первый тест был для модели, но теперь мы хотим
проверить нашу единственную страницу: домашнюю страницу (homepage). В частности, мы
хотим проверить, что она существует (throws an HTTP 200 response), использует view home
и использует home.html шаблон(template).
Нам нужно добавить еще один импорт наверху для reverse и совершенно новый класс
HomePageViewTest для нашего теста.
Группа в ВК "Django_Python"
Chapter 4: Message Board app 88
Code
class PostModelTest(TestCase):
def setUp(self):
Post.objects.create(text='just a test')
def test_text_content(self):
post=Post.objects.get(id= )
expected_object_name = f'{post.text}'
class HomePageViewTest(TestCase):
def setUp(self):
def test_view_url_exists_at_proper_location(self):
resp = self.client.get('/')
self.assertEqual(resp.status_code, )
def test_view_url_by_name(self):
resp = self.client.get(reverse('home'))
self.assertEqual(resp.status_code, )
Группа в ВК "Django_Python"
Chapter 4: Message Board app 89
def test_view_uses_correct_template(self):
resp = self.client.get(reverse('home'))
self.assertEqual(resp.status_code, )
self.assertTemplateUsed(resp, 'home.html')
Если вы запустите наши тесты снова, вы должны увидеть, что они проходят.
Command Line
----------------------------------------------------------------------
Ran tests in . s
OK
Почему там написано четыре теста? Запомните, что наш setUp метод на самом деле не тест,
он просто позволяет нам запускать последующие тесты. Наши четыре реальных теста это
test_test_content, test_view_url_exists_at_proper_location, test_view_url_by_name, и
test_view_-uses_correct_template.
Любая функция, имеющая в начале слово test* в существующем файле tests.py будет
запущена при выполнении команды python manage.py test.
Мы закончили добавление кода для нашего тестирования, пришло время внести изменения
в git.
Группа в ВК "Django_Python"
Chapter 4: Message Board app 90
Command Line
Bitbucket
Нам также нужно сохранить наш код на Bitbucket. Это хорошая привычка, чтобы
сохранить код в случае, если что-нибудь случится с вашим локальным компьютером, и это
также позволяет вам делиться и сотрудничать с другими разработчиками.
У Вас уже должна быть учетная запись Bitbucket из главы 3, поэтому создайте новый
репозиторий, который мы назовем mb-app.
Группа в ВК "Django_Python"
Chapter 4: Message Board app 91
Это должно выглядеть так, замените wsvincent (мое имя пользователя)на ваш логин в
системе bitbucket :
Command Line
Heroku configuration
Вы также должны уже иметь настройки учетной записи Heroku установленные из главы 3.
Нам необходимо внести следующие изменения в наш проект доски объявлений, чтобы
развернуть его в интернете:
• обновить Pipfile.lock
• новый Procfile
• установить gunicorn
• обновить settings.py
В вашем Pipfile укажите версию Python мы используем �.�. Добавьте эти две строки в
конец файла.
Code
# Pipfile
[requires]
Группа в ВК "Django_Python"
Chapter 4: Message Board app 92
Command Line
Затем создайте Procfile, который указывает Heroku, как запустить удаленный сервер, где
наш код будет работать.
Command Line
Command Line
Далее установим gunicorn который мы будем использовать для production но при этом
используя внутренний сервер Django для локальной разработки.
Command Line
file. Code
# mb_project/settings.py
ALLOWED_HOSTS = ['*']
Группа в ВК "Django_Python"
Chapter 4: Message Board app 93
Command Line
Heroku развертывание
Command Line
Затем запустите команду heroku create и Heroku случайным образом сгенерирует для вас
имя приложения. Вы сможете настроить это позже, если будет необходимо.
Command Line
.git
Группа в ВК "Django_Python"
Chapter 4: Message Board app 94
Command Line
Command Line
Command Line
Если вы откроете новый проект heroku open, он автоматически запустит новое окно
браузера с URL вашего приложения. Мой находится по адресу:
https://agile-inlet-25811.herokuapp.com/.
Live site
Группа в ВК "Django_Python"
Chapter 4: Message Board app 95
Вывод
Группа в ВК "Django_Python"
ϏҵҪҬҪ�:Blogapp ҹҺҲҵҸҰүҷҲүύҵҸҭ
ώ ӇҼҸҳ ҭҵҪҬү ҶӅ ҹҸһҼҺҸҲҶ ҹҺҲҵҸҰүҷҲү ҴҸҼҸҺҸү ҹҸұҬҸҵӉүҼ ҹҸҵӆұҸҬҪҼүҵӉҶ һҸұҮҪҬҪҼӆ
ҺүҮҪҴҼҲҺҸҬҪҼӆ Ҳ ҽҮҪҵӉҼӆ һҸҸҫӃүҷҲӉ ϙҪ ҭҵҪҬҷҸҳ һҼҺҪҷҲӀү ҫҽҮҽҼ ҹүҺүӁҲһҵүҷӅ Ҭһү
һҸҸҫӃүҷҲӉ Ҭ ҫҵҸҭү Ҳ ҮҵӉ ҴҪҰҮҸҭҸ ҸҼҮүҵӆҷҸҭҸ һҸҸҫӃүҷҲӉ ҫҽҮүҼ ҬӅҮүҵүҷҪ ҸҼҮүҵӆҷҪӉ
һҼҺҪҷҲӀҪϘӅҼҪҴҰүҹҸұҷҪҴҸҶҲҶһӉһ$44ҮҵӉһҼҲҵҲұҪӀҲҲҲҽұҷҪүҶ ҴҪҴ%KBOHPҺҪҫҸҼҪүҼһҸ
һҼҪҼҲӁүһҴҲҶҲҾҪҳҵҪҶҲ
ϙҪӁҪҵӆҷҪӉҷҪһҼҺҸҳҴҪ
Как описано в предыдущих главах, наши шаги для создания нового проекта Django будут
выглядеть следующим образом:
• Создать новую папку для нашего проекта на рабочем столе с именем blog
И не забудьте указать пробел с точкой ". " в конце команды для создания нашего нового
blog_project. (прм. переводчика. Создает проект Django в существующей директории без
создания новой папки, не обязательно)
Группа в ВК "Django_Python"
Chapter 5: Blog app 97
Command Line
$ cd ~/Desktop
$ mkdir blog
$ cd blog
$ pipenv shell
Чтобы убедиться, что Django знает о нашем новом приложении, откройте текстовый
редактор и добавьте новое приложение в INSTALLED_APPS в нашем settings.py файле:
Code
# blog_project/settings.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'blog', # new
Группа в ВК "Django_Python"
Chapter 5: Blog app 98
Хорошо, первичная настройка закончена! Далее мы создадим модель базы данных для
записей блога.
Группа в ВК "Django_Python"
Chapter 5: Blog app 99
Code
# blog/models.py
class Post(models.Model):
title = models.CharField(max_length= )
author = models.ForeignKey(
'auth.User',
on_delete=models.CASCADE,
body = models.TextField()
def __str__(self):
return self.title
Для title мы ограничиваем длину до 200 символов, а для body мы используем текстовое
поле, которое будет автоматически расширяться по мере необходимости, чтобы
соответствовать тексту пользователя. В Django доступно много типов полей; вы можете
увидеть полный список здесь.
Группа в ВК "Django_Python"
Chapter 5: Blog app 100
Теперь, когда наша новая модель базы данных создана, нам нужно создать для нее новую
запись миграции и перенести изменения в нашу базу данных. Это двухэтапный процесс и
может быть выполнен следующими командами:
Command Line
Admin
Нам нужен способ доступа к нашим данным. Войдем в Django админ! Но сначала создадим
учетную запись суперпользователя, введя приведенную ниже команду и после отвечая на
запросы введем адрес электронной почты и пароль. Обратите внимание, что при вводе
пароля он не будет отображаться на экране по соображениям безопасности.
Command Line
Email:
Password:
Password (again):
Теперь снова запустите сервер Django с помощью команды python manage.py runserver и
откройте Django админ http://127.0.0.1:8000/admin/. Войдите с новой учетной
записью суперпользователя.
Группа в ВК "Django_Python"
Chapter 5: Blog app 101
Admin homepage
Code
# blog/admin.py
admin.site.register(Post)
Группа в ВК "Django_Python"
Chapter 5: Blog app 102
Admin homepage
Давайте добавим два сообщения в блог, чтобы у нас были примеры данных для работы.
Нажмите кнопку + Add рядом с Posts чтобы создать новую запись. Не забудьте добавить
“author” к каждому сообщению, так как по умолчанию все поля модели обязательны для
заполнения. Если вы попытаетесь ввести сообщение без автора вы увидите ошибку. Если
мы захотим изменить это, мы можем добавить field options(параметры поля) в нашу
модель, чтобы сделать это поле необязательным или заполнить его значением по
умолчанию
Группа в ВК "Django_Python"
Chapter 5: Blog app 103
Первый пост
Группа в ВК "Django_Python"
Chapter 5: Blog app 104
Второй пост
Группа в ВК "Django_Python"
Chapter 5: Blog app 105
Теперь, когда наша модель базы данных завершена, нам нужно создать необходимые view,
URL-адреса и шаблоны, чтобы мы могли отображать информацию в нашем веб-
приложении.
URLs
Группа в ВК "Django_Python"
Chapter 5: Blog app 106
Command Line
Code
# blog/urls.py
urlpatterns = [
Мы импортируем views (которые скоро создадим) в верхней части. Пустая строка ''
говорит Python что соответствует всем значениям, далее мы делаем URL именованным
home, к которому мы можем обратиться в наших views позже. Хотя это не обязательно но
добавление имени к URL это хорошая практика которую необходимо принять так как это
помогает сохранять организованность когда количество ваших URL растет.
Также мы должны обновить файл urls.py на уровне проекта, чтобы он мог пересылать все
запросы непосредственно на blog приложение.
Группа в ВК "Django_Python"
Chapter 5: Blog app 107
Code
# blog_project/urls.py
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('blog.urls')),
Views
Группа в ВК "Django_Python"
Chapter 5: Blog app 108
Code
# blog/views.py
class BlogListView(ListView):
model = Post
template_name = 'home.html'
ώҮҬҽҿҬүҺҿҷҲҿһҼҺҸҴҪҿҶӅҲҶҹҸҺҼҲҺҽүҶ-JTU7JFXҲҷҪӂҽҶҸҮүҵӆҫҪұӅҮҪҷҷӅҿ1PTUϓҪҼүҶ
ҶӅһҸұҮҪүҶҹҸҮҴҵҪһһ-JTU7JFXҲҮҸҫҪҬҵӉүҶһһӅҵҴҲҷҪҷҪӂҽҶҸҮүҵӆҲӂҪҫҵҸҷҧҼҸӇҴҸҷҸҶҲҼ
ҷҪҶҶҷҸҭҸҴҸҮҪҹҸһҺҪҬҷүҷҲӈһҺүҪҵҲұҪӀҲүҳҬһүҭҸӇҼҸҭҸһҷҽҵӉ
Templates ӂҪҫҵҸҷӅ
ϞүҹүҺӆ һ ҷҪӂҲҶ 63-$POGT Ҳ WJFXT ұҪҴҸҷӁҲҵҲ ҷҪҶ ҷү ҿҬҪҼҪүҼ ҼҸҵӆҴҸ ҼҺүҼӆүҳ ӁҪһҼҲ
ҭҸҵҸҬҸҵҸҶҴҲӂҪҫҵҸҷҸҬ UFNQMBUFT ϖҪҴҶӅҽҰүузнали изҭҵҪҬы ҶӅҶҸҰүҶҷҪһҵүҮҸҬҪҼӆҸҼ
ҮҺҽҭҲҿ ӂҪҫҵҸҷҸҬ ӁҼҸҫӅ ҮүҺҰҪҼӆ наш ҴҸҮ Ҭ ӁҲһҼҸҼү ϛҸӇҼҸҶҽ ҷҪӁҷүҶ һ ҾҪҳҵҪ CBTFIUNM Ҳ
ҾҪҳҵҪ IPNFIUNM ҴҸҼҸҺӅҳ ҷҪһҵүҮҽүҼһӉ ҸҼ ҷүҭҸ ϛҸұҰү ҴҸҭҮҪ ҶӅ ҮҸҫҪҬҲҶ ӂҪҫҵҸҷӅ ҮҵӉ
һҸұҮҪҷҲӉҲҺүҮҪҴҼҲҺҸҬҪҷҲӉһҸҸҫӃүҷҲҳҫҵҸҭҪ ҸҷҲҼҪҴҰүҶҸҭҽҼҷҪһҵүҮҸҬҪҼӆһӉҸҼbase.html.
Группа в ВК "Django_Python"
Chapter 5: Blog app 109
Command Line
Затем обновите settings.py чтобы Django знал, где искать наши шаблоны.
Code
# blog_project/settings.py
TEMPLATES = [
...
...
},
Code
<html>
<head>
<title>Django blog</title>
</head>
<body>
<header>
</header>
Группа в ВК "Django_Python"
Chapter 5: Blog app 110
<div class="container">
{% block content %}
{% endblock content %}
</div>
</body>
</html>
Обратите внимание на то, что код между {% block content %} и {% endblock content %} может
быть заполнен другими шаблонами. Говоря об этом, вот код для home.html.
Code
{% extends 'base.html' %}
{% block content %}
<div class="post-entry">
</div>
{% endfor %}
{% endblock content %}
Группа в ВК "Django_Python"
Chapter 5: Blog app 111
Нам нужно добавить CSS, который называется статическим файлом, потому что, в отличие
от нашего динамического контента базы данных, он не изменяется. К счастью добавлять,
статические файлы, такие как CSS, JavaScript и изображения в наш проект Django очень
просто.
В готовом к производству Django проекте вы, как правило, храните его в сети доставки
контента (CDN) для лучшей производительности, но для наших целей хранение файлов
локально это нормально.
Сначала закройте наш локальный сервер с Control-c. Затем создайте папку на уровне
проекта с именем static.
Группа в ВК "Django_Python"
Chapter 5: Blog app 112
Command Line
Как и в нашей папке с шаблонами, нам нужно обновить settings.py, чтобы сообщить Django,
где искать эти статические файлы. Мы можем обновить settings.py с изменением строки для
STATICFILES_DIRS. Добавьте его в нижнюю часть файла под заголовком STATIC_URL.
Code
# blog_project/settings.py
Теперь создайте папку css в static и добавьте в нее новый файл base.css.
Command Line
Что мы должны поместить в ваш файл? Как насчет изменения title на красный?
Code
/* static/css/base.css */
header h1 a {
color: red;
Последний шаг. Нам нужно добавить статические файлы в ваши шаблоны, добавив {% load
staticfiles %} в начало base.html. Потому что другие наши шаблоны наследуются от base.html
мы должны добавить это только один раз. Добавьте новую строку в нижней части кода
<head>< / head>, которая явно ссылается на наш новый файл base.css.
Группа в ВК "Django_Python"
Chapter 5: Blog app 113
Code
{% load static %}
<html>
<head>
<title>Django blog</title>
</head>
...
УФ! Это было немного больно, но это одноразовая боль. Теперь мы можем добавить
статические файлы в нашу папку static, и они автоматически появятся во всех наших
шаблонах.
Запустите сервер снова с python manage.py runserver и посмотрите на нашем обновленном
сайте http://127.0.0.1:8000/.
Мы можем сделать немного лучше. Как насчет того, чтобы добавить пользовательский
шрифт и еще немного CSS? Поскольку эта книга не является учебником по CSS, просто
вставьте следующее между тегами <head>< / head>, чтобы добавить Source Sans Pro,
бесплатный шрифт от Google.
Группа в ВК "Django_Python"
Chapter 5: Blog app 114
Code
{% load static %}
<html>
<head>
<title>Django blog</title>
stylesheet">
</head>
...
Code
/* static/css/base.css */
body {
font-size: px;
header {
border-bottom: px solid # ;
margin-bottom: rem;
display: flex;
header h1 a {
color: red;
Группа в ВК "Django_Python"
Chapter 5: Blog app 115
text-decoration: none;
.nav-left {
margin-right: auto;
.nav-right {
display: flex;
padding-top: rem;
.post-entry {
margin-bottom: rem;
.post-entry h2 {
margin: . rem ;
.post-entry h2 a,
.post-entry h2 a:visited {
color: blue;
text-decoration: none;
.post-entry p {
margin: ;
Группа в ВК "Django_Python"
Chapter 5: Blog app 116
font-weight: ;
.post-entry h2 a:hover {
color: red;
Группа в ВК "Django_Python"
Chapter 5: Blog app 117
Code
# blog/views.py
class BlogListView(ListView):
model = Post
template_name = 'home.html'
class BlogDetailView(DetailView):
model = Post
template_name = 'post_detail.html'
Группа в ВК "Django_Python"
Chapter 5: Blog app 118
Command Line
Code
{% extends 'base.html' %}
{% block content %}
<div class="post-entry">
</div>
{% endblock content %}
В верхней части мы указываем, что этот шаблон наследуется от base.html. Затем отобразите
title и body из нашего объекта контекста, который DetailView делает доступным как post.
Лично я нашел именование объектов контекста в общих представлениях чрезвычайно
запутанным при первом изучении Django. Поскольку наш объект контекста из подробного
представления является либо вашим именем модели post, либо объектом, мы также можем
обновить наш шаблон следующим образом, и он будет работать точно так же.
Группа в ВК "Django_Python"
Chapter 5: Blog app 119
Code
{% extends 'base.html' %}
{% block content %}
<div class="post-entry">
</div>
{% endblock content %}
Если вы обнаружите, что использование post или object сбивает с толку, мы также можем
явно задать имя объекта контекста в нашем представлении. Поэтому, если бы мы хотели
назвать его anything_you_want, а затем использовать его в шаблоне, код выглядел бы
следующим образом, и он работал бы так же.
Code
# blog/views.py
...
class BlogDetailView(DetailView):
model = Post
template_name = 'post_detail.html'
context_object_name = 'anything_you_want'
Группа в ВК "Django_Python"
Chapter 5: Blog app 120
Code
{% extends 'base.html' %}
{% block content %}
<div class="post-entry">
</div>
{% endblock content %}
Code
# blog/urls.py
urlpatterns = [
Группа в ВК "Django_Python"
Chapter 5: Blog app 121
Все записи в блоге будут начинаться с post/. Далее идет первичный ключ для нашей записи
post, которая будет представлена в виде целого числа <int: pk>. Вероятно вы спросите что
это за первичный ключ? Django автоматически добавляет автоматически увеличивающийся
первичный ключ к нашим моделям баз данных. Таким образом, как только мы объявили
название поля, author и body в нашей модели Post, Django под капотом также добавил еще
одно поле под названием id, который является нашим первичным ключом. Мы можем
получить к нему доступ как id или pk.
Этот pk для нашего первого поста "Привет, Мир" равен 1. Для второго поста это 2. и так
далее. Поэтому, когда мы переходим на страницу отдельной записи для нашего первого
сообщения, мы можем ожидать, что его url шаблон будет post/1.
Примечание: понимание того, как первичные ключи работают с DetailView является очень
распространенной путаницей для начинающих. Стоит перечитать предыдущие два абзаца
несколько раз, если не понимаете. С практикой это станет второй натурой.
Если теперь запустить сервер с python manage.py runserver и перейти непосредственно к
http://127.0.0.1:8000/post/1/ вы увидите специальную страницу для нашего первого
поста в блоге.
Группа в ВК "Django_Python"
Chapter 5: Blog app 122
Code
{% extends 'base.html' %}
{% block content %}
<div class="post-entry">
</div>
{% endfor %}
{% endblock content %}
Мы начинаем с того, что говорим нашему шаблону Django, что мы хотим ссылаться на
URLConf, используя код {%url ... %}. Какой URL? Тот, который называется post_detail,
который мы назвали BlogDetailView в нашей url-конфигурации всего минуту назад. Если
мы посмотрим на post_detail в нашем URLConf, мы увидим, что он ожидает, что будет
передан аргумент pk, представляющий первичный ключ для записи блога. К счастью,
Django уже создал и включил это поле pk в наш объект post. Мы передаем его в URLConf,
добавляя его в шаблон как post.pk.
Тесты
Сейчас нам нужно протестировать нашу модель и представления. Мы хотим убедиться, что
модель Post работает должным образом, включая ее представление. И мы хотим
протестировать как ListView, так и DetailView.
Группа в ВК "Django_Python"
Chapter 5: Blog app 123
Code
# blog/tests.py
class BlogTests(TestCase):
def setUp(self):
self.user = get_user_model().objects.create_user(
username='testuser',
email='test@email.com',
password='secret'
self.post = Post.objects.create(
author=self.user,
def test_string_representation(self):
self.assertEqual(str(post), post.title)
Группа в ВК "Django_Python"
Chapter 5: Blog app 124
def test_post_content(self):
self.assertEqual(f'{self.post.author}', 'testuser')
def test_post_list_view(self):
response = self.client.get(reverse('home'))
self.assertEqual(response.status_code, )
self.assertTemplateUsed(response, 'home.html')
def test_post_detail_view(self):
self.assertEqual(response.status_code, )
self.assertEqual(no_response.status_code, )
self.assertTemplateUsed(response, 'post_detail.html')
Группа в ВК "Django_Python"
Chapter 5: Blog app 125
Наконец test_post_detail_view проверяет, что наша страница работает должным образом и
что неправильная страница возвращает 404. Всегда хорошо проверить, что что-то
существует, и что что-то неправильное не существует в ваших тестах.
Продолжайте и выполните эти тесты сейчас. Они все должны быть пройдены
Command Line
Git
Сейчас самое время для нашего первого git commit. Сначала инициализируйте
наш каталог.Command Line
Command Line
Conclusion
Мы создаем простое приложение блог с нуля! С помощью администратора Django мы
можем создавать, редактировать или удалять контент. И мы использовали DetailView
впервые создав детальное отдельное представление каждого поста блога.
Группа в ВК "Django_Python"
Chapter 5: Blog app 126
Группа в ВК "Django_Python"
Глава 6: Формы
В этой главе мы продолжим работу над нашим приложением блога из главы 5, добавив
формы, чтобы пользователь мог создавать, редактировать или удалять любую из своих
записей блога.
Формы
Формы очень распространены и очень сложны для правильной реализации. Каждый раз,
когда вы принимаете пользовательский ввод, возникают проблемы безопасности (XSS
Атаки), требуется правильная обработка ошибок, а также вопросы пользовательского
интерфейса о том, как предупредить пользователя о проблемах с формой. Не говоря уже о
необходимости перенаправления при успехе.
К счастью для нас, встроенные формы Django абстрагируют большую часть сложности и
предоставляют богатый набор инструментов для обработки распространенных случаев
использования, работающих с формами.
Чтобы начать, обновите наш базовый шаблон, чтобы отобразить ссылку на страницу для
ввода новых сообщений в блоге. Он примет фрму <a href= "{% url 'post_new'%} " ></a>, где
post_new-это имя нашего URL.
Группа в ВК "Django_Python"
Chapter 6: Forms 128
Code
{% load staticfiles %}
<html>
<head>
<title>Django blog</title>
="stylesheet">
</head>
<body>
<div class="container">
<header>
<div class="nav-left">
</div>
<div class="nav-right">
</div>
</header>
{% block content %}
{% endblock content %}
</div>
</body>
</html>
Группа в ВК "Django_Python"
Chapter 6: Forms 129
Code
# blog/urls.py
urlpatterns = [
Ваш url будет начинаться с post / new/, представление называется Blog Create View, и url
будет называться post_new. Просто, правда?
Теперь давайте создадим наше представление, импортировав новый универсальный класс
под названием Create View, а затем создадим его подкласс для создания нового
представления с именем BlogCreateView.
Code
# blog/views.py
class BlogListView(ListView):
model = Post
template_name = 'home.html'
Группа в ВК "Django_Python"
Chapter 6: Forms 130
class BlogDetailView(DetailView):
model = Post
template_name = 'post_detail.html'
class BlogCreateView(CreateView):
model = Post
template_name = 'post_new.html'
fields = '__all__'
В BlogCreateView мы указываем нашу модель базы данных Post, имя нашего шаблона
post_new.html и все поля с '__all__', так как у нас только два: title и author. Последний шаг -
создать наш шаблон, который мы назовем post_new.html.
Command Line
Группа в ВК "Django_Python"
Chapter 6: Forms 131
Code
{% extends 'base.html' %}
{% block content %}
<h1>New post</h1>
{{ form.as_p }}
</form>
{% endblock %}
Для просмотра нашей работы запустите сервер с python manage.py runserver и перейдите на
домашнюю страницу по адресу http://127.0.0.1:8000/.
Группа в ВК "Django_Python"
Chapter 6: Forms 132
Нажмите на нашу ссылку "+ New Blog Post", которое перенаправит вас
на: http://127.0.0.1:8000/post/new/.
Группа в ВК "Django_Python"
Chapter 6: Forms 133
Группа в ВК "Django_Python"
Chapter 6: Forms 134
Группа в ВК "Django_Python"
Chapter 6: Forms 135
Группа в ВК "Django_Python"
Chapter 6: Forms 136
Откройте models.py файл. Добавьте импорт во второй строке для reverse и новый метод
get_-absolute_url.
Command Line
# blog/models.py
class Post(models.Model):
title = models.CharField(max_length= )
author = models.ForeignKey(
'auth.User',
on_delete=models.CASCADE,
body = models.TextField()
def __str__(self):
return self.title
def get_absolute_url(self):
Группа в ВК "Django_Python"
Chapter 6: Forms 137
Code
Это означает, что для того, чтобы этот маршрут работал, мы должны также передать
аргумент с ключом pk или первичным ключом объекта. Запутанно что pk и id
взаимозаменяемы в Django, хотя документация Django рекомендуют использовать self.id с
параметром get_absolute_url. Поэтому мы сообщаем Django, что конечным
местоположением записи Post является ее представление post_detail, которое представляет
собой posts / <int: pk> /, поэтому маршрут для первой созданной нами записи будет
находиться в posts / 1.
Попробуйте создать новую запись в блоге еще раз по адресу http://127.0.0.1:8000/post/new/,
и в случае успеха вы будете перенаправлены на страницу подробного просмотра, где
размещена запись.
Группа в ВК "Django_Python"
Chapter 6: Forms 138
Вы также заметите, что наш предыдущий пост в блоге тоже есть. Он был успешно
отправлен в базу данных, но Django не знал, как перенаправить нас после этого.
Форма обновления
Процесс создания формы обновления, чтобы пользователи могли редактировать
сообщения в блоге, должен быть знакомым. Мы снова будем использовать встроенное
общее представление на основе классов Django UpdateView и создадим необходимый
шаблон, URL и представление.
Группа в ВК "Django_Python"
Chapter 6: Forms 139
Code
{% extends 'base.html' %}
{% block content %}
<div class="post-entry">
</div>
{% endblock content %}
Мы добавили ссылку, используя <a href> ... </a> и тег движка шаблонов Django {% url ...%}.
В нем мы указали целевое имя нашего URL, которое будет называться post_edit, а также
передали необходимый параметр, который является первичным ключом поста post.pk.
Command Line
Группа в ВК "Django_Python"
Chapter 6: Forms 140
Code
{% extends 'base.html' %}
{% block content %}
<h1>Edit post</h1>
{{ form.as_p }}
</form>
{% endblock %}
Code
# blog/views.py
class BlogListView(ListView):
model = Post
template_name = 'home.html'
Группа в ВК "Django_Python"
Chapter 6: Forms 141
class BlogDetailView(DetailView):
model = Post
template_name = 'post_detail.html'
class BlogCreateView(CreateView):
model = Post
template_name = 'post_new.html'
fields = '__all__'
class BlogUpdateView(UpdateView):
model = Post
template_name = 'post_edit.html'
Группа в ВК "Django_Python"
Chapter 6: Forms 142
Code
# blog/urls.py
urlpatterns = [
path('post/<int:pk>/edit/',
views.BlogUpdateView.as_view(), name='post_edit'),
Группа в ВК "Django_Python"
Chapter 6: Forms 143
Страница редактирования
Группа в ВК "Django_Python"
Chapter 6: Forms 144
Группа в ВК "Django_Python"
Chapter 6: Forms 145
Удаление View
Процесс создания формы для удаления записей блога очень похож на процесс обновления
записи. Мы будем использовать еще одно общее представление на основе классов,
DeleteView, для создания представления, url-адреса и шаблона функциональности.
Давайте начнем с добавления ссылки для удаления записей блога на Вашей странице
блога,post_-detail.html.
Группа в ВК "Django_Python"
Chapter 6: Forms 146
Code
{% extends 'base.html' %}
{% block content %}
<div class="post-entry">
</div>
{% endblock content %}
Затем создайте новый файл для нашего шаблона удаления страницы. Сначала выйдите из
локального сервера Control-c, а затем введите следующую команду:
Command Line
Группа в ВК "Django_Python"
Chapter 6: Forms 147
Code
{% extends 'base.html' %}
{% block content %}
<h1>Delete post</h1>
</form>
{% endblock %}
Обратите внимание, что мы используем post.title для отображения заголовка нашего блога.
Мы также могли бы просто использовать object.title, поскольку он также предоставляется
DetailView.
Теперь обновите наш файл views.py, импортировав DeleteView и reverse_lazy вверху, затем
создайте новое представление, которое подкласс DeleteView.
Code
# blog/views.py
class BlogListView(ListView):
model = Post
Группа в ВК "Django_Python"
Chapter 6: Forms 148
template_name = 'home.html'
class BlogDetailView(DetailView):
model = Post
template_name = 'post_detail.html'
class BlogCreateView(CreateView):
model = Post
template_name = 'post_new.html'
fields = '__all__'
class BlogUpdateView(UpdateView):
model = Post
template_name = 'post_edit.html'
class BlogDeleteView(DeleteView):
model = Post
template_name = 'post_delete.html'
success_url = reverse_lazy('home')
Группа в ВК "Django_Python"
Chapter 6: Forms 149
Code
# blog/urls.py
urlpatterns = [
path('post/<int:pk>/edit/',
views.BlogUpdateView.as_view(), name='post_edit'),
path('post/<int:pk>/delete/',
views.BlogDeleteView.as_view(), name='post_delete'),
Группа в ВК "Django_Python"
Chapter 6: Forms 150
При нажатии на ссылку мы попадаем на страницу удаления записи блога, где отображается
название записи блога.
Группа в ВК "Django_Python"
Chapter 6: Forms 151
Tests
Время для тестов, чтобы убедиться, что все работает сейчас–и в будущем-как и ожидалось.
Мы добавили метод get_absolute_url в нашу модель и новые представления для создания,
обновления и редактирования записей. Это означает, что нам нужно четыре новых теста:
• def test_get_absolute_url
• def test_post_create_view
• def test_post_update_view
• def test_post_delete_view
Группа в ВК "Django_Python"
Chapter 6: Forms 152
Code
# blog/tests.py
class BlogTests(TestCase):
def setUp(self):
self.user = get_user_model().objects.create_user(
username='testuser',
email='test@email.com',
password='secret'
self.post = Post.objects.create(
author=self.user,
def test_string_representation(self):
self.assertEqual(str(post), post.title)
Группа в ВК "Django_Python"
Chapter 6: Forms 153
def test_get_absolute_url(self):
def test_post_content(self):
self.assertEqual(f'{self.post.author}', 'testuser')
def test_post_list_view(self):
response = self.client.get(reverse('home'))
self.assertEqual(response.status_code, )
self.assertTemplateUsed(response, 'home.html')
def test_post_detail_view(self):
self.assertEqual(response.status_code, )
self.assertEqual(no_response.status_code, )
self.assertTemplateUsed(response, 'post_detail.html')
def test_post_create_view(self):
response = self.client.post(reverse('post_new'), {
'author': self.user,
})
Группа в ВК "Django_Python"
Chapter 6: Forms 154
self.assertEqual(response.status_code, )
def test_post_update_view(self):
})
self.assertEqual(response.status_code, )
def test_post_delete_view(self):
response = self.client.get(
self.assertEqual(response.status_code, )
Мы ожидаем, что URL нашего теста будет в post / 1 /, поскольку там только один пост, а 1 -
его первичный ключ, который Django автоматически добавляет для нас. Чтобы
протестировать создание представления, мы создаем новый ответ и затем проверяем, что
ответ проходит (код состояния 200) и содержит наш новый заголовок и основной текст.
Для просмотра обновлений мы обращаемся к первому сообщению, в котором в качестве
единственного аргумента указан pk, равный 1, и подтверждаем, что оно приводит к
перенаправлению 302. Наконец, мы проверяем наше представление удаления,
подтверждая, что если мы удаляем сообщение, код состояния 200 успех.
Всегда можно добавить больше тестов, но это, по крайней мере, охватывает все наши новые
функциональные возможности.
Группа в ВК "Django_Python"
Chapter 6: Forms 155
Заключение
Группа в ВК "Django_Python"
Глава 7: Учетные Записи Пользователей
На данный момент мы создали работающее приложение блога, которое использует формы,
но нам не хватает основной части большинства веб-приложений: аутентификации
пользователей.Реализация правильной аутентификации пользователя очень сложна; на
этом пути есть много проблем с безопасностью, так что вы действительно не захотите
реализовывать это самостоятельно. К счастью, Django поставляется с мощной встроенной
системой аутентификации пользователей, которую мы можем использовать.Каждый раз,
когда вы создаете новый проект, по умолчанию Django устанавливает приложение auth,
которое предоставляет нам объект User, содержащий:
• username
• password
• email
• first_name
• last_name
Мы будем использовать этот объект User для реализации входа в систему, выхода из
системы и регистрации в нашем приложении блога.
Login
Django предоставляет нам представление по умолчанию для страницы входа через
LoginView. Все, что нам нужно добавить, это urlpattern на уровне проекта для системы
аутентификации, шаблон входа в систему и небольшое обновление нашего файла
settings.py.
Сначала обновите файл urls.py уровня проекта. Мы разместим наши страницы входа и
выхода в accounts/ URL. Это однострочное дополнение в предпоследней строке.
Группа в ВК "Django_Python"
Chapter 7: User Accounts 157
Code
# blog_project/urls.py
urlpatterns = [
path('admin/', admin.site.urls),
path('accounts/', include('django.contrib.auth.urls')),
path('', include('blog.urls')),
Command Line
Теперь введите следующий код шаблона для нашего вновь созданного файла.
Группа в ВК "Django_Python"
Chapter 7: User Accounts 158
Code
{% extends 'base.html' %}
{% block content %}
<h2>Login</h2>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Login</button>
</form>
{% endblock content %}
Мы используем HTML теги <form> </ form> и указываем метод POST, так как мы
отправляем данные на сервер (мы будем использовать GET, если запрашиваем данные,
например, в форме поисковой системы). Мы добавляем {% csrf_token%} из соображений
безопасности, а именно для предотвращения атаки XSS. Содержимое формы выводится
между тегами абзаца благодаря {{form.as_p}}, а затем мы добавляем кнопку «submit».На
последнем шаге нам нужно указать, куда перенаправить пользователя при успешном входе
в систему. Мы можем установить это с помощью параметра LOGIN_REDIRECT_URL.
Внизу файла settings.py добавьте следующее:
Code
# settings.py
LOGIN_REDIRECT_URL = 'home'
Группа в ВК "Django_Python"
Chapter 7: User Accounts 159
http://127.0.0.1:8000/accounts/login/
Login page
Группа в ВК "Django_Python"
Chapter 7: User Accounts 160
Code
...
</header>
{% if user.is_authenticated %}
{% else %}
{% endif %}
{% block content %}
{% endblock content %}
Если пользователь вошел в систему, мы передаем ему привет по имени, если нет, мы
предоставляем ссылку на нашу недавно созданную страницу входа.
Группа в ВК "Django_Python"
Chapter 7: User Accounts 161
Homepage logged in
Это сработало! Моего суперпользователя зовут wsv, вот что я вижу на странице.
Ссылка на выход
Мы добавили логику страницы шаблона для пользователей, вышедших из системы, но ...
как нам выйти сейчас? Мы могли бы зайти в панель администратора и сделать это вручную,
но есть и лучший способ. Давайте вместо этого добавим ссылку выхода из системы,
которая перенаправляет на домашнюю страницу. Благодаря системе аутентификации
Django этого достичь очень просто.
В нашем файле base.html добавьте однострочную ссылку {% url 'logout'%} для выхода из
системы.
Группа в ВК "Django_Python"
Chapter 7: User Accounts 162
Command Line
<!-- templates/base.html-->
...
{% if user.is_authenticated %}
{% else %}
...
Это все, что нам нужно сделать, так как необходимое представление предоставляется нам
приложением Django auth. Нам нужно указать, куда перенаправить пользователя при
выходе из системы.
Code
# blog_project/settings.py
LOGIN_REDIRECT_URL = 'home'
LOGOUT_REDIRECT_URL = 'home'
Если вы обновите домашнюю страницу, то увидите, что на ней теперь есть ссылка «Выйти» для
зарегистрированных пользователей.
Группа в ВК "Django_Python"
Chapter 7: User Accounts 163
Группа в ВК "Django_Python"
Chapter 7: User Accounts 164
Попробуйте несколько раз войти в систему и выйти из нее под своей учетной записью.
Регистрация
Нам нужно написать собственное представление для страницы регистрации для
регистрации новых пользователей, но Django предоставляет нам класс формы
UserCreationForm, чтобы упростить задачу. По умолчанию он имеет три поля: имя
пользователя, пароль1, и пароль 2.
Есть много способов организовать ваш код и структуру URL для надежной системы
аутентификации пользователей. Здесь мы создадим новое приложение, accounts, для нашей
страницы регистрации.
Группа в ВК "Django_Python"
Chapter 7: User Accounts 165
Command Line
файл. Code
# blog_project/settings.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'blog',
'accounts',
Затем добавьте URL уровня проекта, указывающий на это новое приложение, ниже
включаемого встроенного приложения auth .
Группа в ВК "Django_Python"
Chapter 7: User Accounts 166
Code
# blog_project/urls.py
urlpatterns = [
path('admin/', admin.site.urls),
path('accounts/', include('django.contrib.auth.urls')),
path('accounts/', include('accounts.urls')),
path('', include('blog.urls')),
Здесь важен порядок наших URL, потому что Django читает этот файл сверху вниз.
Поэтому, когда мы запрашиваем их /accounts/signup url, Django сначала смотрит в auth, не
находит его, а затем переходит к приложению account.
Command Line
Группа в ВК "Django_Python"
Chapter 7: User Accounts 167
Code
# acounts/urls.py
urlpatterns = [
Code
# accounts/views.py
class SignUpView(generic.CreateView):
form_class = UserCreationForm
success_url = reverse_lazy('login')
template_name = 'signup.html'
Группа в ВК "Django_Python"
Chapter 7: User Accounts 168
Зачем здесь использовать reverse_lazy вместо reverse? Причина в том, что для всех общих
представлений на основе классов URL не загружаются при импорте файла, поэтому мы
должны использовать ленивую форму реверса, чтобы загрузить их позже, когда они станут
доступны.
Command Line
Code
{% extends 'base.html' %}
{% block content %}
<h2>Sign up</h2>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
</form>
{% endblock %}
Этот формат очень похож на то, что мы делали раньше. Мы расширяем наш базовый
шаблон сверху, размещаем нашу логику между тегами <form> </ form>, используем
csrf_token для безопасности, отображаем содержимое формы в тегах абзаца с помощью
form.as_p и добавляем кнопку отправки.
Группа в ВК "Django_Python"
Chapter 7: User Accounts 169
страницу: http://127.0.0.1:8000/accounts/signup/
Обратите внимание, что по умолчанию в Django есть много лишнего текста. Мы можем
настроить это, используя что-то вроде встроенной платформы сообщений, но пока
попробуйте форму.
Группа в ВК "Django_Python"
Chapter 7: User Accounts 170
Таким образом, наш конечный поток: Signup -> Login -> Homepage. И, конечно, мы можем
настроить это, как мы хотим. RegistrationView перенаправляет на вход в систему, потому
что мы установили success_url = reverse_lazy ('login'). Страница входа перенаправляется на
домашнюю страницу, потому что в нашем файле settings.py мы установили
LOGIN_REDIRECT_URL = 'home'.
На первый взгляд может показаться сложным отслеживать все различные части проекта
Django. Это нормально. Но я обещаю, что со временем они станут более понятными.
Bitbucket
Прошло много времени с тех пор, как мы сделали git commit. Давайте сделаем это, а затем
вставим копию нашего кода в Bitbucket.
Группа в ВК "Django_Python"
Chapter 7: User Accounts 171
Command Line
Command Line
Command Line
Heroku конфигурация
Это наше третье развертывание приложения. Как и в нашем приложении Message Board
(доска сообщений), есть четыре изменения, которые нам нужно сделать, чтобы его можно
было развернуть на Heroku.
• обновить Pipfile.lock
• новый Procfile
• установить gunicorn
Группа в ВК "Django_Python"
Chapter 7: User Accounts 172
• обновить settings.py
Мы укажем версию Python в нашем Pipfile, а затем запустим pipenv, чтобы применить ее к
Pipfile.lock. Мы добавим Procfile, который является файлом конфигурации, специфичным
для Heroku, установим gunicorn для запуска в качестве нашего рабочего веб-сервера вместо
локального сервера Django и, наконец, обновим ALLOWED_HOSTS, чтобы любой мог
просматривать наше приложение.
Откройте Pipfile в текстовом редакторе и в нижней части добавьте следующие две строки.
Code
# Pipfile
[requires]
Мы используем здесь «3.6», А не более конкретный «3.6.4», так что наше приложение
автоматически обновляется до самой последней версии Python 3.6x для Heroku.Теперь
запустите pipenv lock, чтобы обновить наш Pipfile.lock, поскольку Heroku будет
использовать его для создания новой среды на серверах Heroku для нашего приложения.
Command Line
Command Line
В вашем текстовом редакторе добавьте следующую строку в Procfile. Это говорит Heroku
использовать gunicorn, а не локальный сервер, который не подходит для производства.
Группа в ВК "Django_Python"
Chapter 7: User Accounts 173
Code
Command Line
Code
# blog_project/settings.py
ALLOWED_HOSTS = ['*']
Command Line
Развертывание на Heroku
Группа в ВК "Django_Python"
Chapter 7: User Accounts 174
Command Line
(blog) $ heroku login
Затем выполните команду create, которая скажет Heroku создать новый контейнер для
нашего приложения. Если вы просто запустите heroku create, Heroku назначит вам
произвольное имя, однако вы можете указать произвольное имя, но оно должно быть
уникальным в Heroku. Другими словами, так как я выбираю название dfb-blog, вы не
сможете дать такое же имя. Вам нужна другая комбинация букв и цифр.
Command Line
Теперь настройте git таким образом, чтобы при переходе на Heroku он переходил к новому
имени приложения (заменив dfb-blog своим произвольным именем).
Command Line
Теперь мы должны сделать еще один шаг, когда у нас есть статические файлы, в нашем
случае это CSS. Django не поддерживает обслуживание статических файлов в производстве,
однако проект WhiteNoise поддерживает. Итак, давайте установим его.
Command Line
Затем нам нужно обновить наши static настройки, чтобы они были использованы в
производстве. В вашем текстовом редакторе откройте settings.py. Добавьте whitenoise в
INSTALLED_APPS над встроенным приложением staticfiles, а также в MIDDLEWARE в
третьей строке. Порядок имеет значение как для INSTALLED_APPS, так и для
MIDDLEWARE.
Внизу файла добавьте новые строки для STATIC_ROOT и STATICFILES_STORAGE. Это
должно выглядеть следующим образом.
Группа в ВК "Django_Python"
Chapter 7: User Accounts 175
Code
# blog_project/settings.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'whitenoise.runserver_nostatic', # new!
'django.contrib.staticfiles',
'blog',
'accounts',
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'whitenoise.middleware.WhiteNoiseMiddleware', # new!
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
...
Группа в ВК "Django_Python"
Chapter 7: User Accounts 176
STATIC_URL = '/static/'
STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage' \
# new!
Command Line
Наконец, мы можем перенести наш код в Heroku и добавить веб-процесс, чтобы dyno работал.
Command Line
URL вашего нового приложения будет в выходных данных командной строки, или вы
можете запустить heroku open, чтобы найти его. Мой находится по адресу https://df b-
blog.herokuapp.com/.
Heroku site
Группа в ВК "Django_Python"
Chapter 7: User Accounts 177
Заключение
Группа в ВК "Django_Python"
Глава 8: Custom User Model
Встроенная в Django модель User позволяет нам сразу начать работать с пользователями,
как мы только что делали с нашим приложением блога в предыдущих главах. Однако
официальная документация Django настоятельно рекомендует использовать
пользовательскую модель для новых проектов. Причина в том, что если вы хотите внести
какие-либо изменения в пользовательскую модель в будущем например, добавив поле
возраста с помощью custom user model с самого начала это довольно просто. Но если вы не
создадите custom user model, обновление модели пользователя по умолчанию в
существующем проекте Django будет очень и очень сложным.
Поэтому всегда используйте пользовательскую модель для всех новых проектов Django.
Однако пример официальной документации не совсем то, что рекомендуют многие
эксперты Django. Он использует довольно сложный AbstractBaseUser, чем если мы просто
используем AbstractUser, все гораздо проще и все еще настраиваемо. Это подход, который
мы будем использовать в этой главе, где мы правильно запускаем новое приложение
Newspaper(Газета) с пользовательской моделью. Выбор приложения газеты отдает дань
уважения корням Django в качестве веб фреймворка, созданного для редакторов и
журналистов в Lawrence Journal-World.
Настройка
Первым шагом является создание нового проекта Django из командной строки. Нам нужно
сделать несколько вещей:
• установка Django
• создать новый проект Django newspaper_project
Группа в ВК "Django_Python"
Chapter 8: Custom User Model 179
Command Line
$ cd ~/Desktop
$ mkdir news
$ cd news
$ pipenv shell
Обратите внимание, что мы не выполняли миграцию для настройки базы данных. Важно
подождать, пока мы не создадим нашу новую пользовательскую модель, прежде чем делать
это, учитывая, насколько тесно связана пользовательская модель с остальной частью
Django.
Группа в ВК "Django_Python"
Chapter 8: Custom User Model 180
Welcome page
• обновить settings.py
Группа в ВК "Django_Python"
Chapter 8: Custom User Model 181
Code
# newspaper_project/settings.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'users', # new
...
AUTH_USER_MODEL = 'users.CustomUser'
Теперь обновите users / models.py новой моделью User, которую мы будем называть
CustomUser. Мы также добавим наше первое дополнительное поле для «age»(возраста)
наших пользователей. Мы можем использовать PositiveIntegerField от Django, что означает,
что целое число должно быть либо положительным, либо нулевым.
Группа в ВК "Django_Python"
Chapter 8: Custom User Model 182
Code
# users/models.py
class CustomUser(AbstractUser):
age = models.PositiveIntegerField(default= )
Это действительно весь код, который нам нужен! Поскольку мы расширяем AbstractUser,
наш CustomUser является в основном копией модели User по умолчанию. Единственное
обновление - наше поле age.
Формы
Если мы на шаг отступим назад, как мы будем взаимодействовать с нашей новой моделью
CustomUser? Первый случай, когда пользователь регистрирует новую учетную запись на
нашем сайте. Другой находится в приложении администратора, которое позволяет нам, как
суперпользователям, изменять существующих пользователей. Поэтому нам нужно
обновить две встроенные формы для этой функции: UserCreationForm и UserChangeForm.
Command Line
Группа в ВК "Django_Python"
Chapter 8: Custom User Model 183
Code
# users/forms.py
class CustomUserCreationForm(UserCreationForm):
class Meta(UserCreationForm.Meta):
model = CustomUser
fields = UserCreationForm.Meta.fields
class CustomUserChangeForm(UserChangeForm):
class Meta:
model = CustomUser
fields = UserChangeForm.Meta.fields
Группа в ВК "Django_Python"
Chapter 8: Custom User Model 184
Это говорит нам о том, что настройка по умолчанию для полей в UserCreationForm - это
просто имя пользователя, адрес электронной почты и пароль, хотя доступно еще много
полей. Это может быть не понятно, так как для правильного понимания форм и моделей
требуется некоторое время. В следующей главе мы создадим наши собственные страницы
регистрации, входа и выхода, которые будут более четко связывать нашу модель
CustomUser и формы. Так что держитесь! Последний шаг это обновить наш файл admin.py,
так как Admin тесно связан с моделью пользователя по умолчанию. Мы расширим
существующий класс UserAdmin для использования нашей новой модели CustomUser и
двух новых форм.
Code
# users/admin.py
class CustomUserAdmin(UserAdmin):
add_form = CustomUserCreationForm
form = CustomUserChangeForm
model = CustomUser
admin.site.register(CustomUser, CustomUserAdmin)
Обратите внимание, что наш CustomUserAdmin также имеет параметр list_display, чтобы
он отображал только поля email, username и age, даже если на данный момент в модели
CustomUser их гораздо больше.
Группа в ВК "Django_Python"
Chapter 8: Custom User Model 185
Command Line
Superuser
Давайте создадим учетную запись суперпользователя, чтобы подтвердить, что все
работает, как ожидалось. В командной строке введите следующую команду и выполните
запросы.
Command Line
Тот факт, что это работает, является первым доказательством того, что наша
пользовательская модель работает, как и ожидалось. Давайте посмотрим на админку,
чтобы быть более уверенным.
Запустите веб-сервер.
Command Line
Группа в ВК "Django_Python"
Chapter 8: Custom User Model 186
Admin page
Группа в ВК "Django_Python"
Chapter 8: Custom User Model 187
Заключение
Группа в ВК "Django_Python"
Глава 9: Аутентификация пользователя
Теперь, когда у нас есть рабочая пользовательская модель, мы можем добавить
функциональность, которая нужна каждому веб-сайту: возможность регистрироваться,
входить и выходить из системы. Django предоставляет все необходимое для входа и выхода,
но нам нужно будет создать собственную форму для регистрации новых пользователей. Мы
также создадим базовую домашнюю страницу со ссылками на все три функции, поэтому
нам не придется каждый раз вводить URL вручную.
Templates(Шаблоны)
Command Line
Теперь нам нужно сообщить Django об этом новом каталоге, обновив конфигурацию для
'DIRS' в settings.py. Это изменение в одну строку.
Группа в ВК "Django_Python"
Chapter 9: User Authentication 189
Code
# newspaper_project/settings.py
TEMPLATES = [
...
...
Если вы думаете о том, что происходит, когда вы входите или выходите из сайта, вы сразу
же перенаправляетесь на следующую страницу. Нам нужно указать Django, куда отправлять
пользователей в каждом конкретном случае. Делают это настройки
LOGIN_REDIRECT_URL и LOGOUT_REDIRECT_URL. Мы настроим оба, чтобы
перенаправить на нашу домашнюю страницу, которая будет иметь названный URL
«home».Помните, что когда мы создаем наши маршруты URL, у нас есть возможность
добавить имя для каждого из них. Поэтому, когда мы создадим URL домашней страницы,
мы обязательно назовем его «home».Добавьте эти две строки внизу файла settings.py.
Code
# newspaper_project/settings.py
LOGIN_REDIRECT_URL = 'home'
LOGOUT_REDIRECT_URL = 'home'
Группа в ВК "Django_Python"
Chapter 9: User Authentication 190
Command Line
Вот HTML код для каждого используемого файла. base.html будет унаследован каждым
другим шаблоном в нашем проекте. Используя блок типа {% block content %}, мы можем
позже переопределить содержимое только в этом месте в других шаблонах.
Code
<!DOCTYPE html>
<html>
<head>
<title>Newspaper App</title>
</head>
<body>
<main>
{% block content %}
{% endblock %}
</main>
</body>
</html>
Группа в ВК "Django_Python"
Chapter 9: User Authentication 191
Code
{% extends 'base.html' %}
{% block content %}
{% if user.is_authenticated %}
Hi {{ user.username }}!
{% else %}
{% endif %}
{% endblock %}
Code
{% extends 'base.html' %}
{% block content %}
<h2>Login</h2>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
Группа в ВК "Django_Python"
Chapter 9: User Authentication 192
<button type="submit">Login</button>
</form>
{% endblock %}
Code
{% extends 'base.html' %}
{% block content %}
<h2>Sign up</h2>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
</form>
{% endblock %}
URLs
Давайте начнем с URL-маршрутов. В нашем файле urls.py уровня проекта мы хотим, чтобы
наш шаблон home.html отображался в качестве домашней страницы. Но мы пока не хотим
создавать приложение для выделенных страниц, поэтому мы можем использовать быстрый
доступ импортируя TemplateView и установки имени шаблона прямо в нашем шаблоне
URL.
Группа в ВК "Django_Python"
Chapter 9: User Authentication 193
Code
# newspaper_project/urls.py
urlpatterns = [
path('admin/', admin.site.urls),
path('users/', include('users.urls')),
path('users/', include('django.contrib.auth.urls')),
Command Line
Группа в ВК "Django_Python"
Chapter 9: User Authentication 194
Code
# users/urls.py
urlpatterns = [
Последний шаг это наш файл views.py, который будет содержать логику для нашей формы
регистрации. Здесь мы используем общий CreateView от Django и говорим ему
использовать нашу CustomUserCreation-Form и перенаправлять на вход в систему после
успешной регистрации пользователя, и что наш шаблон называется signup.html.
Code
# users/views.py
class SignUp(generic.CreateView):
form_class = CustomUserCreationForm
success_url = reverse_lazy('login')
template_name = 'signup.html'
Группа в ВК "Django_Python"
Chapter 9: User Authentication 195
Homepage logged in
Login
Группа в ВК "Django_Python"
Chapter 9: User Authentication 196
Homepage logged in
Теперь используйте ссылку выхода, чтобы вернуться на главную страницу, и на этот раз
нажмите на ссылку регистрации.
Signup page
Создайте нового пользователя. Мой называется testuser. После успешной отправки формы
вы будете перенаправлены на страницу входа(login ). Войдите в систему с новым
пользователем, и вы снова будете
Группа в ВК "Django_Python"
Chapter 9: User Authentication 197
Admin
Давайте также войдем в admin для просмотра наших двух учетных записей
Группа в ВК "Django_Python"
Chapter 9: User Authentication 198
Потому что мы вошли в систему с нашей новой учетной записью тестового пользователя, а
не с учетной записью суперпользователя. Только учетная запись суперпользователя имеет
разрешения для входа в систему администратора! Поэтому используйте свою учетную
запись суперпользователя для входа.
Группа в ВК "Django_Python"
Chapter 9: User Authentication 199
Все работает, но вы можете заметить, что для нашего тестового пользователя нет поля
электронной почты. Почему так? Ну, оглянитесь на страницу регистрации в users/signup/, и
вы увидите, что она запрашивает только имя пользователя и пароль, а не электронную
почту! Именно так работает настройка Django по умолчанию. Однако мы можем легко
изменить это. Вернемся к нашему файлу users/forms.py.
Группа в ВК "Django_Python"
Chapter 9: User Authentication 200
Code
# users/forms.py
class CustomUserCreationForm(UserCreationForm):
class Meta(UserCreationForm.Meta):
model = CustomUser
fields = UserCreationForm.Meta.fields
class CustomUserChangeForm(UserChangeForm):
class Meta:
model = CustomUser
fields = UserChangeForm.Meta.fields
Группа в ВК "Django_Python"
Chapter 9: User Authentication 201
Code
# users/forms.py
...
class CustomUserCreationForm(UserCreationForm):
class Meta(UserCreationForm.Meta):
model = CustomUser
class CustomUserChangeForm(UserChangeForm):
class Meta:
model = CustomUser
Группа в ВК "Django_Python"
Chapter 9: User Authentication 202
Группа в ВК "Django_Python"
Chapter 9: User Authentication 203
Заключение
До сих пор наше приложение Newspaper имеет кастомную модель пользователя и рабочие
страницы регистрации, входа и выхода. Но вы, возможно, заметили, что наш сайт выглядит
не очень хорошо. В следующей главе мы добавим Bootstrap для стилизации и создадим
приложение Pages.
Группа в ВК "Django_Python"
Глава ��: Bootstrap
Веб-разработка требует много навыков. Вам нужно не только программировать сайт для
корректной работы, но так же пользователи ожидают, что он будет хорошо выглядеть.
Когда вы создаете все с нуля, может быть крайне тяжело добавить все необходимые
HTML / CSS для красивого сайта.
К счастью, есть Bootstrap, самая популярная платформа для создания адаптивных проектов,
ориентированных на мобильные устройства. Вместо того, чтобы писать все наши
собственные CSS и JavaScript для общих функций макета веб-сайта, мы можем вместо этого
положиться на Bootstrap, чтобы сделать тяжелую работу. Это означает, что с небольшим
количеством кода с нашей стороны мы сможем быстро создать великолепно выглядящие
сайты. И если мы хотим вносить изменения по мере развития проекта, то при
необходимости Bootstrap легко переопределить.
Приложение Pages
Группа в ВК "Django_Python"
Chapter 10: Bootstrap 205
Command Line
Затем сразу обновите наш файл settings.py. Я часто забываю делать это, поэтому
рекомендуется думать о создании нового приложения как о двухэтапном процессе:
запустите команду startapp, а затем обновите INSTALLED_APPS.
Code
# newspaper_project/settings.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'users',
'pages', # new
Теперь мы можем обновить наш файл urls.py на уровне проекта. Идем дальше и удалим
импорт TemplateView. Мы также обновим маршрут ' ', чтобы включить приложение pages.
Группа в ВК "Django_Python"
Chapter 10: Bootstrap 206
Code
# newspaper_project/urls.py
urlpatterns = [
path('', include('pages.urls')),
path('admin/', admin.site.urls),
path('users/', include('users.urls')),
path('users/', include('django.contrib.auth.urls')),
Пришло время добавить нашу домашнюю страницу, что означает стандартные urls/views/
templates. Начнем с файла pages/urls.py . Сначала создайте его.
Command Line
Группа в ВК "Django_Python"
Chapter 10: Bootstrap 207
Code
# pages/urls.py
urlpatterns = [
Code
# pages/views.py
class HomePageView(TemplateView):
template_name = 'home.html'
У нас уже есть существующий шаблон home.html . Давайте проверим, что он по прежнему
работает должным образом с нашим новым url и представлением. Перейдите к странице
http://127.0.0.1:8000/ что бы проверить что все остается неизменным.
Группа в ВК "Django_Python"
Chapter 10: Bootstrap 208
Homepage logged in
Тесты
Мы добавили новый код и функциональность, что означает, что пришло время для тестов.
Вы никогда не сможете иметь достаточно тестов в своих проектах. Даже если они заранее
время, чтобы написать, они всегда экономят время и дают уверенность по мере
возрастания сложности проекта.
Есть два идеальных момента для добавления тестов: либо перед тем, как писать какой-либо
код (разработка на основе тестов), либо сразу после того, как вы добавили новую
функциональность, и вам должно это быть понятно.
• home
• signup
• login
• logout
Однако нам нужно только проверить первые два. Вход и выход из системы являются
частью Django и зависят от внутренних представлений и url маршрутов. Поэтому они уже
имеют тестовое покрытие. Если мы внесем существенные изменения в них в будущем, то
мы захотели бы добавить тесты и для этого. Но, как правило, вам не нужно добавлять тесты
для основной функциональности Django.
Группа в ВК "Django_Python"
Chapter 10: Bootstrap 209
Поскольку у нас есть URL, шаблоны и представления для каждой из наших двух новых
страниц, мы добавим тесты для каждой. SimpleTestCase будет достаточно для тестирования
домашней страницы, но страница регистрации использует базу данных, поэтому нам также
нужно использовать TestCase.
Code
# pages/tests.py
class HomePageTests(SimpleTestCase):
def test_home_page_status_code(self):
response = self.client.get('/')
self.assertEqual(response.status_code, )
def test_view_url_by_name(self):
response = self.client.get(reverse('home'))
self.assertEqual(response.status_code, )
def test_view_uses_correct_template(self):
response = self.client.get(reverse('home'))
self.assertEqual(response.status_code, )
self.assertTemplateUsed(response, 'home.html')
class SignupPageTests(TestCase):
Группа в ВК "Django_Python"
Chapter 10: Bootstrap 210
username = 'newuser'
email = 'newuser@email.com'
def test_signup_page_status_code(self):
response = self.client.get('/users/signup/')
self.assertEqual(response.status_code, )
def test_view_url_by_name(self):
response = self.client.get(reverse('signup'))
self.assertEqual(response.status_code, )
def test_view_uses_correct_template(self):
response = self.client.get(reverse('signup'))
self.assertEqual(response.status_code, )
self.assertTemplateUsed(response, 'signup.html')
def test_signup_form(self):
new_user = get_user_model().objects.create_user(
self.username, self.email)
self.assertEqual(get_user_model().objects.all().count(), )
self.assertEqual(get_user_model().objects.all()
[ ].username, self.username)
self.assertEqual(get_user_model().objects.all()
[ ].email, self.email)
Группа в ВК "Django_Python"
Chapter 10: Bootstrap 211
Наша страница регистрации также имеет форму, поэтому мы должны проверить и это. В
тестовой форме test_sign up_ мы проверяем, что когда имя пользователя и адрес
электронной почты публикуются (отправляются в базу данных), они соответствуют тому,
что хранится в модели CustomUser.
Выйдите из локального сервера с Control+c, а затем запустите наши тесты, чтобы
подтвердить, что все проходит.
Command Line
Bootstrap
Существует два способа добавить Bootstrap в проект: можно загрузить все файлы и
обслуживать их локально или использовать Сеть Доставки Контента (CDN). Второй
подход проще реализовать, если у вас есть стабильное подключение к интернету, это мы и
будем использовать здесь.
• Bootstrap.css
• jQuery.js
• Popper.js
• Bootstrap.js
Группа в ВК "Django_Python"
Chapter 10: Bootstrap 212
Вот как должен выглядеть обновленный файл base.html. Как правило, вы должны набирать
все примеры кода самостоятельно, но так как это довольно длинный код, здесь его можно
скопировать и вставить.
Code
<!-- templates/base.html -->
<!doctype html>
<html lang="en">
<head>
o-fit=no">
<title>Hello, world!</title>
</head>
<body>
<h1>Hello, world!</h1>
in="anonymous"></script>
Группа в ВК "Django_Python"
Chapter 10: Bootstrap 213
PVCmYl" crossorigin="anonymous"></script>
</body>
</html>
Если вы снова запустите сервер с помощью python manage.py runserver и обновите домашнюю
страницу по адресу http://127.0.0.1:8000/, вы увидите, что в данный момент изменился
только размер шрифта.
Давайте добавим панель навигации вверху страницы, которая содержит наши ссылки для
домашней страницы, входа в систему, выхода из системы и регистрации. В частности, мы
можем использовать теги if / else в шаблонизаторе Django для добавления некоторой
базовой логики. Мы хотим показать кнопки «войти» и «зарегистрироваться»
пользователям, которые вышли из системы, а кнопки «выйти» и «изменить пароль»
пользователям, которые вошли в систему.
Вот как выглядит код. Опять же, здесь можно копировать / вставлять, поскольку эта книга
посвящена изучению Django, а не HTML, CSS и Bootstrap.
Code
<!doctype html>
<html lang="en">
<head>
o-fit=no">
Группа в ВК "Django_Python"
Chapter 10: Bootstrap 214
</head>
<body>
a-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
{% if user.is_authenticated %}
<li class="nav-item">
{{ user.username }}
</a>
erMenu">
ge password</a>
Группа в ВК "Django_Python"
Chapter 10: Bootstrap 215
<div class="dropdown-divider"></div>
</div>
</li>
</ul>
{% else %}
</a>
<a href="{% url 'signup' %}" class="btn btn-primary ml- ">Sign up</a>
</form>
{% endif %}
</div>
</nav>
<div class="container">
{% block content %}
{% endblock %}
</div>
in="anonymous"></script>
Группа в ВК "Django_Python"
Chapter 10: Bootstrap 216
PVCmYl" crossorigin="anonymous"></script>
</body>
</html>
Нажмите на имя пользователя в верхнем правом углу - wsv в моем случае - чтобы увидеть
хорошее выпадающее меню, которое предлагает Bootstrap.
Группа в ВК "Django_Python"
Chapter 10: Bootstrap 217
Еще лучше, если вы уменьшите размер окна вашего браузера. Bootstrap автоматически
изменяет размеры и вносит изменения, чтобы он выглядел хорошо и на мобильном
устройстве.
Если вы нажмете кнопку «logout», а затем «log in» в верхней панели навигации, вы также
увидите, что наша страница входа в систему http://127.0.0.1:8000/users/login также выглядит
лучше.
Группа в ВК "Django_Python"
Chapter 10: Bootstrap 218
Bootstrap login
Code
...
...
Группа в ВК "Django_Python"
Chapter 10: Bootstrap 219
Signup Form
Откуда взялся этот текст? Всякий раз, когда что-то кажется «волшебным» в Django, будьте
уверены, что это определенно не так. Вероятно, код пришел из внутреннего фрагмента
Django.
Самый быстрый метод, который я нашел, чтобы выяснить, что происходит в Django, -
просто перейти к исходному коду Django на Github, использовать панель поиска и
попытаться найти конкретный фрагмент текста.
Группа в ВК "Django_Python"
Chapter 10: Bootstrap 220
Текст поставляется как часть приложения auth, в поле имени пользователя для AbstractUser.
Сейчас у нас есть три варианта:
Мы выберем третий вариант, так как это хороший способ представить отличный
сторонний пакет django-crispy-forms. Работа с формами является сложной задачей, и
django-crispy-forms упрощает написание DRY кода.
Сначала остановите локальный сервер с Control+c. Затем используйте Pip env для
установки пакета в нашем проекте.
Command Line
Группа в ВК "Django_Python"
Chapter 10: Bootstrap 221
Code
# newspaper_project/settings.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
# rd Party
'crispy_forms',
# Local
'users',
'pages',
Code
# newspaper_project/settings.py
Теперь в нашем шаблоне signup.html мы можем быстро использовать crispy формы. Сначала мы
загружаем crispy_forms_tags сверху, а затем меняем {{ form.as_p }} на {{ form|crispy }}.
Группа в ВК "Django_Python"
Chapter 10: Bootstrap 222
Code
{% extends 'base.html' %}
{% load crispy_forms_tags %}
{% block content %}
<h2>Sign up</h2>
<form method="post">
{% csrf_token %}
{{ form|crispy }}
</form>
{% endblock %}
Если вы снова запустите сервер с помощью python manage.py runserver и обновите страницу
регистрации, мы увидим новые изменения.
Группа в ВК "Django_Python"
Chapter 10: Bootstrap 223
Намного лучше. Хотя, как насчет того, чтобы наша кнопка “Sign up” была немного более
привлекательной? В Bootstrap есть все виды стилей кнопок, которые мы можем выбрать.
Давайте использовать “success”, который имеет зеленый фон и белый текст.
Группа в ВК "Django_Python"
Chapter 10: Bootstrap 224
Code
<!-- templates/signup.html -->
...
...
Следующий шаг
Наше приложение Newspaper начинает выглядеть довольно хорошо. Последний шаг это
настройка смены и сброса пароля.
Группа в ВК "Django_Python"
Chapter 10: Bootstrap 225
Здесь снова Django позаботился о тяжелой работе за нас, поэтому он требует минимального
количества кода с нашей стороны.
Группа в ВК "Django_Python"
Глава ��: Изменение и сброс пароля
В этой главе мы завершим поток авторизации нашего приложения Newspaper, добавив
функцию изменения и сброса пароля. Пользователи смогут изменить свой текущий пароль
или, и если они его забыли сбросить его по электронной почте.
Так же как в Django поставляется с встроенным представлением и URL для входа и выхода,
также поставляется и с views/URL смены и сброса пароля. Сначала мы рассмотрим версии
по умолчанию, а затем узнаем, как настроить их с помощью наших собственных шаблонов
Bootstrap и службы электронной почты.
Изменение пароля
Группа в ВК "Django_Python"
Chapter 11: Password Change and Reset 227
Password change
Введите старый пароль, а затем новый. Затем нажмите кнопку “Change My Password”.
расположенную по адресу:
http://127.0.0.1:8000/users/password_change/done/.
Группа в ВК "Django_Python"
Chapter 11: Password Change and Reset 228
Command Line
Code
{% extends 'base.html' %}
{% block content %}
<h1>Password change</h1>
<p>Please enter your old password, for security's sake, and then enter your ne\
<form method="POST">
{% csrf_token %}
{{ form.as_p }}
Группа в ВК "Django_Python"
Chapter 11: Password Change and Reset 229
</form>
{% endblock %}
Группа в ВК "Django_Python"
Chapter 11: Password Change and Reset 230
Code
{% extends 'base.html' %}
{% block content %}
{% endblock content %}
Он также расширяет base.html и включает новый title. Однако на странице нет формы,
только новый текст.Новая страница находится по адресу http://127.0.0.1:8000/users/
password_change/done/.
Это было не так уж плохо, верно? Конечно, было гораздо меньше работы, чем создание
всего с нуля, особенно весь код вокруг безопасного обновления пароля пользователя. Далее
идет наша функция сброса пароля.
Группа в ВК "Django_Python"
Chapter 11: Password Change and Reset 231
Сброс пароля
Сброс пароля обрабатывает частый случай, когда пользователи, забывают свои пароли.
Шаги очень похожи на настройку смены пароля, как мы только что делали. Django уже
предоставляет реализацию по умолчанию, которую мы будем использовать, а затем
настроим шаблоны, чтобы они соответствовали остальной части нашего сайта.
Code
# newspaper_project/settings.py
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
И у нас все готово! Джанго позаботится обо всем остальном за нас. Давайте
попробуем.Перейдите по адресу http://127.0.0.1:8000/users/password_reset/, чтобы
просмотреть страницу сброса пароля по умолчанию.
Группа в ВК "Django_Python"
Chapter 11: Password Change and Reset 232
Убедитесь, что введенный вами адрес электронной почты соответствует одной из ваших учетных
записей. После отправки вы будете перенаправлены на страницу сброса пароля по адресу:
http://127.0.0.1:8000/users/password_reset/done/.
Тут говорится , чтобы вы проверить вашу электронную почту. Так как мы указали Django
отправлять письма в консоль командной строки, текст письма теперь будет там. Это то, что
я вижу в своей консоли.
Группа в ВК "Django_Python"
Chapter 11: Password Change and Reset 233
Command Line
MIME-Version: .
Content-Transfer-Encoding: bit
From: webmaster@localhost
To: will@wsvincent.com
You're receiving this email because you requested a password reset for your user\
account at . . . : .
The . . . : team
Группа в ВК "Django_Python"
Chapter 11: Password Change and Reset 234
Теперь введите новый пароль и нажмите кнопку “Change my password”. Последним шагом
будет перенаправление вас на страницу “сброс пароля выполнен”.
Группа в ВК "Django_Python"
Chapter 11: Password Change and Reset 235
Чтобы подтвердить, что все сработало, нажмите на ссылку “Log in” и используйте свой
новый пароль. Это должно сработать.
Собственные шаблоны
Как и в случае с “сменой пароля”, нам нужно только создать новые шаблоны, чтобы
настроить внешний вид сброса пароля.
Command Line
Группа в ВК "Django_Python"
Chapter 11: Password Change and Reset 236
Code
{% extends 'base.html' %}
{% block content %}
<p>Enter your email address below, and we'll email instructions for setting a ne\
w one.</p>
<form method="POST">
{% csrf_token %}
{{ form.as_p }}
</form>
{% endblock %}
Группа в ВК "Django_Python"
Chapter 11: Password Change and Reset 237
Теперь мы можем обновить остальные три страницы. Каждая из них имеет одинаковую
форму расширения base.html, нового заголовка, нового текста контента, а также для
«подтверждения сброса пароля» обновленную форму.
Code
{% extends 'base.html' %}
{% block content %}
<p>We've emailed you instructions for setting your password. You should receiv\
{% endblock %}
Группа в ВК "Django_Python"
Chapter 11: Password Change and Reset 238
Code
{% extends 'base.html' %}
{% block content %}
<form method="POST">
{% csrf_token %}
{{ form.as_p }}
</form>
{% endblock %}
В командной строке выберите ссылку URL из электронного письма, выведенного на консоль - мое
было http://���.�.�.�:����/users/reset/MQ/�up-������c���db�ead����/ вы увидите
следующее.
Группа в ВК "Django_Python"
Chapter 11: Password Change and Reset 239
Code
{% extends 'base.html' %}
{% block content %}
<p>Your new password has been set. You can log in now on the <a href="{% url 'lo\
{% endblock %}
Группа в ВК "Django_Python"
Chapter 11: Password Change and Reset 240
Заключение
Группа в ВК "Django_Python"
Глава ��: Email
На данный момент вы можете чувствовать себя немного перегруженным всей
информацией о конфигурации аутентификации пользователя, которую мы сделали до
этого момента. Это нормально. В конце концов, мы еще даже не создали каких либо
основных функций приложения Newspaper! Все было о настройке пользовательских
учетных записей пользователей и прочем.
Плюсом подхода Django является то, что в нем невероятно легко настроить любую часть нашего
сайта. Недостатком является то, что Django требует немного больше нестандартного кода, чем
некоторые конкурирующие веб-фреймворки. По мере того, как вы становитесь все более
опытным в веб-разработке, вы будете понимать мудрость подхода Django.
SendGrid
SendGrid это популярный сервис для отправки транзакционных писем, поэтому мы будем
использовать его. Django не заботится о том, какой сервис вы выбираете, хотя; вы можете
так же легко использовать MailGun или любой другой сервис по вашему выбору.
На главной странице SendGrid нажмите на большую синюю кнопку “See Plans and Pricing”.
Группа в ВК "Django_Python"
Chapter 12: Email 242
SendGrid homepage
На следующей странице немного прокрутите вниз и найдите в левой части кнопку “Try for Free”.
SendGrid предоставляет бесплатный уровень, который мы можем использовать, хотя они
несколько затрудняют его поиск.
Группа в ВК "Django_Python"
Chapter 12: Email 243
SendGrid pricing
Группа в ВК "Django_Python"
Chapter 12: Email 244
После подтверждения вашей новой учетной записи по электронной почте вас попросят
войти в систему и перейти на страницу панели инструментов SendGrid.
Группа в ВК "Django_Python"
Chapter 12: Email 245
SendGrid loggedin
Теперь мы можем настроить наш код Django в файле settings.py. Сначала мы обновляем
почтовый сервер для использования SMTP.
Code
# newspaper_project/settings.py
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
Затем прямо под ним добавьте следующие пять строк конфигурации электронной почты.
Обратите внимание, что в идеале вы должны хранить защищенную информацию, такую
как ваш пароль, в переменной, но мы не будем этого делать здесь, что бы упростить
ситуацию.
Группа в ВК "Django_Python"
Chapter 12: Email 246
Code
# newspaper_project/settings.py
EMAIL_HOST = 'smtp.sendgrid.net'
EMAIL_HOST_USER = 'sendgrid_username'
EMAIL_HOST_PASSWORD = 'sendgrid_password'
EMAIL_PORT =
EMAIL_USE_TLS = True
http://127.0.0.1:8000/users/password_reset/
Вы должны получить электронное письмо в свой почтовый ящик! Текст будет точно таким
же, как и в консоли командной строки ранее.
Текущий текст электронной почты не очень личный, не так ли? Давайте изменим. На этом
этапе я мог бы просто показать вам, какие шаги предпринять, но я думаю, что было бы
полезно, если бы я мог объяснить, как я понял, как это сделать. В конце концов, вы хотите
иметь возможность настраивать все части Django по мере необходимости.
В этом случае я знал, какой текст использовал Django по умолчанию, но не было ясно, где в
исходном коде Django он был написан. И поскольку весь исходный код Django доступен на
Github, мы можем просто найти его.
Группа в ВК "Django_Python"
Chapter 12: Email 247
Github Django
Github search
Первый результат - тот, который нам нужен. Он показывает, что код находится по адресу
django / contrib / ad-min / templates / registration / password_reset_email.html. Это означает,
что в приложении contrib файл который нам нужен, называется password_reset_email.html.
Группа в ВК "Django_Python"
Chapter 12: Email 248
Code
{% blocktrans %}You're receiving this email because you requested a password res\
{% block reset_link %}
ken %}
{% endblock %}
{% endautoescape %}
Давайте изменим это. Нам нужно создать новый файл password_reset_email.html в нашей
папке registration .
Command Line
Затем используйте следующий код, который настраивает то, что Django предоставляет
по умолчанию.
Группа в ВК "Django_Python"
Chapter 12: Email 249
Code
{% trans "We've received a request to reset your password. If you didn't make th\
is request, you can safely ignore this email. Otherwise, click the button below \
{% block reset_link %}
ken %}
{% endblock %}
{% endautoescape %}
Этот код может выглядеть немного страшно, поэтому давайте разберем его построчно.
Вверху мы загружаем тег шаблона i18n, что означает, что этот текст может быть переведен
на несколько языков. Django имеет надежную поддержку интернационализации, хотя ее
охват выходит за рамки этой книги.
Давайте также обновим заголовок темы электронного письма. Для этого мы создадим
новый файл templates / registration / password_reset subject.txt.
Группа в ВК "Django_Python"
Chapter 12: Email 250
Command Line
И у нас все готово. Попробуйте снова наш новый поток, введя новый пароль по адресу
http://127.0.0.1:8000/users/password_reset/. Затем проверьте свою электронную почту, и она
будет иметь наш новый контент и тему.
Заключение
Группа в ВК "Django_Python"
Глава ��: приложение Newspaper
Пришло время создать наше приложение Newspaper. У нас будет страница статей, на
которой журналисты могут публиковать статьи, установим разрешения, чтобы только
автор статьи мог их редактировать или удалять, и, наконец, добавим возможность другим
пользователям писать комментарии к каждой статье, в которых будет введена концепция
внешних ключей.
Приложение Articles(статьи)
Для начала создайте приложение статей и определите модели нашей базы данных. Не
существует жестких и быстрых правил, касающихся имен ваших приложений, за
исключением того, что вы не можете использовать имя встроенного приложения. Если вы
посмотрите раздел INSTALLED_APPS файла settings.py, вы увидите, какие имена
приложений запрещены: admin, auth, contenttypes, sessions, messages, и staticfiles.. Общее
практическое правило заключается в использовании множественного числа имени
приложения - сообщений, платежей, пользователей и т. д. - если только это не является
явно неправильным, как в случае блога, где единственное число имеет больше смысла.
Command Line
Затем добавьте его в наш INSTALLED_APPS и обновите часовой пояс, так как мы будем
отмечать время в наших статьях. Вы можете найти свой часовой пояс в списке Википедии.
Например, я живу в Бостоне, штат Массачусетс, который находится в восточном часовом
поясе Соединенных Штатов. Поэтому моя запись - America/New_York.
Группа в ВК "Django_Python"
Chapter 13: Newspaper app 252
Code
# newspaper_project/settings.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
# rd Party
'crispy_forms',
# Local
'users',
'pages',
'articles', # new
TIME_ZONE = 'America/New_York'
Далее мы определяем нашу модель базы данных, которая содержит четыре поля: заголовок,
тело, дата и автор. Обратите внимание, что мы позволяем Django автоматически
устанавливать время и дату в соответствии с нашей настройкой TIME_ZONE. В поле
автора мы хотим сослаться на нашу пользовательскую модель пользователя
users.CustomUser, которую мы установили в файле settings.py как AUTH_USER_MODEL.
Поэтому, если мы импортируем настройки, мы можем ссылаться на них как
settings.AUTH_USER_MODEL.
Мы также реализуем лучшие практики определения get_absolute_url с самого начала и
метод __str__ для просмотра модели в нашем интерфейсе администратора.
Группа в ВК "Django_Python"
Chapter 13: Newspaper app 253
Code
# articles/models.py
class Article(models.Model):
title = models.CharField(max_length= )
body = models.TextField()
date = models.DateTimeField(auto_now_add=True)
author = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
def __str__(self):
return self.title
def get_absolute_url(self):
Поскольку у нас есть совершенно новое приложение и модель, пришло время создать
новый файл миграции и затем применить его к базе данных.
Группа в ВК "Django_Python"
Chapter 13: Newspaper app 254
Command Line
На этом этапе мне нравится переходить в админку, чтобы поиграться с моделью, прежде
чем создавать urls/views/templates, необходимые для фактического отображения данных на
веб сайте. Но сначала нам нужно обновить admin.py, чтобы наше новое приложение
отобразилось.
Code
# articles/admin.py
admin.site.register(models.Article)
Command Line
Группа в ВК "Django_Python"
Chapter 13: Newspaper app 255
Admin page
Группа в ВК "Django_Python"
Chapter 13: Newspaper app 256
Я добавил три новые статьи, как вы можете видеть на обновленной странице статей.
Группа в ВК "Django_Python"
Chapter 13: Newspaper app 257
Если вы нажмете на отдельную статью, вы увидите, что отображаются title, body, и author, но не
дата. Это потому, что Django автоматически добавила нам дату и поэтому не может быть
изменена администратором. Мы могли бы сделать дату редактируемой - в более сложных
приложениях обычно есть поля create_at и updated_at - но для простоты мы просто покажем
дату создания. Даже если дата здесь не отображается, мы по-прежнему сможем получить к ней
доступ в наших шаблонах, чтобы ее можно было отображать на веб страницах.
URLs и Views
Следующий шаг - настройка URLs и представлений. Пусть наши статьи появятся в разделе
articles/. Импортируйте include во вторую строку и добавьте шаблон URL для статей на
уровне проекта файл urls.py.
Группа в ВК "Django_Python"
Chapter 13: Newspaper app 258
Code
# newspaper_project/urls.py
urlpatterns = [
path('', include('pages.urls')),
path('admin/', admin.site.urls),
path('users/', include('users.urls')),
path('users/', include('django.contrib.auth.urls')),
Command Line
Затем заполните его нашими маршрутами. Начнем со страницы со списком всех статей в
articles/ которая будет использовать представление ArticleListView.
Группа в ВК "Django_Python"
Chapter 13: Newspaper app 259
Code
# articles/urls.py
urlpatterns = [
Code
# articles/views.py
class ArticleListView(ListView):
model = models.Article
template_name = 'article_list.html'
Нам нужно указать только два поля: модель Article и имя нашего шаблона, который будет
article_list.html.
Последний шаг это создать наш шаблон. Мы можем сделать пустой файл из командной
строки.
Группа в ВК "Django_Python"
Chapter 13: Newspaper app 260
Command Line
Code
{% extends 'base.html' %}
{% block content %}
<div class="card">
<div class="card-header">
pan>
</div>
<div class="card-body">
{{ article.body }}
</div>
Группа в ВК "Django_Python"
Chapter 13: Newspaper app 261
</div>
</div>
<br />
{% endfor %}
{% endblock content %}
Снова запустите сервер с помощью python manage.py runserver и посетите нашу страницу
по адресу http://127.0.0.1:8000/articles/.
Articles page
Группа в ВК "Django_Python"
Chapter 13: Newspaper app 262
Редактирование/Удаление
Как мы можем добавить параметры редактирования и удаления? Нам нужны новые urls,
представления и шаблоны. Давайте начнем с urls. Мы можем воспользоваться тем, что
Django автоматически добавляет первичный ключ в каждую базу данных. Поэтому наша
первая статья с первичным ключом 1 будет находиться в article / 1 / edit /, а маршрут удаления
будет находиться в article / 1 / delete /.
Code
# articles/urls.py
urlpatterns = [
path('<int:pk>/edit/',
path('<int:pk>/',
path('<int:pk>/delete/',
Группа в ВК "Django_Python"
Chapter 13: Newspaper app 263
Code
# articles/views.py
class ArticleListView(ListView):
model = models.Article
template_name = 'article_list.html'
class ArticleDetailView(DetailView):
model = models.Article
template_name = 'article_detail.html'
class ArticleUpdateView(UpdateView):
model = models.Article
template_name = 'article_edit.html'
class ArticleDeleteView(DeleteView):
model = models.Article
template_name = 'article_delete.html'
Группа в ВК "Django_Python"
Chapter 13: Newspaper app 264
success_url = reverse_lazy('article_list')
Наконец нам нужно добавить наши новые шаблоны. Остановите сервер с помощью Control
+ c и введите следующее.
Command Line
Мы начнем со страницы details , где будут отображаться заголовок, дата, тело и автор со
ссылками для редактирования и удаления. Она также будет ссылаться на все статьи.
Напомним, что тегу url языка шаблонов Django требуется имя URL, а затем передаются все
аргументы. Имя нашего маршрута редактирования - article_edit, и нам нужно передать его
первичный ключ article.pk. Имя маршрута для удаления - article_delete, для него также
требуется первичный ключ article.pk. Наша страница статей представляет собой ListView,
поэтому ей не нужно передавать никаких дополнительных аргументов.
Code
{% extends 'base.html' %}
{% block content %}
<div class="article-entry">
</div>
Группа в ВК "Django_Python"
Chapter 13: Newspaper app 265
<p><a href="{% url 'article_edit' article.pk %}">Edit</a> | <a href="{% url 'a\
{% endblock content %}
Code
{% extends 'base.html' %}
{% block content %}
<h1>Edit</h1>
{{ form.as_p }}
</form>
{% endblock %}
Группа в ВК "Django_Python"
Chapter 13: Newspaper app 266
Code
{% extends 'base.html' %}
{% block content %}
<h1>Delete</h1>
</form>
{% endblock %}
В качестве заключительного шага мы можем добавить ссылки редактировать и удалять на нашу страницу list в классе div для
card-footer.... Они будут такими же, как те, которые добавлены на страницу detail.
Code
...
</div>
...
http://127.0.0.1:8000/articles/1/edit/
Группа в ВК "Django_Python"
Chapter 13: Newspaper app 267
Edit page
Detail page
Группа в ВК "Django_Python"
Chapter 13: Newspaper app 268
Delete page
Создание страницы
Последним шагом является создание страницы для новых статей, которые мы можем
сделать с Django CreateView. Наши три шага - это создание представления, url-адреса и
шаблона. Этот процесс должен быть уже довольно знакомым.
Группа в ВК "Django_Python"
Chapter 13: Newspaper app 269
В нашем файле представлений добавьте Create View к импорту вверху и создайте новый
класс ArticleCreateView Create View, который указывает вашу модель, шаблон и доступные
поля.
Code
# articles/views.py
...
class ArticleCreateView(CreateView):
model = models.Article
template_name = 'article_new.html'
...
Обратите внимание, что у наших полей есть автор, так как мы хотим связать новую статью
с автором, однако после создания статьи мы не хотим, чтобы пользователь мог изменить
автора, поэтому ArticleUpdateView имеет только поля ['title', 'body',].
Группа в ВК "Django_Python"
Chapter 13: Newspaper app 270
Code
# articles/urls.py
...
urlpatterns = [
...
...
Затем остановите сервер с Control+c, чтобы создать новый шаблон с именем article_new.html.
Command Line
Code
{% extends 'base.html' %}
{% block content %}
<h1>New article</h1>
{{ form.as_p }}
</form>
{% endblock %}
Группа в ВК "Django_Python"
Chapter 13: Newspaper app 271
Code
...
<body>
{% if user.is_authenticated %}
</ul>
{% endif %}
label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
...
Группа в ВК "Django_Python"
Chapter 13: Newspaper app 272
Code
{% extends 'base.html' %}
{% block content %}
<div class="jumbotron">
<p class="lead">
</p>
</div>
{% endblock %}
Мы все закончили. Давайте просто подтвердим, что все работает, как ожидалось. Запустите
сервер снова python manage.py runserver и перейдите на нашу домашнюю страницу по адресу:
http://127.0.0.1:8000/.
Группа в ВК "Django_Python"
Chapter 13: Newspaper app 273
Группа в ВК "Django_Python"
Chapter 13: Newspaper app 274
Create page
Группа в ВК "Django_Python"
Chapter 13: Newspaper app 275
Detail page
Также обратите внимание, что первичный ключ здесь 4 в URL. Хотя сейчас мы показываем
только три статьи, Django не переупорядочивает первичные ключи только потому, что мы
удалили один. На практике большинство реальных сайтов ничего не удаляют; вместо этого
они «скрывают» удаленные поля, поскольку это облегчает поддержание целостности базы
данных и дает возможность «восстановить» позже, если это необходимо. С нашим текущим
подходом, как только что-то удалено, оно ушло навсегда!
Нажмите на ссылку “All Articles”, чтобы увидеть нашу новую страницу /articles page.
Группа в ВК "Django_Python"
Chapter 13: Newspaper app 276
Заключение
Группа в ВК "Django_Python"
Глава ��:Разрешения и авторизация
Есть несколько проблем с нашим текущим сайтом газеты. Во первых, мы хотим, чтобы
наша газета была финансово устойчивой. В будущем мы могли бы добавить платежное
приложение, чтобы взимать плату за доступ, но сейчас нам потребуется, чтобы
пользователь вошел в систему для просмотра любых статей. Это известно как авторизация.
Распространено устанавливать разные правила относительно того, кто имеет право
просматривать области вашего сайта. Обратите внимание, что это отличается от
аутентификации, которая представляет собой процесс регистрации и входа в систему
пользователей. Авторизация ограничивает доступ; Аутентификация позволяет
пользователю зарегистрироваться и войти в систему.
Как развитый веб фреймворк, Django имеет встроенную функциональность для
авторизации, которую мы можем быстро использовать. В этой главе мы ограничим доступ
к различным страницам открыв его только зарегистрированным пользователям. Мы также
добавим разрешения, чтобы только автор статьи мог ее обновить или удалить; На данный
момент это может сделать любой пользователь!
Улучшение CreateView
В настоящее время автором новой статьи может быть задан любой пользователь. Вместо
этого он должен быть автоматически установлен как текущий пользователь. Затем мы
установим права на редактирование / удаление, чтобы такие изменения мог вносить только
автор статьи. Созданный по умолчанию CreateView предоставляет нам множество
функциональных возможностей, но для того, чтобы назначить текущего пользователя
автором, нам нужно его настроить. Мы удалим автора из полей и вместо этого установим
его автоматически с помощью метода form_valid.
Группа в ВК "Django_Python"
Chapter 14: Permissions and Authorization 278
Code
# articles/views.py
...
class ArticleCreateView(CreateView):
model = models.Article
template_name = 'article_new.html'
form.instance.author = self.request.user
return super().form_valid(form)
...
Как я узнал, что могу обновить CreateView следующим образом? Ответ я посмотрел на
исходный код и использовал Google. Представления на основе классов отлично подходят
для запуска новых проектов, но когда вы хотите настроить их, необходимо засучить рукава
и начать понимать, что происходит под капотом. Чем больше вы используете и
настраиваете встроенные представления, тем удобнее вам будет выполнять такие
настройки. Скорее всего, то, что вы пытаетесь сделать, уже где-то решено, либо в самом
Django, либо на форуме, подобно Stack Overflow. Не бойтесь просить о помощи!
Группа в ВК "Django_Python"
Chapter 14: Permissions and Authorization 279
Авторизация
Группа в ВК "Django_Python"
Chapter 14: Permissions and Authorization 280
Теперь попробуйте создать новую статью с заголовком и телом. Нажмите на кнопку “Save”.
Группа в ВК "Django_Python"
Chapter 14: Permissions and Authorization 281
Ошибка. Это связано с тем, что в нашей модели ожидается поле автора, которое связано с
текущим вошедшим пользователем. Но поскольку мы не вошли в систему, автора нет, и
поэтому отправка не удалась.
Mixins(Миксины)
Мы явно хотим установить некоторые полномочия, чтобы только зарегистрированные
пользователи могли получить доступ к сайту. Для этого мы можем использовать миксин,
который представляет собой особый вид множественного наследования, который
использует Django, чтобы избежать дублирования кода и сделать возможной настройку.
Например, встроенному универсальному ListView необходим способ возврата шаблона, так
же, как и DetailView, и практически любой другое представление. Вместо того, чтобы
повторять один и тот же код в каждом большом общем представлении, Django разбивает
эту функциональность на «миксин», известный как TemplateRespon-seMixin. И ListView, и
DetailView используют этот миксин для визуализации правильного шаблона.
Группа в ВК "Django_Python"
Chapter 14: Permissions and Authorization 282
Code
# articles/views.py
...
...
Error page
Если вы посмотрите на документацию для LoginRequired mixin, она скажет нам ответ. Мы
можем добавить login_url для переопределения параметра по умолчанию. Мы используем
именованный URL маршрут входа в систему.
Группа в ВК "Django_Python"
Chapter 14: Permissions and Authorization 283
Code
# articles/views.py
...
model = models.Article
template_name = 'article_new.html'
form.instance.author = self.request.user
return super().form_valid(form)
Updating views
Группа в ВК "Django_Python"
Chapter 14: Permissions and Authorization 284
Code
# articles/views.py
model = models.Article
template_name = 'article_list.html'
login_url = 'login'
model = models.Article
template_name = 'article_detail.html'
login_url = 'login'
model = models.Article
template_name = 'article_edit.html'
login_url = 'login'
Группа в ВК "Django_Python"
Chapter 14: Permissions and Authorization 285
model = models.Article
template_name = 'article_delete.html'
success_url = reverse_lazy('article_list')
login_url = 'login'
model = models.Article
template_name = 'article_new.html'
login_url = 'login'
form.instance.author = self.request.user
return super().form_valid(form)
Далее поиграйте с сайтом, чтобы убедиться, что перенаправления входа в систему теперь
работают как положено. Если вам нужна помощь, чтобы вспомнить, какие правильные
URLs, сначала войдите в систему и запишите URLs для каждого из маршрутов создания,
редактирования, удаления и страницы всех статей.
Заключение
Наше приложение Newspaper почти готово. Наши статьи правильно настроены, настроены
разрешения и авторизация, аутентификация пользователя в хорошем состоянии.
Последний пункт это добавить возможность другим зарегистрированным пользователям
оставлять комментарии, о которых мы расскажем в следующей главе.
Группа в ВК "Django_Python"
Глава ��: Комментарии
Есть два способа добавить комментарии на сайт нашей газеты. Первый - создать
специальное приложение comments и связать его с articles, однако на данный момент это
похоже на чрезмерное проектирование. Вместо этого мы можем просто добавить
дополнительную модель comment в наше приложение articles и связать ее с моделью Article
с помощью внешнего ключа. К концу этой главы пользователи смогут оставлять
комментарии к статьям других пользователей.
Модель
Для начала мы можем добавить еще одну таблицу в нашу существующую базу данных под
названием Comment. Эта модель будет иметь связь внешнего ключа многие-к-одному к Article:
одна статья может иметь много комментариев, но не наоборот. Традиционно поле
внешнего ключа называется просто моделью, на которую оно ссылается, поэтому это поле
будет называться article. Остальные два поля будут comment и author.
Группа в ВК "Django_Python"
Chapter 15: Comments 287
Code
# articles/models.py
...
class Comment(models.Model):
comment = models.CharField(max_length= )
author = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
def __str__(self):
return self.comment
def get_absolute_url(self):
return reverse('article_list')
Наша модель Comment также имеет метод __str__ и метод get_absolute_url, который
возвращает на страницу статьи.
Поскольку мы обновили наши модели, пришло время создать новый файл миграции и
применить его. Обратите внимание, что мы добавляем articles в конец команды, что
является необязательным, мы указываем, что хотим использовать в миграции только
приложение articles. Это хорошая привычка. Например, что делать, если мы внесли
изменения в модели в двух разных приложениях? Если бы мы не указали приложение, то
изменения обоих приложений были бы включены в один и тот же файл миграции, что
затруднит в будущем отладку ошибок. Держите каждую миграцию как можно компактнее и
сдержаннее.
Группа в ВК "Django_Python"
Chapter 15: Comments 288
Command Line
Admin
После создания новой модели хорошо поиграть с ней в приложении администратора,
прежде чем отображать ее на нашем фактическом веб сайте. Добавьте Comment к вашему
файлу admin.py что бы он был виден.
Code
# articles/admin.py
admin.site.register(models.Article)
admin.site.register(models.Comment)
Запустите сервер с помощью python manage.py runserver и перейдите на нашу главную страницу
админки http://127.0.0.1:8000/admin/
Группа в ВК "Django_Python"
Chapter 15: Comments 289
Под нашим приложением “Articles” вы увидите две таблицы: Comments и Articles. Нажмите
на кнопку “+ Add” рядом с Comments. Вы увидите, что под статьей находится выпадающий
список существующих статей, то же самое для автора, и есть текстовое поле рядом с
Comment.
Группа в ВК "Django_Python"
Chapter 15: Comments 290
Admin Comments
Группа в ВК "Django_Python"
Chapter 15: Comments 291
На этом этапе мы можем добавить дополнительное поле администратора, чтобы увидеть комментарий и
статью на этой странице. Но не лучше ли просто просмотреть все модели комментариев, связанные с одной
моделью публикации? Оказывается, мы это можем ,с помощью функции Django admin называемой inlines,
Группа в ВК "Django_Python"
Chapter 15: Comments 292
Code
# articles/admin.py
class CommentInline(admin.StackedInline):
model = models.Comment
class ArticleAdmin(admin.ModelAdmin):
inlines = [
CommentInline,
admin.site.register(models.Article, ArticleAdmin)
admin.site.register(models.Comment)
Группа в ВК "Django_Python"
Chapter 15: Comments 293
Группа в ВК "Django_Python"
Chapter 15: Comments 294
Code
# articles/admin.py
class CommentInline(admin.TabularInline):
model = models.Comment
class ArticleAdmin(admin.ModelAdmin):
inlines = [
CommentInline,
admin.site.register(models.Article, ArticleAdmin)
admin.site.register(models.Comment)
Обновите страницу администратора и вы увидите новое изменение: все поля для каждой
модели отображаются в одной строке.
Группа в ВК "Django_Python"
Chapter 15: Comments 295
TabularInline page
Намного лучше. Теперь нам нужно обновить шаблон для отображения комментариев.
Template(шаблон)
Поскольку Comment находится в нашем существующем приложении articles , нам нужно
только обновить существующие шаблоны для article_list.html и article_detail.html для
отображения нашего нового контента. Нам не нужно создавать новые шаблоны и возиться
с urls и представлениями.
То, что мы хотим сделать, это отобразить все комментарии, связанные с конкретной
статьей. Это называется “query”, поскольку мы запрашиваем у базы данных определенный
бит информации. В нашем случае, работая с внешним ключом, мы хотим проследить
обратную связь: в каждой статье ищем связанные модели Comment.
Группа в ВК "Django_Python"
Chapter 15: Comments 296
модели Article мы можем использовать article_set для доступа ко всем экземплярам модели.
Но лично мне сильно не нравится этот синтаксис, поскольку я нахожу его запутанным и
неинтуитивным. Лучший подход это добавить атрибут related_name в нашу модель, который
позволяет явно задать имя этой обратной связи. Давайте сделаем это.
Для начала добавьте атрибут related_name в нашу модель Comment. Хорошим значением
по умолчанию является множественное число модели с ForeignKey.
Code
# articles/models.py
...
class Comment(models.Model):
article = models.ForeignKey(
Article,
on_delete=models.CASCADE,
related_name='comments' # new
Поскольку мы только что внесли изменения в нашу модель базы данных, нам нужно
создать файл миграции и обновить базу данных. Остановите локальный сервер с помощью
Control+c и выполните следующие две команды. Затем снова запустите сервер, мы будем
использовать его в ближайшее время.
Группа в ВК "Django_Python"
Chapter 15: Comments 297
Command Line
Code
{% extends 'base.html' %}
{% block content %}
<div class="card">
<div class="card-header">
Группа в ВК "Django_Python"
Chapter 15: Comments 298
pan>
</div>
<div class="card-body">
</div>
<div class="card-footer">
<p>
{{ comment }}
</p>
{% endfor %}
</div>
</div>
<br />
{% endfor %}
{% endblock content %}
Группа в ВК "Django_Python"
Chapter 15: Comments 299
Эй! Это работает. Мы можем видеть оба комментария, перечисленные под сообщением.
Заключение
Группа в ВК "Django_Python"
Chapter 15: Comments 300
У нас уже есть поле возраста для всех пользователей, которое в настоящее время
устанавливается в 0 по умолчанию. Если бы мы хотели, мы могли бы добавить возрастное
раскрывающееся меню в форму регистрации и ограничить доступ пользователей только
для пользователей старше 13 лет. Или мы можем предложить скидки пользователям
старше 65 лет. Все, что мы захотим сделать с нашей CustomUser моделью, является опцией.
Группа в ВК "Django_Python"
Заключение
Поздравляем с окончанием Django для начинающих! Начав с абсолютного нуля, мы
создали пять различных веб приложений с нуля. Мы рассмотрели все основные функции
Django: шаблоны, представления, urls, пользователей, модели, безопасность, тестирование
и развертывание. Теперь у вас есть знания, чтобы идти дальше и создавать свои
собственные современные веб сайты с Django.
Как и в случае с любым новым навыком, важно практиковать и применять то, что вы
только что узнали. Функциональность CRUD в нашем блоге и газете распространена во
многих, многих других веб приложениях. Например, можно ли создать веб приложение
списка задач? У вас уже есть все необходимые инструменты.
Веб разработка это очень глубокая область, и есть еще многое, что узнать о том, что Django
может предложить. Например, более продвинутый проект Django, скорее всего, будет
использовать несколько файлов настроек, переменных и PostgreSQL локально вместо
SQLite. Он может даже использовать сторонние пакеты, такие как django-allauth для
социальной аутентификации, django-debug-toolbar для отладки и django-extensions для
дополнительных вкусностей.
Лучший способ узнать больше о Django и веб разработке в целом это подумать о проекте,
который вы хотите построить, а затем шаг за шагом узнать, что вам нужно для его
завершения. Дополнительным ресурсом, который может помочь, является DjangoX,
который является реальным стартовым проектом, который имеет социальную
аутентификацию и многое другое.
Группа в ВК "Django_Python"
Conclusion 302
Ресурсы Django
Я также настоятельно рекомендую Two Scoops of Django 1.11: Best Practices for the
Django Web Framework, который является текущей Библией лучших практик для
разработчиков Django.
Книги Python
Группа в ВК "Django_Python"
Conclusion 303
• Automate the Boring Stuff это еще одно отличное руководство по обучению и
использованию Python в реальных условиях.
Блоги
• Real Python
• Dan Bader
• Trey Hunner
• Full Stack Python
• Ned Batchelder
• Armin Ronacher
• Kenneth Reitz
• Daniel Greenfeld
Обратная связь
Если вы прошли через всю книгу, мне бы очень хотелось услышать ваши мысли. Что тебе
понравилось или не понравилось? Какие области были особенно сложными? А какой
новый контент вы хотели бы видеть? Со мной можно связаться по адресу
will@wsvincent.com.
Группа в ВК "Django_Python"
От переводчика.
Группа в ВК "Django_Python"