Этот шаблон расширяет base.html, поэтому он имеет такую же базовую структуру, как и остальные страницы Learning Log. В точке (1) определяется форма HTML. Аргумент action сообщает серверу, куда передавать данные, отправленные формой; в данном случае данные возвращаются функции представления new_topic(). Аргумент method приказывает браузеру отправить данные в запросе типа POST.

Django использует шаблонный тег {% csrf_token %} (2) для предотвращения попыток получения несанкционированного доступа к серверу (атаки такого рода называются межсайтовой подделкой запросов). В точке (3) отображается форма; это наглядный пример того, насколько легко в Django выполняются такие стандартные операции, как отображение формы. Чтобы автоматически создать все поля, необходимые для отображения формы, достаточно включить шаблонную переменную {{ form.as_p }}. Модификатор as_p приказывает Django отобразить все элементы формы в формате абзацев — это простой способ аккуратного ­отображения формы.

Django не создает кнопку отправки данных для форм, поэтому мы определяем ее в точке (4).

<p>Создание ссылки на страницу new_topic</p>

Далее ссылка на страницу new_topic создается на странице topics:

topics.html

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

{% block content %}

Topics

    ...

    Add a new topic:

    {% endblock content %}

    Разместите ссылку после списка существующих тем. Полученная форма изображена на рис. 19.1. Воспользуйтесь ею и добавьте несколько своих тем.

    Рис. 19.1. Страница для добавления новой темы

    <p>Добавление новых записей</p>

    Теперь, когда пользователь может добавлять новые темы, он также захочет добавлять новые записи. Мы снова определим URL, напишем новую функцию и шаблон и создадим ссылку на страницу. Но сначала нужно добавить в forms.py еще один класс.

    <p>Класс EntryForm</p>

    Мы должны создать форму, связанную с моделью 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']

    (1) . . . .labels = {'text': ''}

    (2) . . . .widgets = {'text': forms.Textarea(attrs={'cols': 80})}

    Сначала в команду import к Topic добавляется Entry. Новый класс EntryForm наследует от forms.ModelForm и содержит вложенный класс Meta с указанием модели, на которой он базируется, и поле, включаемое в форму. Полю 'text' снова назначается пустая надпись (1) .

    В точке (2) включается атрибут widgets. Виджет (widget) представляет собой элемент формы HTML: однострочное или многострочное текстовое поле, раскрывающийся список и т.д. Включая атрибут widgets, вы можете переопределить виджеты, выбранные Django по умолчанию. Приказывая Django использовать элемент forms.Textarea, мы настраиваем виджет ввода для поля 'text', чтобы ширина текстовой области составляла 80 столбцов вместо значения по умолчанию 40. У пользователя будет достаточно места для создания содержательных записей.

    <p>URL-адрес для new_entry</p>

    Необходимо включить аргумент topic_id в URL-адрес для создания новой записи, потому что запись должна ассоциироваться с конкретной темой. Вот как выглядит URL, который мы добавляем в learning_logs/urls.py:

    urls.py

    ...

    urlpatterns = [

    ...

    . .# Страница для добавления новой записи

    . .url(r'^new_entry/(?P\d+)/$', views.new_entry, name='new_entry'),

    ]

    Эта схема URL соответствует любому URL-адресу в форме http://localhost:8000/new_entry/id/, где id — число, равное идентификатору темы. Выражение (?P\d+) захватывает числовое значение и сохраняет его в переменной topic_id. При запросе URL-адреса, соответствующего этой схеме, Django передает запрос и идентификатор темы функции представления new_entry().

    <p>Функция представления new_entry()</p>

    Функция представления new_entry очень похожа на функцию добавления новой темы:

    views.py

    from django.shortcuts import render

    ...

    from .models import Topic

    from .forms import TopicForm, EntryForm

    ...

    def new_entry(request, topic_id):

    . ."""Добавляет новую запись по конкретной теме."""

    (1) . .topic = Topic.objects.get(id=topic_id)

    . .

    (2) . .if request.method != 'POST':

    . . . .# Данные не отправлялись; создается пустая форма.

    (3) . . . .form = EntryForm() . . . .

    . .else:

    . . . .# Отправлены данные POST; обработать данные.

    (4) . . . .form = EntryForm(data=request.POST)

    . . . .if form.is_valid():

    (5) . . . . . .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}

    Перейти на страницу:

    Все книги серии Библиотека программиста

    Похожие книги