Django-форма — это Python-класс. В шаблоне она превращается в HTML. Разберём способы рендера: от автоматического до полностью ручного.
Передача формы в шаблон
# forms.py
from django import forms
class CommentForm(forms.Form):
name = forms.CharField(max_length=100, label="Имя")
email = forms.EmailField(label="Email")
text = forms.CharField(widget=forms.Textarea, label="Комментарий")
# views.py
from django.shortcuts import render, redirect
from .forms import CommentForm
def add_comment(request, post_pk):
if request.method == 'POST':
form = CommentForm(request.POST)
if form.is_valid():
# сохранить данные
return redirect('post-detail', pk=post_pk)
else:
form = CommentForm()
return render(request, 'blog/comment_form.html', {'form': form})
Автоматический рендер
Быстрый способ — позволить Django самому отрисовать поля:
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="btn btn-primary">Отправить</button>
</form>
| Метод | HTML-обёртка |
|---|---|
{{ form.as_p }} |
Каждое поле в <p> |
{{ form.as_div }} |
Каждое поле в <div> (Bootstrap-совместимо) |
{{ form.as_table }} |
Таблица <tr>/<td> |
{{ form.as_ul }} |
Список <li> |
Ограничение: автоматический рендер не добавляет классы Bootstrap — стиль придётся задавать через CSS или виджеты.
Ручной рендер: полный контроль
Ручной рендер даёт полный контроль над HTML каждого поля:
<form method="post" novalidate>
{% csrf_token %}
<div class="mb-3">
{{ form.name.label_tag }}
{{ form.name }}
{% if form.name.errors %}
<div class="invalid-feedback d-block">
{{ form.name.errors }}
</div>
{% endif %}
</div>
<div class="mb-3">
{{ form.email.label_tag }}
{{ form.email }}
{% if form.email.errors %}
<div class="invalid-feedback d-block">
{{ form.email.errors }}
</div>
{% endif %}
</div>
<div class="mb-3">
{{ form.text.label_tag }}
{{ form.text }}
{% if form.text.errors %}
<div class="invalid-feedback d-block">
{{ form.text.errors }}
</div>
{% endif %}
</div>
<button type="submit" class="btn btn-primary">Отправить</button>
</form>
{{ form.name }} рендерит <input>, {{ form.name.label_tag }} — <label>, {{ form.name.errors }} — список ошибок валидации.
Bootstrap-классы через виджеты
Чтобы не писать стили в шаблоне, добавьте классы в форму:
# forms.py
class CommentForm(forms.Form):
name = forms.CharField(
max_length=100,
label="Имя",
widget=forms.TextInput(attrs={
'class': 'form-control',
'placeholder': 'Ваше имя',
})
)
email = forms.EmailField(
label="Email",
widget=forms.EmailInput(attrs={'class': 'form-control'})
)
text = forms.CharField(
label="Комментарий",
widget=forms.Textarea(attrs={
'class': 'form-control',
'rows': 4,
})
)
Теперь {{ form.as_p }} уже выдаст поля с классом form-control.
Цикл по полям формы
Если полей много, можно пройтись по ним в цикле:
<form method="post">
{% csrf_token %}
{% for field in form %}
<div class="mb-3">
{{ field.label_tag }}
{{ field }}
{% if field.help_text %}
<small class="form-text text-muted">{{ field.help_text }}</small>
{% endif %}
{% for error in field.errors %}
<div class="invalid-feedback d-block">{{ error }}</div>
{% endfor %}
</div>
{% endfor %}
{{ form.non_field_errors }}
<button type="submit" class="btn btn-primary">Отправить</button>
</form>
form.non_field_errors — ошибки, не привязанные к конкретному полю (например, из form.clean()).
Пример: форма входа на DevBlog
{% extends 'base.html' %}
{% block title %}Войти — DevBlog{% endblock %}
{% block content %}
<div class="row justify-content-center">
<div class="col-md-5">
<h1 class="mb-4">Вход</h1>
<form method="post">
{% csrf_token %}
<div class="mb-3">
<label for="{{ form.username.id_for_label }}" class="form-label">
Имя пользователя
</label>
{{ form.username }}
{{ form.username.errors }}
</div>
<div class="mb-3">
<label for="{{ form.password.id_for_label }}" class="form-label">
Пароль
</label>
{{ form.password }}
{{ form.password.errors }}
</div>
{% if form.non_field_errors %}
<div class="alert alert-danger">{{ form.non_field_errors }}</div>
{% endif %}
<button type="submit" class="btn btn-primary w-100">Войти</button>
</form>
</div>
</div>
{% endblock %}
💬 Комментарии (0)
Комментариев пока нет
Станьте первым, кто поделится мнением об этой статье!