Рис. 19.1. Страница для добавления новой темы
Редактирование данных 413
Добавление новых записей
Теперь, когда пользователь может добавлять новые темы, он также захочет добав-
лять новые записи. Мы снова определим URL, напишем новую функцию и шаблон
и создадим ссылку на страницу. Но сначала нужно добавить в
forms .py
еще один
класс.
Класс EntryForm
Мы должны создать форму, связанную с моделью
Entry
, но более специализиро-
ванную по сравнению с
TopicForm
:
forms.py
from django import forms
from .models import Topic, Entry
class TopicForm(forms.ModelForm):
...
class EntryForm(forms.ModelForm):
class Meta:
model = Entry
fields = ['text']
labels = {'text': ''}
widgets = {'text': forms.Textarea(attrs={'cols': 80})}
Сначала в команду
import
к
Topic
добавляется
Entry
. Новый класс
EntryForm
на-
следует от
forms.ModelForm
и содержит вложенный класс
Meta
с указанием модели,
на которой он базируется, и поле, включаемое в форму. Полю
'text'
снова назна-
чается пустая надпись .
В точке включается атрибут
widgets
. Виджет (widget) представляет собой эле-
мент формы HTML: однострочное или многострочное текстовое поле, раскрываю-
щийся список и т. д. Включая атрибут
widgets
, вы можете переопределить виджеты,
выбранные Django по умолчанию. Приказывая Django использовать элемент
forms.
Textarea
, мы настраиваем виджет ввода для поля
'text'
, чтобы ширина текстовой
области составляла 80 столбцов вместо значения по умолчанию 40. У пользователя
будет достаточно места для создания содержательных записей.
URL-адрес для new_entry
Необходимо включить аргумент
topic_id
в URL-адрес для создания новой записи,
потому что запись должна ассоциироваться с конкретной темой. Вот как выглядит
URL, который мы добавляем в
learning_logs/urls .py
:
urls.py
...
urlpatterns = [
...
# Страница для добавления новой записи
url(r'^new_entry/(?P\d+)/$', views.new_entry, name='new_entry'),
]
414 Глава 19 • Учетные записи пользователей
Эта схема URL соответствует любому URL-адресу в форме http://
localhost:8000/new_entry/id/, где id — число, равное идентификатору темы.
Выражение
(?P\d+)
захватывает числовое значение и сохраняет
его в переменной
topic_id
. При запросе URL-адреса, соответствующего этой
схеме, Django передает запрос и идентификатор темы функции представления
new_entry()
.
Функция представления new_entry()
Функция представления
new_entry
очень похожа на функцию добавления новой
темы:
views.py
from django.shortcuts import render
...
from .models import Topic
from .forms import TopicForm, EntryForm
...
def new_entry(request, topic_id):
"""Добавляет новую запись по конкретной теме."""
topic = Topic.objects.get(id=topic_id)
if request.method != 'POST':
# Данные не отправлялись; создается пустая форма.
form = EntryForm()
else:
# Отправлены данные POST; обработать данные.
form = EntryForm(data=request.POST)
if form.is_valid():
new_entry = form.save(commit=False)
new_entry.topic = topic
new_entry.save()
return HttpResponseRedirect(reverse('learning_logs:topic',
args=[topic_id]))
context = {'topic': topic, 'form': form}
return render(request, 'learning_logs/new_entry.html', context)
Мы обновляем команду
import
и включаем в нее только что созданный класс
EntryForm
. Определение
new_entry()
содержит параметр
topic_id
для сохранения
полученного значения из URL. Идентификатор темы понадобится для отображе-
ния страницы и обработки данных формы, поэтому мы используем
topic_id
для
получения правильного объекта темы .
В точке проверяется метод запроса: POST или GET. Блок
if
выполняется для
запроса GET, и мы создаем пустой экземпляр
EntryForm
. Для метода запроса
POST мы обрабатываем данные, создавая экземпляр
EntryForm
, заполненный
данными POST из объекта запроса . Затем проверяется корректность данных
формы. Если данные корректны, необходимо задать атрибут
topic
объекта записи
перед сохранением его в базе данных.
Редактирование данных 415
При вызове
save()
мы включаем аргумент
commit=False
для того, чтобы создать
новый объект записи и сохранить его в
new_entry
, не сохраняя пока в базе данных.
Мы присваиваем атрибуту
topic
объекта
new_entry
тему, прочитанную из базы дан-
ных в начале функции
, после чего вызываем
save()
без аргументов. В результате
запись сохраняется в базе данных с правильной ассоциированной темой.
В точке
пользователь перенаправляется на страницу темы. При вызове
reverse()
должны передаваться два аргумента: имя схемы URL, для которой
генерируется URL-адрес, и список аргументов со всеми аргументами, которые
должны быть включены в URL. Список аргументов содержит всего один элемент
topic_id
. Вызов
HttpResponseRedirect()
перенаправляет пользователя на стра-
ницу темы, для которой была создана запись, и пользователь видит новую запись
в списке записей.
Шаблон new_entry
Как видно из следующего кода, шаблон
new_entry
похож на шаблон
new_topic
:
new_entry.html
{% extends "learning_logs/base.html" %}
{% block content %}
{{ topic }}
Add a new entry:
{% endblock content %}
В начале страницы выводится тема , чтобы пользователь мог видеть, в какую тему
добавляется новая запись. Тема также служат ссылкой для возврата к основной
странице этой темы.
Аргумент
action
формы включает значение
topic_id
из URL, чтобы функция
представления могла связать новую запись с правильной темой . В остальном
этот шаблон почти не отличается от
new_topic .html
.
Создание ссылки на страницу new_entry
Затем необходимо создать ссылку на страницу
new_entry
на каждой странице темы:
topic.html
{% extends "learning_logs/base.html" %}
{% block content %}
Topic: {{ topic }}
416 Глава 19 • Учетные записи пользователей
Entries:
add new entry
{% endblock content %}
Ссылка добавляется перед выводом записей, потому что добавление новой запи-
си является самым частым действием на этой странице. На рис. 19.2 изображена
страница
new_entry
. Теперь пользователь может добавить сколько угодно новых
тем и новых записей по каждой теме. Опробуйте страницу
new_entry
, добавив не-
сколько записей для каждой из созданных вами тем.
Достарыңызбен бөлісу: |