Django Forms предоставляет мощный инструмент для:
- Генерации HTML-форм
- Валидации данных
- Преобразования данных в Python-типы
- Защиты от распространенных уязвимостей
Базовый класс для создания форм:
from django import forms
class SimpleForm(forms.Form):
username = forms.CharField(max_length=100)
email = forms.EmailField()
message = forms.CharField(widget=forms.Textarea)
Форма, связанная с моделью:
from django import forms
from .models import User
class UserForm(forms.ModelForm):
class Meta:
model = User
fields = ['username', 'email', 'bio']
# или fields = '__all__' для всех полей
exclude = ['created_at'] # исключение полей
class CompleteForm(forms.Form):
# Текстовые поля
text = forms.CharField(max_length=100)
email = forms.EmailField()
url = forms.URLField()
# Числовые поля
number = forms.IntegerField(min_value=0, max_value=100)
decimal = forms.DecimalField(max_digits=5, decimal_places=2)
# Поля выбора
choice = forms.ChoiceField(choices=[('1', 'One'), ('2', 'Two')])
multiple = forms.MultipleChoiceField(choices=[('1', 'One'), ('2', 'Two')])
# Булево поле
boolean = forms.BooleanField(required=False)
# Поля даты и времени
date = forms.DateField()
time = forms.TimeField()
datetime = forms.DateTimeField()
class FieldParametersExample(forms.Form):
username = forms.CharField(
label='Имя пользователя', # Label для поля
help_text='Введите ваше имя', # Вспомогательный текст
initial='John Doe', # Значение по умолчанию
required=True, # Обязательное поле
disabled=False, # Отключено ли поле
validators=[custom_validator] # Пользовательские валидаторы
)
class ValidationForm(forms.Form):
username = forms.CharField(
min_length=3,
max_length=32,
required=True
)
age = forms.IntegerField(
min_value=18,
max_value=99
)
from django.core.exceptions import ValidationError
def validate_even(value):
if value % 2 != 0:
raise ValidationError('%(value)s не является четным числом',
params={'value': value})
class CustomValidationForm(forms.Form):
even_number = forms.IntegerField(validators=[validate_even])
class PasswordForm(forms.Form):
password = forms.CharField(widget=forms.PasswordInput)
password_confirm = forms.CharField(widget=forms.PasswordInput)
def clean(self):
cleaned_data = super().clean()
password = cleaned_data.get('password')
password_confirm = cleaned_data.get('password_confirm')
if password and password_confirm and password != password_confirm:
raise ValidationError('Пароли не совпадают')
return cleaned_data
class WidgetsExample(forms.Form):
# Текстовые виджеты
text = forms.CharField(widget=forms.TextInput(attrs={
'class': 'form-control',
'placeholder': 'Введите текст'
}))
password = forms.CharField(widget=forms.PasswordInput)
large_text = forms.CharField(widget=forms.Textarea)
# Виджеты выбора
select = forms.ChoiceField(widget=forms.Select)
radio = forms.ChoiceField(widget=forms.RadioSelect)
checkbox = forms.BooleanField(widget=forms.CheckboxInput)
# Виджеты для дат
date = forms.DateField(widget=forms.DateInput(attrs={
'type': 'date'
}))
from django.core.exceptions import ValidationError
ALLOWED_TYPES = ['image/jpeg', 'image/png']
MAX_FILE_SIZE = 5 * 1024 * 1024 # 5MB
def validate_file(file):
if file.content_type not in ALLOWED_TYPES:
raise ValidationError(f'Неподдерживаемый тип файла: {file.content_type}')
if file.size > MAX_FILE_SIZE:
raise ValidationError('Файл слишком большой')
class FileUploadForm(forms.Form):
file = forms.FileField(
validators=[validate_file],
widget=forms.FileInput(attrs={
'class': 'form-control',
'accept': '.jpg,.jpeg,.png'
})
)
def upload_file(request):
if request.method == 'POST':
form = FileUploadForm(request.POST, request.FILES)
if form.is_valid():
handle_uploaded_file(request.FILES['file'])
return redirect('success')
else:
form = FileUploadForm()
return render(request, 'upload.html', {'form': form})
# forms/base.py
class BaseForm(forms.Form):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
for field in self.fields.values():
field.widget.attrs.update({'class': 'form-control'})
# forms/user.py
class UserForm(BaseForm):
username = forms.CharField(max_length=100)
email = forms.EmailField()
# validators.py
from django.core.validators import RegexValidator
phone_validator = RegexValidator(
regex=r'^\+?1?\d{9,15}$',
message='Номер телефона должен быть в формате: "+999999999"'
)
# forms.py
class ContactForm(forms.Form):
phone = forms.CharField(validators=[phone_validator])
class DatePickerWidget(forms.DateInput):
def __init__(self, attrs=None):
default_attrs = {'type': 'date'}
if attrs:
default_attrs.update(attrs)
super().__init__(default_attrs)
class EventForm(forms.Form):
date = forms.DateField(widget=DatePickerWidget)
class FormWithCustomErrors(forms.Form):
def add_error_class(self):
for field in self:
if field.errors:
field.field.widget.attrs['class'] += ' is-invalid'
def is_valid(self):
valid = super().is_valid()
if not valid:
self.add_error_class()
return valid
Django Forms предоставляет мощный и гибкий инструментарий для работы с формами. Ключевые моменты:
- Используйте ModelForm для форм, связанных с моделями
- Применяйте пользовательскую валидацию где необходимо
- Создавайте переиспользуемые компоненты
- Следите за безопасностью при обработке файлов
- Придерживайтесь DRY (Don't Repeat Yourself) принципа