Build a Personal Diary With Django and Python

Оглавление

Создание дневника Django позволяет создать персональное безопасное веб-приложение на вашем компьютере без использования внешних облачных сервисов. В этом руководстве вы узнаете о настройке проекта Django, в котором вы сможете создавать, читать, обновлять и удалять записи. Вы изучите ключевые концепции, такие как модели, представления на основе классов и шаблоны, что даст вам представление о будущих проектах на Django.

К концу этого урока вы поймете, что:

  • Создание дневника - отличный проект для начинающих, поскольку он включает в себя фундаментальные концепции веб-приложений, такие как CRUD-операции и аутентификация.
  • Представления на основе классов обеспечивают структурированный способ обработки распространенных шаблонов веб-приложений с меньшими затратами кода.
  • Вы можете использовать сайт администратора Django для аутентификации, упростив механизм входа в систему, чтобы обезопасить свои записи в дневнике.

Это руководство проведет вас шаг за шагом к окончательному написанию дневника. Если вы только начинаете работать с Django и хотите завершить свой первый настоящий проект, то это руководство для вас!

Чтобы получить полный исходный код проекта Django и его пошаговые инструкции, перейдите по ссылке ниже:

Получите исходный код: Нажмите здесь, чтобы получить исходный код, который вы будете использовать для создания веб-приложения для личного дневника на Django и Python в этом руководстве.

Демонстрационное видео

На главной странице вашего дневника у вас будет список записей. Вы можете просматривать их и создавать новые одним нажатием кнопки. В этом руководстве представлен стиль оформления, поэтому вы можете сосредоточиться на части кода, связанной с Django. Вот краткое демонстрационное видео о том, как это будет выглядеть в действии:

К концу урока вы сможете безошибочно ориентироваться в своем дневнике, создавать, читать, обновлять и удалять записи по требованию.

Обзор проекта

Учебное пособие состоит из нескольких этапов. Таким образом, вы можете делать перерывы и продолжать в своем собственном темпе. На каждом этапе вы будете заниматься определенной областью вашего дневникового проекта:

  1. Настройка вашего проекта Django diary
  2. Создание записей в серверной части
  3. Отображение записей во внешнем интерфейсе
  4. Добавление стиля
  5. Управление записями во внешнем интерфейсе
  6. Улучшение взаимодействия с пользователем
  7. Внедрение аутентификации

Следуя дальше, вы познакомитесь с основами веб-приложений и с тем, как добавить общие функции в проект Django. После завершения обучения вы создадите свое собственное приложение для ведения личного дневника и получите схему проекта Django, на основе которой сможете работать.

Предварительные условия

Для завершения этого проекта вам не нужны какие-либо предварительные знания Django. Если вы хотите узнать больше о темах, с которыми вы столкнетесь в этом руководстве, вы найдете ссылки на ресурсы по ходу работы.

Однако вам должно быть удобно пользоваться командной строкой и вы должны обладать базовыми знаниями о Python и классы. Хотя полезно знать о виртуальных средах и pip, в процессе работы с руководством вы узнаете, как все настроить.

Шаг 1: Настройка вашего дневника Django

Запустите проект, создав каталог вашего проекта и настроив виртуальную среду. Эта настройка изолирует ваш код от любых других проектов на вашем компьютере. Вы можете назвать папку проекта и виртуальную среду любым удобным для вас способом. В этом руководстве папка проекта называется my-diary, а виртуальная среда - .venv/.

Выберите свою операционную систему ниже, затем с помощью команды, зависящей от вашей платформы, создайте папку проекта и перейдите во вновь созданную папку:

PS> mkdir my-diary\
PS> cd my-diary\
$ mkdir my-diary/
$ cd my-diary/

Сначала вы создаете новую папку с именами my-diary/, а затем переходите в нее. В my-diary/ настройте виртуальную среду:

PS> python -m venv .venv\
PS> .\venv\Scripts\activate
(venv) PS>
$ python -m venv .venv/
$ source venv/bin/activate
(venv) $

С помощью приведенных выше команд вы создаете и активируете виртуальную среду с именем .venv, используя встроенный в Python модуль venv. Надпись в скобках (.venv) перед приглашением означает, что вы успешно активировали виртуальную среду.

Примечание: В остальной части руководства предполагается, что вы будете выполнять команды, связанные с Python и Django, в вашей активной виртуальной среде.

Единственное дополнительное требование к вашему дневнику - это сам Django. Установите конкретную версию этого руководства с помощью pip:

(.venv) $ python -m pip install Django==5.1

Эта команда устанавливает Django и некоторые зависимости, которые требуются для Django. Это все, что вам нужно.

Инициализировать Django

Когда все требования выполнены, пришло время приступить к самому проекту Django. Используйте утилиту командной строки Django для создания базовой структуры проекта:

(.venv) $ django-admin startproject diary .

Не забудьте добавить точку (.) в конце приведенной выше команды. Точка не позволяет Django создавать другой каталог для вашего дневникового проекта.

Django только что создал файл manage.py и папку с именем diary с пятью файлами. Вам не обязательно точно понимать, что они делают. Если вам интересно, вы можете взглянуть на файлы. Все они содержат объяснение в начале, в котором описывается, почему они существуют. В ходе этого урока вам нужно будет отредактировать только два из них:

File Edited during tutorial?
manage.py
diary/__init__.py
diary/asgi.py
diary/settings.py
diary/urls.py
diary/wsgi.py

С этого момента файл manage.py будет выполнять административные задачи в командной строке. С некоторыми из них вы познакомитесь в этом руководстве.

Создайте базу данных

Теперь, когда основа вашего проекта Django diary подготовлена, вам нужно место для хранения будущего содержимого вашего дневника. Для этого вы должны создать базу данных .

Django поставляется с поддержкой нескольких баз данных и по умолчанию работает с базой данных SQLite, если не предусмотрено никаких других конфигураций базы данных. База данных SQLite - это все, что вам нужно, потому что вы единственный пользователь, который подключается к ней, и ваш проект Django diary будет запущен только локально.

Самое приятное то, что вы можете создать базу данных SQLite с помощью одной команды. Запустив миграции, вы применяете изменения схемы базы данных к базе данных:

(.venv) $ python manage.py migrate

Когда вы заглянете в каталог вашего проекта, вы должны увидеть файл db.sqlite3. Похлопайте себя по плечу: вы только что создали базу данных!

Чтобы сравнить текущее состояние вашего проекта с загружаемыми файлами для этого руководства, перейдите по ссылке ниже:

Получите исходный код: Нажмите здесь, чтобы получить исходный код, который вы будете использовать для создания веб-приложения для личного дневника на Django и Python в этом руководстве.

Файлы, относящиеся к этому разделу, находятся в каталоге source_code_step_1/.

Быть суперпользователем

Как владелец своего личного дневника, вы заслужили роль superuser. Воспользуйтесь этой командой:

(.venv) $ python manage.py createsuperuser
Username (leave blank to use 'root'): admin
Email address: admin@example.com
Password: RealPyth0n
Password (again): RealPyth0n
Superuser created successfully.

Вам будет предложено выбрать имя пользователя, указать адрес электронной почты и установить пароль. Это ключ к вашему дневнику, поэтому обязательно запомните его.

Запуск веб-сервера разработки

Другой командой, которую вы будете часто использовать, является runserver. Эта команда запускает облегченный веб-сервер разработки :

(.venv) $ python manage.py runserver

Вы можете указать IP-адрес и порт подключения. runserver. По умолчанию сервер работает через порт 8000 на 127.0.0.1 и доступен только на вашем компьютере. При запущенном сервере вы можете посетить свой проект Django в своем браузере, используя либо http://127.0.0.1:8000, либо http://localhost:8000:

Successful Django Installation

Это домашняя страница вашего дневника. Пока что на ней видна только ракета. Это означает, что установка прошла успешно.

Важно: Каждый раз, когда вы посещаете свой проект diary в браузере, вы должны сначала запустить свой локальный веб-сервер разработки, если он еще не запущен.

Завершите первый шаг этого руководства, посетив http://localhost:8000/admin и войдя в систему под своими учетными данными:

Django admin site - Start

Это ваш собственный сайт администратора Django! Это одна из самых мощных функций Django. С помощью всего лишь нескольких настроек вы сможете управлять контентом и пользователями прямо сейчас. На данный момент на сайте администратора Django не так много интересного. Пришло время это изменить!

Шаг 2: Добавление записей вашего дневника в серверную часть

Проект Django содержит одно или несколько приложений. Область применения приложения должна быть ограничена. Вначале различие между проектом и приложениями может привести к путанице. Но в крупных проектах на Django такое разделение задач обеспечивает чистоту кодовой базы. Еще одним преимуществом этой структуры является то, что вы можете повторно использовать приложения для других проектов.

Подключите приложение Entries

В вашем терминале веб-сервер разработки Django, возможно, все еще запущен. Остановите его, нажав Ctrl+C в терминале.

Совет: Откройте второе окно терминала, чтобы управлять сервером в одном окне и запускать команды в другом:

Split Pane Terminal for Django Development

После того, как вы перешли к своему проекту и активировали виртуальную среду, вы можете запускать предстоящие команды этого проекта во втором окне терминала.

В этом руководстве вам понадобится только одно дополнительное приложение. Основное назначение этого приложения - обрабатывать записи в вашем дневнике, поэтому давайте назовем его entries. Запустите команду для создания приложения entries:

(.venv) $ python manage.py startapp entries

Эта команда создает в вашем проекте папку entries/ с некоторыми предопределенными файлами. Позже в этом руководстве вам нужно будет отредактировать только три из них:

File Edited during tutorial?
entries/__init__.py
entries/admin.py
entries/apps.py
entries/models.py
entries/tests.py
entries/views.py

Как вы можете видеть, некоторые из них имеют те же имена, что и файлы в каталоге diary/. Перейдя по ссылке ниже, вы можете сравнить свою структуру папок со структурой в каталоге source_code_step_2/:

Получите исходный код: Нажмите здесь, чтобы получить исходный код, который вы будете использовать для создания веб-приложения для личного дневника на Django и Python в этом руководстве.

Пока что Django не знает приложение, которое вы только что создали. Чтобы подключить приложение entries к проекту Django diary, добавьте путь к классу конфигурации в начале списка INSTALLED_APPS в diary/settings.py:

diary/settings.py

# ...

INSTALLED_APPS = [
  "entries.apps.EntriesConfig",
  "django.contrib.admin",
  "django.contrib.auth",
  "django.contrib.contenttypes",
  "django.contrib.sessions",
  "django.contrib.messages",
  "django.contrib.staticfiles",
]

# ...

Приложение entries теперь подключено к проекту diary, и Django находит его конфигурации. Одной из таких конфигураций является модель, которая описывает, как должны выглядеть записи вашего дневника в базе данных.

Создайте модель записей

Вы уже создали базу данных. Теперь пришло время определить таблицу базы данных, в которой будут храниться записи вашего дневника. В Django это делается с помощью класса model. Как и в случае с обычными классами в Python, имена моделей должны быть в единственном числе и в верхнем регистре. Пока ваше приложение называется entries, ваша модель будет называться Entry.

Поля модели Entry являются элементами, которые будут содержать записи в дневнике. В начале эти поля будут отображаться в виде формы. В конце они будут столбцами вашей таблицы базы данных Entry. Запись в дневнике в этом руководстве содержит три поля:

  1. title это заголовок.
  2. content является основным текстом.
  3. date_created это дата и время создания.

В entries/models.py сначала импортируйте timezone из django.utils. Затем создайте класс Entry в том же файле, как показано ниже:

entries/models.py

 1from django.db import models
 2from django.utils import timezone
 3
 4class Entry(models.Model):
 5    title = models.CharField(max_length=200)
 6    content = models.TextField()
 7    date_created = models.DateTimeField(default=timezone.now)
 8
 9    def __str__(self):
10        return self.title
11
12    class Meta:
13        verbose_name_plural = "Entries"

Импортируя модуль timezone, вы можете использовать timezone.now в качестве аргумента default для date_created в строке 7. Таким образом, текущие дата и время будут использоваться по умолчанию, если вы не зададите для них конкретное значение при создании записи. Вы воспользуетесь этим режимом позже, когда будете создавать форму для записей в своем дневнике.

В дополнение к title, content, и date_created, Django автоматически добавит id в качестве уникального первичного ключа. Строковое представление записи с первичным ключом 1 по умолчанию будет равно Entry object (1). Когда вы добавляете .__str__(), вы можете настроить то, что отображается вместо этого. Для записи в дневнике лучше использовать название в виде строки.

Еще одна переменная, которую вам необходимо настроить, - это verbose_name_plural. В противном случае Django записал бы множественное число вашего Entry как Entrys, а не Entries.

Зарегистрируйте модель входа

Чтобы также увидеть модель Entry на сайте администратора Django, вам необходимо зарегистрировать ее в entries/admin.py:

entries/admin.py

from django.contrib import admin
from .models import Entry

admin.site.register(Entry)

Django не выдаст ошибку, если вы забудете зарегистрировать модель на сайте администратора. В конце концов, не каждой моделью нужно управлять в пользовательском интерфейсе. Но для создания минимально жизнеспособного продукта в виде вашего дневника вы воспользуетесь преимуществами встроенного сайта администратора Django.

Перенос модели ввода

После добавления нового класса и его регистрации на сайте администратора вам необходимо создать файлы миграции для Django и запустить их. С помощью makemigrations вы создаете файлы миграции, которые содержат инструкции Django по созданию и обновлению схемы базы данных. С помощью migrate вы реализуете их:

(.venv) $ python manage.py makemigrations
(.venv) $ python manage.py migrate

После завершения миграции запустите веб-сервер разработки, перейдите в браузер и посетите сайт администратора Django по адресу http://localhost:8000/admin:

Django admin site without entries

На данный момент записей в списке нет. Завершите этот шаг, создав хотя бы одну запись в своем дневнике, нажав Добавить запись. Не уверены, что написать? Может быть, стоит задуматься о том, как здорово, что у вас есть полностью функциональный сервер для вашего проекта Django diary!

Шаг 3: Отображение записей вашего дневника на интерфейсе

Теперь вы можете добавлять новые записи на сайт администратора Django. Но когда вы заходите на главную страницу своего дневника в браузере, он по-прежнему показывает дрожащую ракету. На этом шаге вы узнаете, как отображать записи в вашем дневнике на интерфейсе.

Если вы хотите посмотреть, как будет выглядеть код в конце этого шага, перейдите по ссылке ниже:

Получите исходный код: Нажмите здесь, чтобы получить исходный код, который вы будете использовать для создания веб-приложения для личного дневника на Django и Python в этом руководстве.

Файлы, относящиеся к этому шагу, находятся в каталоге source_code_step_3/.

Создание списка и подробных представлений

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

Меньше работы - это хорошо. Но это не единственная причина, по которой вы будете использовать представления на основе классов для своего дневника. В вашем дневнике Django будут использоваться представления, типичные для веб-приложений, например, для отображения списка элементов базы данных или их сведений. Вот почему просмотры на основе классов - хороший выбор для просмотра вашего дневника.

Django предоставляет множество универсальных представлений "из коробки". В этом случае вы создадите подклассов из a DetailView и a ListView и подключите их к вашей модели Entry в entries/views.py:

entries/views.py

 1from django.views.generic import (
 2    ListView,
 3    DetailView,
 4)
 5
 6from .models import Entry
 7
 8class EntryListView(ListView):
 9    model = Entry
10    queryset = Entry.objects.all().order_by("-date_created")
11
12class EntryDetailView(DetailView):
13    model = Entry

Как и было обещано, на данный момент вам предстоит написать не так уж много кода. Запрос Entry.objects.all() в строке 10 вернет все записи, упорядоченные по их первичному ключу. Добавление в него .order_by("-date_created") приведет к возврату ваших записей в порядке возрастания, с самой новой записью в верхней части списка.

Когда вы пишете представление, подобное этому, Django в фоновом режиме делает предположения, такие как название и местоположение шаблона для отображения в представлении.

Создавайте свои шаблоны

С помощью шаблонов вы можете генерировать HTML динамически. Django ожидает, что шаблоны для представлений на основе классов, которые вы только что создали, будут находиться в определенном месте с определенным именем. Создайте вложенные папки для ваших шаблонов:

(.venv) $ mkdir -p entries/templates/entries

Конечно, путь к шаблонам выглядит немного странно из-за повторяющегося entries. Но таким образом вы гарантируете, что Django найдет именно те шаблоны, которые вам нужны, даже если другие приложения используют те же имена моделей. Внутри entries/templates/entries/ вы будете хранить все файлы шаблонов для модели Entry. Начните с создания entry_list.html и добавления этого содержимого:

entries/templates/entries/entry_list.html

 1{% for entry in entry_list %}
 2    <article>
 3        <h2 class="{{ entry.date_created|date:'l' }}">
 4            {{ entry.date_created|date:'Y-m-d H:i' }}
 5        </h2>
 6        <h3>
 7            <a href="{% url 'entry-detail' entry.id %}">
 8                {{ entry.title }}
 9            </a>
10        </h3>
11    </article>
12{% endfor %}

В шаблонах Django вы даже можете динамически ссылаться на классы CSS. Если вы посмотрите на <h2> в режиме онлайн 3, вы увидите, что к нему добавлен class="{{ entry.date_created|date:'l' }}". Здесь отображается временная метка со специальным форматированием . Таким образом, элемент <h2> будет иметь день недели в качестве класса, и позже вы сможете присвоить каждому дню недели уникальный цвет в CSS.

Внутри цикла entry_list вы можете получить доступ к полям модели Entry. Чтобы не загромождать список слишком большим количеством информации, вы будете показывать содержимое только при посещении страницы сведений о записи. Создайте эту страницу сведений в entries/templates/entries/ с entry_detail.html в качестве имени файла и добавьте следующее содержимое:

entries/templates/entries/entry_detail.html

<article>
    <h2>{{ entry.date_created|date:'Y-m-d H:i' }}</h2>
    <h3>{{ entry.title }}</h3>
    <p>{{ entry.content }}</p>
</article>

Шаблон detail ожидает ровно один объект ввода. Вот почему вы можете получить к нему прямой доступ здесь, без цикла.

Добавляйте маршруты в свои просмотры

Чтобы увидеть шаблоны в действии, вам необходимо подключить свои представления к URL-адресам. Django работает с файлом urls.py для отправки входящих запросов от пользователей в браузере. Файл, подобный этому, уже существует в папке проекта diary. Для приложения entries вы должны сначала создать его в entries/urls.py и добавить пути к EntryListView и EntryDetailView:

entries/urls.py

 1from django.urls import path
 2from . import views
 3
 4urlpatterns = [
 5    path(
 6        "",
 7        views.EntryListView.as_view(),
 8        name="entry-list"
 9    ),
10    path(
11        "entry/<int:pk>",
12        views.EntryDetailView.as_view(),
13        name="entry-detail"
14    ),
15]

Функция path() в строках 5 и 10 должна иметь как минимум два аргумента:

  1. Строковый шаблон маршрута, содержащий шаблон URL-адреса
  2. Ссылка на представление, которое является функцией as_view() для представлений на основе классов

Кроме того, вы можете передать дополнительные аргументы в виде ключевых слов, чтобы указать имя. С помощью имени вы можете легко ссылаться на представления в своем проекте Django. Таким образом, даже если вы решите изменить шаблон URL, вам не нужно обновлять свои шаблоны.

Теперь, когда URL-адреса для entries приложения готовы, вам нужно подключить их к urlpatterns списку diary. Когда вы откроете diary/urls.py, вы увидите urlpatterns, который используется в вашем проекте Django Diary. Пока что есть только маршрут к "admin/", который добавлен по умолчанию, чтобы вы могли попасть на сайт администратора Django. Чтобы показать записи вашего дневника при посещении http://localhost:8000, вам сначала нужно отправить корневой URL-адрес приложения entries:

diary/urls.py

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path("admin/", admin.site.urls),
    path("", include("entries.urls")),
]

После создания новых шаблонов вручную перезапустите веб-сервер разработки Django. Затем посетите http://localhost:8000 и наслаждайтесь просмотрами:

Diary Entries Unstyled

Вы можете просмотреть подробную информацию о записи, щелкнув ссылку на нее в списке или посетив http://localhost:8000/entries/1, где 1 - это ID существующей записи.

Теперь все готово для просмотра ваших записей в личном кабинете. Однако ваш дневник все еще выглядит немного не оформленным. Давайте изменим это на следующем шаге!

Шаг 4: Приведение вашего дневника Django в порядок

На этом шаге вы добавите немного стиля в свой дневник. Если вы хотите взглянуть на готовый код этого шага, перейдите по ссылке ниже и ознакомьтесь с каталогом source_code_step_4/:

Получите исходный код: Нажмите здесь, чтобы получить исходный код, который вы будете использовать для создания веб-приложения для личного дневника на Django и Python в этом руководстве.

Несмотря на то, что вы пишете творчески, дизайн дневника в настоящее время немного упрощен. Вы можете начать с создания базового шаблона по адресу entries/templates/entries/base.html с таким содержимым:

entries/templates/entries/base.html

{% load static %}
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>My Diary</title>
    <link rel="stylesheet" href="{% static 'css/diary.css' %}">
</head>

<body>
    <h1><a href="/">Dear diary …</a></h1>

    {% block content %}{% endblock content %}

</body>

</html>

С помощью наследования шаблонов вам не нужно повторять разметку в своих шаблонах. Вместо этого вы расширяете свои дочерние шаблоны. Затем Django автоматически объединяет их вместе при отображении в представлении.

Добавить таблицу стилей

Вставив {% load static %} в начало файла шаблона, вы можете ссылаться на статические файлы с помощью тега {% static %} шаблона и относительного пути к файлу шаблона. CSS-файл. Создайте diary.css в entries/static/css/ и разверните поле ниже, чтобы просмотреть CSS-код, который вы добавите в файл.

 

Скопируйте и вставьте приведенный ниже CSS-код в diary.css:

entries/static/css/diary.css

* {
    box-sizing: border-box;
}

body {
    font-family: sans-serif;
    font-size: 18px;
}

a {
    color: inherit;
}
a:hover {
    opacity: 0.7;
}

h1 {
    font-size: 2.8em;
}

h1 a {
    text-decoration: none;
}

h2, h3 {
    font-size: 1.4em;
    margin: 0;
    display: inline-block;
    padding: 0.5rem 1rem;
    vertical-align: top;
}

h2 {
    background-color: aquamarine;
}

.mark {
    background-color: gainsboro;
}
.mark a {
    text-decoration: none;
}

article {
    margin-bottom: 0.5rem;
}

p {
    font-size: 1.2em;
    padding-left: 1rem;
    line-height: 1.3em;
    max-width: 36rem;
    color: dimgray;
}

em {
    font-style: normal;
    font-weight: bold;
}

/* Form */

label {
    display: block;
}

button,
textarea,
input {
    font-size: inherit;
    min-height: 2.5em;
    padding: 0 1rem;
}

input[type="text"],
textarea {
    width: 100%;
}

textarea {
    padding: 0.5rem 1rem;
    font-family: sans-serif;
}

button,
input[type="submit"] {
    margin: 0 1rem 2px 1rem;
    cursor: pointer;
    font-weight: bold;
    min-width: 8rem;
}

/* Day coloring */

.Saturday,
.Sunday {
    background-color: lightsalmon;
}

Не стесняйтесь улучшать и оптимизировать приведенный выше код, чтобы настроить любые элементы по своему вкусу. Если вы не знакомы с CSS, стоит изучить основы, если вы занимаетесь веб-разработкой.

Как указывалось ранее, каждый элемент <h2> в списке записей имеет свой день недели в качестве класса. Оформив .Saturday и .Sunday по-разному, вы сможете легко определить выходные дни в списке.

Расширение дочерних шаблонов

Теперь пришло время соединить дочерние шаблоны с родительским шаблоном base.html. Обновите entries/templates/entries/entry_list.html таким образом, это выглядит следующим образом:

entries/templates/entries/entry_list.html

 1{% extends "entries/base.html" %}
 2
 3{% block content %}
 4    {% for entry in entry_list %}
 5        <article>
 6            <h2 class="{{ entry.date_created|date:'l' }}">
 7                {{ entry.date_created|date:'Y-m-d H:i' }}
 8            </h2>
 9            <h3>
10                <a href="{% url 'entry-detail' entry.id %}">
11                    {{ entry.title }}
12                </a>
13            </h3>
14        </article>
15    {% endfor %}
16{% endblock content %}

Тег {% block %} template определяет часть документа, которую может переопределять дочерний шаблон. Чтобы включить это, вы должны объявить, что ваш дочерний шаблон расширяет родительский шаблон, и определить блочный элемент с таким же именем. С помощью тега шаблона {% extends %} в строке 1 вы определяете entries/base.html в качестве родительского элемента. {% block %} и {% endblock %} в строках 3 и 16 завершаете разметку, которая будет размещена в content родительский блок.

Проделайте то же самое для entries/templates/entries/entries_detail.html:

entries/templates/entries/entries_detail.html

{% extends "entries/base.html" %}

{% block content %}
    <article>
        <h2>{{ entry.date_created|date:'Y-m-d H:i' }}</h2>
        <h3>{{ entry.title }}</h3>
        <p>{{ entry.content }}</p>
    </article>
{% endblock content %}

Оба шаблона наследуют структуру HTML и стиль оформления от своего родительского шаблона. У них одинаковые заголовок и <h1>, а также стиль, предоставляемый diary.css. Чтобы увидеть это в действии, запустите свой сервер разработки Django и перейдите к http://localhost:8000:

Diary Entries Styled

Теперь вы можете читать свои записи со вкусом. Однако, если вы хотите создать, обновить или удалить запись, вам нужно перейти на сайт администратора Django. Это слишком много кликов, если вы хотите быстро записать какие-то мысли. На следующем шаге вы улучшите свой рабочий процесс, добавив эту функциональность во внешний интерфейс.

Шаг 5: Управление записями в вашем дневнике на интерфейсе

При создании и использовании веб-приложений вы постоянно выполняете четыре основные операции. Эти операции настолько распространены, что часто их просто обозначают аббревиатурой CRUD:

  • C< < < 3> >
  • > reate<<<4 > > >
  • R< < < 7> >
  • > ead <<<8 > > >
  • Update
  • < < < 12>>>
  • D< < < 15>
  • > > elete<<<16 > > >

На сайте администратора Django вы уже можете выполнить все эти действия. В интерфейсе вы пока можете только читать свои записи. Чтобы использовать функциональность сайта администратора Django, вы повторите то, что уже делали для EntryDetail и EntryList, добавив представление, шаблон и URL-адрес.

Добавить виды

В entries/views.py вы уже импортировали ListView и DetailView. Обновите инструкции по импорту, чтобы они выглядели следующим образом:

entries/views.py

from django.urls import reverse_lazy
from django.views.generic import (
    ListView,
    DetailView,
    CreateView,
    UpdateView,
    DeleteView,
)

# ...

Добавьте свои три подкласса в нижней части таблицы. entries/views.py:

entries/views.py

 1# ...
 2
 3class EntryCreateView(CreateView):
 4    model = Entry
 5    fields = ["title", "content"]
 6    success_url = reverse_lazy("entry-list")
 7
 8class EntryUpdateView(UpdateView):
 9    model = Entry
10    fields = ["title", "content"]
11
12    def get_success_url(self):
13        return reverse_lazy(
14            "entry-detail",
15            kwargs={"pk": self.entry.id}
16        )
17
18class EntryDeleteView(DeleteView):
19    model = Entry
20    success_url = reverse_lazy("entry-list")

На этот раз недостаточно подключить классы к вашей модели Entry. Для EntryCreateView и EntryUpdateView вам также необходимо определить, какие поля модели должны отображаться в форме, как вы можете видеть в строках 5 и 10. Ваш EntryDeleteView в строке 18 выполняет только действие по удалению элемента ввода, поэтому вам не нужно определять в нем какие-либо поля.

Кроме того, вам необходимо определить, куда следует перенаправить пользователя после отправки формы просмотра. По умолчанию, .get_success_url() просто возвращает значение success_url. В EntryUpdateView вам нужно перезаписать этот метод.

Указав entry.id в качестве аргумента ключевого слова в строке 15, вы останетесь на странице сведений о записи после ее редактирования. Вместо прямого использования URL-адресов вы используете reverse_lazy(), чтобы ссылаться на них по имени, точно так же, как вы делали это в своих шаблонах.

Создайте шаблоны

Как и раньше, Django ищет шаблоны с определенным именем:

  • Для EntryDeleteView, это entry_confirm_delete.html.
  • Для EntryCreateView, это entry_form.html.
  • Для EntryUpdateView это было бы entry_update_form.html.

Когда Django не находит entry_update_form.html, он пробует entry_form.html в качестве запасного варианта. Вы можете воспользоваться этим, создав шаблон, который обрабатывает оба представления в entries/templates/entries/ и добавив базовую форму отправки:

entries/templates/entries/entry_form.html

 1{% extends "entries/base.html" %}
 2
 3{% block content %}
 4    <form method="post">
 5        {% csrf_token %}
 6        {{ form.as_p }}
 7        <input type="submit" value="Save">
 8    </form>
 9    {% if entry %}
10        <a href="{% url 'entry-detail' entry.id %}">
11            <button>Cancel</button>
12        </a>
13    {% else %}
14        <a href="{% url 'entry-list' %}">
15            <button>Cancel</button>
16        </a>
17    {% endif %}
18{% endblock content %}

Когда этот шаблон будет загружен с помощью CreateView, форма будет пустой, и при ее отмене вы снова вернетесь к списку записей. При загрузке с помощью CreateUpdateView он будет предварительно заполнен текущим названием и содержанием записи. Отмена приведет вас на страницу сведений о записи.

Существует несколько способов отобразить форму в шаблоне. С помощью {{ form.as_p }} в строке 6 Django отобразит поля, которые вы определили в представлении, в виде абзацев. Всякий раз, когда вы публикуете контент в Django forms, вы также должны включать в него тег {% csrf_token %} template в строке 5. Это мера безопасности для предотвращения подделки межсайтовых запросов.

Как и в случае с другими шаблонами, вы добавляете {% extends "entries/base.html" %} в строку 1, чтобы расширить базовый шаблон. Затем вы определяете, что включить в тег block content между строками 4 и 17. Вы используете тот же шаблон для entry_confirm_delete.html в entries/templates/entries/:

entries/templates/entries/entry_confirm_delete.html

{% extends "entries/base.html" %}

{% block content %}
    <form method="post">
        {% csrf_token %}
        <p>
            Are you sure you want to delete
            <em>"{{ entry.title }}"</em>
            created on {{ entry.date_created|date:'Y-m-d' }}?
        </p>
        <input type="submit" value="Confirm">
    </form>
    <a href="{% url 'entry-detail' entry.id %}">
        <button>Cancel</button>
    </a>
{% endblock content %}

Этот шаблон появится, когда вы собираетесь удалить запись. Упоминание "{{ entry.title }}" и {{ entry.created_date|date:'Y-m-d' }} в форме напоминает вам, какую запись вы хотели бы удалить, нажав Подтвердить.

Создайте URL-адреса

После того, как вы создали виды и их шаблоны, создайте их маршруты, чтобы получить к ним доступ во внешнем интерфейсе. Добавьте три дополнительных пути к urlpatterns в entries/urls.py:

entries/urls.py

from django.urls import path
from . import views

urlpatterns = [
    path(
        "",
        views.EntryListView.as_view(),
        name="entry-list"
    ),
    path(
        "entry/<int:pk>",
        views.EntryDetailView.as_view(),
        name="entry-detail"
    ),
    path(
        "create",
        views.EntryCreateView.as_view(),
        name="entry-create"
    ),
    path(
        "entry/<int:pk>/update",
        views.EntryUpdateView.as_view(),
        name="entry-update",
    ),
    path(
        "entry/<int:pk>/delete",
        views.EntryDeleteView.as_view(),
        name="entry-delete",
    ),
]

Для entry-create вам нужен только базовый путь create. Как и для entry-detail, созданных ранее, для entry-update и entry-delete требуется первичный ключ, чтобы определить, какую запись следует обновить или удалить.

Теперь вы можете создавать, обновлять и удалять записи для своего дневника непосредственно в интерфейсе. Запустите веб-сервер разработки и посетите http://localhost:8000/create, чтобы протестировать его. Если вы хотите сравнить свой код с кодом из этого руководства, то перейдите по ссылке ниже:

Получите исходный код: Нажмите здесь, чтобы получить исходный код, который вы будете использовать для создания веб-приложения для личного дневника на Django и Python в этом руководстве.

Вы можете найти файлы, относящиеся к этому шагу, в каталоге source_code_step_5/.

Шаг 6: Улучшение Вашего пользовательского опыта

Используя свой дневник, вы, возможно, наткнулись на несколько особенностей, которые несколько затрудняют навигацию. На этом этапе вы разберетесь с ними по очереди. Вы увидите, что небольшие изменения в интерфейсе могут существенно повлиять на удобство работы с вашим дневником.

Управляйте своим успехом

Всегда приятно получить обратную связь, особенно если она положительная. Используя фреймворк сообщений, вы можете быстро определить одноразовые флэш-сообщения, которые будут отображаться после отправки ваших форм. Чтобы воспользоваться этой функцией, импортируйте messages и SuccessMessageMixin в entries/views.py:

entries/views.py

from django.contrib import messages
from django.contrib.messages.views import SuccessMessageMixin
from django.urls import reverse_lazy
from django.views.generic import (
    ListView,
    DetailView,
    CreateView,
    UpdateView,
    DeleteView,
)

from .models import Entry

# ...

EntryListView и EntryDetailView являются представлениями для чтения и не обрабатывают форму. Они могут отображать сообщение в шаблоне, но не отправлять его. Это означает, что вам не нужно создавать для них подклассы SuccessMessageMixin. EntryCreateView, EntryUpdateView а EntryDeleteView, с другой стороны, добавляют уведомление в хранилище сообщений, поэтому вам необходимо настроить их функциональность:

entries/views.py

 1# ...
 2
 3class EntryCreateView(SuccessMessageMixin, CreateView):
 4    model = Entry
 5    fields = ["title", "content"]
 6    success_url = reverse_lazy("entry-list")
 7    success_message = "Your new entry was created!"
 8
 9class EntryUpdateView(SuccessMessageMixin, UpdateView):
10    model = Entry
11    fields = ["title", "content"]
12    success_message = "Your entry was updated!"
13
14    def get_success_url(self):
15        return reverse_lazy(
16            "entry-detail",
17            kwargs={"pk": self.object.pk}
18        )
19# ...

После наследования SuccessMessageMixin в EntryCreateView в строке 3 и в EntryUpdateView в строке 9 вы определяете success_message для них в строках 7 и 12. Особенно важно, когда вы совершаете деструктивные действия, такие как удаление записи, сообщить, что все прошло нормально. Чтобы отобразить сообщение в виде DeleteView, вам необходимо добавить пользовательский метод .delete() и добавить свой пользовательский метод success_message в messages framework вручную:

entries/views.py

 1# ...
 2
 3class EntryDeleteView(DeleteView):
 4    model = Entry
 5    success_url = reverse_lazy("entry-list")
 6    success_message = "Your entry was deleted!"
 7
 8    def delete(self, request, *args, **kwargs):
 9        messages.success(self.request, self.success_message)
10        return super().delete(request, *args, **kwargs)

Вам нужен этот дополнительный метод в строке 8, потому что класс DeleteView не является предком класса FormView. Вот почему вы можете не добавлять SuccessMessageMixin в свой EntryDeleteView в строке 3.

Нажмите на ссылку ниже, чтобы ознакомиться с полным содержанием entries/views.py. Вы можете найти его в source_code_step_6/ каталоге:

Получите исходный код: Нажмите здесь, чтобы получить исходный код, который вы будете использовать для создания веб-приложения для личного дневника на Django и Python в этом руководстве.

Теперь, когда представления отправляют сообщения, вам нужно улучшить шаблоны для их отображения.

Получить сообщение

Сообщения хранятся в хранилище сообщений. Просматривая его, вы показываете все сообщения, которые в данный момент находятся в хранилище сообщений. В шаблонах Django это достигается с помощью тега шаблона сообщения. После того, как вы создали дневник и структурировали шаблоны, вам нужно только добавить его в entries/base.html:

entries/base.html

 1<!-- ...  -->
 2
 3<h1><a href="/">Dear diary …</a></h1>
 4
 5{% if messages %}
 6    <ul class="messages">
 7    {% for message in messages %}
 8        <li class="message">
 9            {{ message }}
10        </li>
11    {% endfor %}
12    </ul>
13{% endif %}
14
15{% block content %}{% endblock content %}
16
17<!-- ...  -->

Заключая список сообщений в {% if messages %} в строках 5 и 13, вы гарантируете, что он будет отображаться только условно, если в хранилище есть какие-либо сообщения.

Улучшите свою навигацию

Чтобы создать, отредактировать или удалить запись, вам нужно запомнить соответствующие URL-адреса и затем ввести их в адресную строку. Как это утомительно! К счастью, вы можете исправить это, добавив ссылки на просмотры. Начните со ссылки на представление entry-create в шаблоне entries/templates/entries/entry_list.html:

entries/templates/entries/entry_list.html

 1<!-- ... -->
 2
 3{% block content %}
 4<article>
 5    <h2 class="mark">{% now "Y-m-d H:i" %}</em></h2>
 6    <a href="{% url 'entry-create' %}"><button>Add new entry</button></a>
 7</article>
 8
 9{% for entry in entry_list %}
10<!-- ... -->

Эта разметка будет похожа на другие элементы списка записей дневника. Добавьте новый абзац в шаблон entries/templates/entries/entry_detail.html сразу после </article>, чтобы быстро отредактировать или удалить запись:

entries/templates/entries/entry_detail.html

<!-- ... -->

</article>
<p>
    <a href="{% url 'entry-update' entry.id %}">✍️ Edit</a>
    <a href="{% url 'entry-delete' entry.id %}">⛔ Delete</a>
</p>
{% endblock content %}
<!-- ... -->

Этот код добавляет две ссылки под деталями записи, которые ссылаются на entry-update и entry-delete соответственно.

Оформляйте свои сообщения

Наконец, оформите флэш-сообщения, добавив .messages и .message в конце текста. entries/static/css/diary.css:

/* entries/static/css/diary.css */

/* Messages */

.messages {
    padding: 0;
    list-style: none;
}

.message {
    width: 100%;
    background: lightblue;
    padding: 1rem;
    text-align: center;
    margin: 1rem 0;
}

Остановите веб-сервер разработки, нажав Ctrl+C в терминале и перезапустите его. Затем перейдите на страницу http://localhost:8000, чтобы увидеть свои изменения в действии. Если сообщения выглядят нестыкованными, возможно, вам придется очистить кэш вашего браузера, чтобы он перезагрузил изменения в таблице стилей:

Diary List With Message

Теперь у вас есть полноценное веб-приложение для ведения дневника, полностью созданное на Django. Хотя ваш дневник хранится только локально, рекомендуется убедиться, что только вы можете получить к нему доступ. Давайте добавим это ограничение, прежде чем вы начнете вести журнал.

Шаг 7: Заблокируйте свой дневник Django

Если для физического дневника подойдет маленький золотой замочек, то для вашего цифрового дневника подойдет форма входа в систему. Ключом к этой блокировке является комбинация имени и пароля, которые вы уже используете для входа на сайт администратора Django.

Повторно используйте свой логин администратора Django

Система аутентификации , которую предоставляет Django, довольно проста. Для других проектов с обычными пользователями вы можете рассмотреть возможность ее настройки. Но для вашего Django diary достаточно повторно использовать логин сайта администратора Django. Вскоре вы увидите, что это прекрасно работает. Сначала давайте позаботимся о выходе из системы.

Добавить кнопку выхода из системы

Вы выходите из системы, отправив запрос POST на специальный URL-адрес. Django предоставляет встроенный URL-адрес с именем admin:logout для выхода из системы с сайта администратора Django. Когда вы вошли в систему и у вас есть форма, указывающая на этот URL-адрес из любой точки вашего проекта, Django автоматически завершит ваш вход при отправке формы.

Примечание: В более ранних версиях Django вы могли выйти из системы с запросом GET, обратившись к admin:logout. С выпуском Django 5.0 представление, расположенное за admin:logout, принимает только запросы POST.

Чтобы отправить запрос POST на URL-адрес выхода из системы из любой точки вашего сайта, добавьте эту форму внизу страницы. entries/templates/entries/base.html:

entries/templates/entries/base.html

{% load static %}
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>My Diary</title>
    <link rel="stylesheet" href="{% static 'css/diary.css' %}">
</head>

<body>
<h1><a href="/">Dear diary …</a></h1>

{% if messages %}
    <ul class="messages">
    {% for message in messages %}
        <li class="message">
            {{ message }}
        </li>
    {% endfor %}
    </ul>
{% endif %}

{% block content %}{% endblock content %}

<hr>
<form method="post" action="{% url 'admin:logout' %}">
    {% csrf_token %}
    {{ form.as_p }}
    <input type="submit" value="Logout" />
</form>
</body>

</html>

Запустите свой веб-сервер разработки, перейдите на свою домашнюю страницу по адресу http://localhost:8000 и нажмите на ссылку Выход из системы. Теперь, когда вы заходите на страницу http://localhost:8000/admin, вы видите форму входа в систему. Это означает, что вы вышли из системы. Однако, когда вы снова заходите на страницу http://localhost:8000, ваши записи в дневнике по-прежнему доступны. Пора это изменить!

Ограничить доступ к Вашим просмотрам

В Django вы можете определить, кому разрешено просматривать те или иные просмотры. По умолчанию они открыты для всех, кто посещает ваш веб-сайт. Чтобы убедиться, что для доступа к представлениям требуется аутентифицированный пользователь, импортируйте LoginRequiredMixin в верхней части entries/views.py:

entries/views.py

from django.contrib.auth.mixins import LoginRequiredMixin
from django.contrib import messages
from django.contrib.messages.views import SuccessMessageMixin
from django.urls import reverse_lazy
from django.views.generic import (
    ListView,
    DetailView,
    CreateView,
    UpdateView,
    DeleteView,
)

from .models import Entry

# ...

Как только класс представления использует LoginRequiredMixin,, сначала требуется успешный вход в систему. Кроме того, вы должны определить login_url, чтобы Django знал, куда перенаправлять вас, когда вы не вошли в систему. Вместо того, чтобы делать это для всех классов по отдельности, вы можете создать базовый класс, который наследует LoginRequiredMixin и определяет login_url в entries/views.py:

entries/views.py

# ...

class LockedView(LoginRequiredMixin):
    login_url = "admin:login"

# ...

Теперь вы можете наследовать LockedView во всех ваших других представлениях, которые должны быть доступны только для аутентифицированных пользователей. Отредактируйте entries/views.py таким образом, ваши классы выглядят следующим образом:

entries/views.py

# ...

class EntryListView(LockedView, ListView):
    model = Entry
    queryset = Entry.objects.all().order_by("-date_created")

class EntryDetailView(LockedView, DetailView):
    model = Entry

class EntryCreateView(LockedView, SuccessMessageMixin, CreateView):
    model = Entry
    fields = ["title", "content"]
    success_url = reverse_lazy("entry-list")
    success_message = "Your new entry was created!"

class EntryUpdateView(LockedView, SuccessMessageMixin, UpdateView):
    model = Entry
    fields = ["title", "content"]
    success_message = "Your entry was updated!"

    def get_success_url(self):
        return reverse_lazy(
            "entry-detail",
            kwargs={"pk": self.object.pk}
        )

class EntryDeleteView(LockedView, SuccessMessageMixin, DeleteView):
    model = Entry
    success_url = reverse_lazy("entry-list")
    success_message = "Your entry was deleted!"

    def delete(self, request, *args, **kwargs):
        messages.success(self.request, self.success_message)
        return super().delete(request, *args, **kwargs)

Теперь при посещении http://localhost:8000 вы будете перенаправлены на форму входа в систему Django. После входа в систему вы будете перенаправлены на список записей и увидите все, что доступно только вашим глазам:

Django Diary Final Entry

И это все! Вы успешно создали свой собственный личный дневник в Django. Если вы хотите сравнить свой код с окончательным кодом проекта, перейдите по ссылке ниже:

Получите исходный код: Нажмите здесь, чтобы получить исходный код, который вы будете использовать для создания веб-приложения для личного дневника на Django и Python в этом руководстве.

Полный код для проекта находится в каталоге source_code_final/.

Следующие шаги

Созданный вами дневник полностью функционален и готов к использованию. Но он также является отличной основой для дальнейшего развития. Возможно, у вас уже есть какие-то идеи относительно того, как вы можете еще больше улучшить свой дневник. Или вы можете попробовать одну из приведенных ниже идей:

  • Добавьте страницу для ваших последних записей.
  • Придайте каждому дню недели свой цвет.
  • Укажите дату создания в теге HTML <title>.
  • Создайте эмодзи с указанием выбранного дня для записи.
  • Разбейте список записей на страницы.

На протяжении всего этого урока вы знакомились с некоторыми базовыми концепциями и шаблонами, которые предоставляет Django. Надеюсь, это вызвало у вас интерес к более глубокому изучению веб-фреймворка Python. Если вы хотите продолжить свое путешествие и узнать больше, вы можете ознакомиться с этими руководствами:

Вы можете применить знания, полученные при выполнении проекта "Дневник", к другим учебным пособиям по Django и вывести свои навыки работы с веб-приложениями на новый уровень!

Заключение

В этом руководстве вы с нуля создали личный дневник с помощью Django. Вы узнали, как создать полнофункциональное веб-приложение, которым можно пользоваться изо дня в день. В нем используются многие преимущества Django, включая сайт администратора, представления на основе классов, фреймворк сообщений и систему шаблонов.

Этот проект на Django также является идеальной основой для ваших будущих проектов на Django. Шаги, которые вы выполнили в этом дневниковом проекте, в основном аналогичны шагам, которые вы выполняете в других проектах, таких как блог или приложение для выполнения задач..

В этом руководстве вы узнали, как:

  • Создать проект на Django
  • Работа со стандартной базой данных SQLite
  • Воспользуйтесь сайтом администратора Django
  • Создание моделей и представлений на основе классов
  • Вложенность и стиль шаблонов
  • Защитите свой дневник с помощью аутентификации

Вы можете скачать полный исходный код для дневника Django, перейдя по ссылке ниже:

Получите исходный код: Нажмите здесь, чтобы получить исходный код, который вы будете использовать для создания веб-приложения для личного дневника на Django и Python в этом руководстве.

Часто задаваемые вопросы

Теперь, когда у вас есть некоторый опыт в создании личного дневника с помощью Django, вы можете воспользоваться приведенными ниже вопросами и ответами, чтобы проверить свое понимание и резюмировать то, что вы узнали.

Эти часто задаваемые вопросы относятся к наиболее важным понятиям, которые вы рассмотрели в этом руководстве. Нажмите на переключатель Показывать/скрывать рядом с каждым вопросом, чтобы открыть ответ.

 

Создание дневника - хороший проект для начинающих, поскольку он охватывает фундаментальные концепции веб-разработки, такие как настройка проекта Django, создание моделей, обработка представлений и реализация аутентификации, и все это в рамках управляемой области.

 

Представления на основе классов в Django позволяют вам организовать свой код, инкапсулируя логику представления в классы многократного использования, уменьшая избыточность и делая ваш код более удобным в обслуживании.

 

Вы можете использовать сайт администратора Django для аутентификации, используя встроенную систему входа в систему, которая позволяет ограничить доступ к просмотрам вашего веб-приложения только для прошедших проверку подлинности пользователей.

<статус завершения article-slug="django-дневник-проект-python" class="btn-group mb-0" data-api-статья-закладка-url="/api/v1/статьи/django-дневник-проект-python/закладка/" data-api-статья-статус завершения-url="/api/v1/articles/django-дневник-проекта-python/завершение_статуса/"> <кнопка поделиться bluesky-text="Интересная статья на #Python от @realpython.com :" email-body="Ознакомьтесь с этой статьей о Python:%0A%0 Как создать личный дневник с помощью Django и Python" email-subject="Статья о Python для вас" twitter-text="Интересная статья о #Python от @realpython:" url="https://realpython.com/django-diary-project-python /" url-title="Создайте личный дневник с помощью Django и Python">

Вернуться на верх