- HTML
- Django templates
- наследование
- передача переменных
- Дополнительная литература
- HTML формы
- HTML формы
- HTML формы
- Django формы
- Django формы
- Django формы
- [Form Fields](#orgac68da6)
- Bound / Unbond forms
- Unbound
- Bound
- Валидация форм
- Валидаторы
- Валидаторы
- Валидаторы
- Forms Workflow
- Рендеринг форм вручную
- Безопасность
- CSRF
- CSRF
- CSRF
- ModelForm
- ModelForm
- ModelForm
- ModelForm
- ModelForm
- ModelForm
- ModelForm
- ModelForm
- Widgets
- Widgets
- Widgets
- Widgets
- Немного практики
- Вопросы-ответы
<html>
<head>
<title>Мир! Труд! Май!</title>
</head>
<body>
<center
onclick="alert('привет!')"
style="color:red;font-size:40px"
>
<!-- тут нужно вставить своё имя -->
<i>Привет, <ИМЯ>!</i>
</center>
</body>
</html>
<html>
<head>
<title>Мир! Труд! Май!</title>
</head>
<body>
<center
onclick="alert('привет!')"
style="color:red;font-size:40px"
>
<i>Привет, {{ name }}!</i>
</center>
</body>
</html>
- extends: взять за основу расширяемый шаблон и переопределить в нём нужные блоки. Остальное содержимое шаблона останется прежним.
- include: вставить на место {% include … %} содержимое подключаемого шаблона.
- В шаблоне доступны объекты из middleware, например user
- Нужные вам переменные вы передаёте из вьюхи во время рендеринга
- https://docs.djangoproject.com/en/2.2/ref/templates/builtins/
- https://docs.djangoproject.com/en/2.2/topics/templates/
- https://habr.com/ru/post/23132/?ysclid=l2hw076rbl
HTML-формы это просто текст. И вообщем-то мы можем писать его вручную или, например, с использованием f-string в Python.
<form action="." method="post">
<label for="message">Послание</label>
<input type='text' name="message"
value="сообщение"
maxlength="100" />
<input type="submit"
value="Отправить" />
</form>
Формы могут быть более красивыми
И очень разнообразными. Но писать такие разнообразные формы вручную это очень утомительно. На помощь нам приходят Django Forms.
from django import forms
class MessageForm(forms.Form):
message = forms.CharField(
label='Послание',
max_length=100
)
form = MessageForm(
initial={'message': 'сообщение'}
)
initial заполнит форму какими-то данными. При рендеринге это будет значение атрибута value в HTML. Обычно мы передаём туда request.POST
<tr>
<th>
<label for="id_message">
Послание:
</label>
</th>
<td>
<input type="text"
name="message"
value="сообщение"
maxlength="100"
required
id="id_message" />
</td>
</tr>
Поля формы в Django описываются классами Field, каждый из которых имеет своё представление в виде Widget-а.
Формы в Django могут быть в двух состояних
- unbound: — форма пустая
- bound: — форма заполнена данными
Форма не связана ни с какими данными
form = MessageForm()
form.is_bound # -> False
Форма частично или полностью заполнена
# обычно мы передаём request.POST
form = MessageForm({
'message': 'foobar'
})
form.is_bound # -> True
form.is_valid() # -> True / False
# в случае когда is_valid -> True,
# тогда у формы появляется атрибут
# cleaned_data, который содержит
# словарь со значениями полей
form.cleaned_data['field_name']
# если is_valid -> False
# то заполняется переменная
form.errors
Пример написания своего валидатора
from django.core.exceptions import (
ValidationError
)
def validate_even(value):
if value % 2 != 0:
raise ValidationError(
'%(value) нечётно',
params={'value': value}
)
from django import forms
class EvenNumbersForm(forms.Form):
number = forms.IntegerField(
validators=[validate_even]
)
validators добавит валидаторы к уже существующему базовому валидатору IntegerField
Готовых валидаторов очень много!
{{ form.non_field_errors }}
<div class="fieldWrapper">
{{ form.subject.errors }}
<label
for="{{form.subject.id_for_label}}" />
>
Email subject:
</label>
{{ form.subject }}
</div>
Настоятельно рекомендую ознакомиться с этой документацией
\newline
https://docs.djangoproject.com/en/3.2/topics/security/
На сайте может быть обычная кнопка, предлагающая вам посмотреть фотографии.
А на самом деле там будет отправляться форма перевода денег с вашего аккаунта на аккаунт злоумышленника.
<form
action="bank.com/transfer.do"
method="POST">
<input type="hidden"
name="acct" value="воришка"/>
<input type="hidden"
name="amount" value="$1kk"/>
<input type="submit"
value="View my pictures!"/>
</form>
Но если на стороне банка используются csrf-токены в формах, то ничего страшного не случится. Запрос злоумышленника не может содержать нужное значение (случайное в рамках сессии) csrf-токена.
<form method="post"
action="{% url signup %}">
{% csrf_token %}
</form>
У ModelForm появляется метод .save()
class NameForm(models.ModelForm):
class Meta:
model = Name
form = NameForm(request.POST)
# сохранить запись в базу данных
form.save()
class NameForm(models.ModelForm):
class Meta:
model = Name
form = NameForm(request.POST)
# создаёт объект модели Name
# но не записываем его в базу
model = form.save(commit=False)
class YaForm(models.ModelForm):
class Meta:
# содержит поля X, Y, Z
model = YaModel
fields = ['X', 'Y']
form = YaForm(request.POST)
# не передаст в модель Z,
# а значит в базу запишется
# пустое значение поля Z
from.save()
Один из вариантов решения — определить модель заранее
model = YaModel(Z='foobar')
form = YaForm(
request.POST,
instance=model
)
# форма будет содержать все
# поля заполненными
form.save()
Или использовать commit=False чтобы доопределить модель перед записью в БД.
form = YaForm(request.POST)
model = form.save(commit=False)
model.Z = 'foobar'
model.save()
Допустим, мы определили модель
class Article(models.Model):
headline = models.CharField(
max_length=200,
null=True,
blank=True,
)
content = models.TextField()
Если поле не перечислено в fields или добавлено в excludes в Meta-классе, то это поле будет исключено из данных передаваемых в модель.
class ArticleForm(ModelForm):
slug = CharField(
validators=[validate_slug]
)
class Meta:
model = Article
# slug не попадёт в save()
fields = ['headline', 'content']
Виджеты это то как формы будут представлены на web-страницы, то есть виджеты отвечают за генерацию HTML-кода для полей форм.
Документация
Можно добавлять стили и другие атрибуты виджетам
class CommentForm(forms.Form):
name = forms.CharField(
widget=forms.TextInput(
attrs={'class': 'special'}
)
)
url = forms.URLField()
comment = forms.CharField(
widget=forms.TextInput(
attrs={'size': '40'}
)
)
class CommentForm(ModelForm):
class Meta:
model = Comment
fields = (
'name', 'url', 'comment'
)
widgets = {
'name': forms.TextInput(
attrs={'class': 'special', 'rows': 20}
),
'comment': forms.TextInput(
attrs={'size': '40'}
)
}
<input type="text" name="name"
class="special" required>
<input type="url" name="url"
required>
<input type="text" name="comment"
size="40" required>