Pull to refresh

Работа с формами в Django

Level of difficultyMedium
Reading time4 min
Views39K
Original author: uswaretech.com
Формы являются одной из самых вкусных вещей в Django (после моделей, админки, url-маршрутизации и т.д.). Перед вами небольшое, но ёмкое руководство по их использованию, представляющее собой разбор 8 часто встречающихся ситуаций при программировании форм.

  • Задача. Проверка и отображение простейшей формы.
    Copy Source | Copy HTML<br/>class UserForm(forms.Form):<br/>
    username = forms.CharField()<br/>
    joined_on = forms.DateField() <br/>

    Этот код отвечает за отображение двух текстовых полей, за данные, которые содержатся в них, а так же за корректность введенной даты.

  • Задача. Создание формы, значения которой зависят от какого-то конкретного параметра. Например, вам может потребоваться отобразить значения, относящиеся к определённому субдомену.
    Copy Source | Copy HTML<br/>class UserForm(forms.Form):<br/> username = forms.CharField()<br/> plan = forms.ModelChoiceField(queryset = Plan.objects.none())<br/> <br/> def __init__(self, subdomain, *args, **kwargs):<br/> self.default_username = default_username<br/> super(UserForm, self).__init__(*args, **kwargs)<br/> self.fields['plan'].queryset = Plan.objects.filter(subdomain = subdomain) <br/>
    Здесь в методе __init__ мы переопределяем стандартный queryset поля plan. Подобным образом можно переопределять абсолютно любые атрибуты. Внимательный читатель Заметим также, что выборка происходит лишь после вызова super(UserForm, self).__init__(*args, **kwargs).

  • Задача. Многократное использование формы. Обработка данных с помощью cleaned_data.
    Copy Source | Copy HTML<br/>class UserForm(forms.Form):<br/> username = forms.CharField()<br/> <br/> def save(self):<br/> data = self.cleaned_data<br/> user = User.objects.create(username = data['username'])<br/> #create a profile<br/> UserProfile.objects.create(user = user, ...some more data...) <br/>
    Вы можете назвать этот метод как угодно, но обычно его называют save, чтобы сохранить сходство с ModelForm.

  • Задача. Создание формы с полями, которые имеют собственный вид проверки.
    Copy Source | Copy HTML<br/>class UserForm(forms.Form):<br/> username = forms.CharField()<br/> <br/> def clean_username(self):<br/> data = self.cleaned_data<br/> try:<br/> User.objects.get(username = data['username'])<br/> except User.DoesNotExist:<br/> return data['username']<br/> raise forms.ValidationError('This username is already taken.') <br/>
    Здесь идёт проверка на уникальность имени пользователя.

  • Задача. Создание формы с перекрёстной проверкой полей.
    Copy Source | Copy HTML<br/>class UserForm(forms.Form):<br/> username = forms.CharField()<br/> <br/> password1 = forms.PasswordField()<br/> password2 = forms.PasswordField()<br/> <br/> def clean(self):<br/> data = self.cleaned_data<br/> if "password1" in data and "password2" in data and data["password1"] != data["password2"]:<br/> raise forms.ValudationError("Passwords must be same") <br/>
    Пароли в двух полях проверяются на идентичность друг другу.

  • Задача. Создание формы, поля которой зависят от некого значения в базе данных. Например, вам может потребоваться отображать разные формы для разных пользователей.
    Copy Source | Copy HTML<br/>def get_user_form_for_user(user):<br/> class UserForm(forms.Form):<br/> username = forms.CharField()<br/> fields = user.get_profile().all_field()<br/> #Use field to find what to show. <br/>
    Выходом в данном случае будет — создавать форму динамически.

  • Задача. Создание HTML формы, работающей с несколькими моделями.
    Copy Source | Copy HTML<br/>#in forms.py<br/>class UserForm(forms.ModelForm):<br/> class Meta:<br/> model = User<br/> fields = ["username", "email"]<br/> <br/>class UserProfileForm(forms.ModelForm):<br/> class Meta:<br/> model = UserProfile<br/> <br/>#in views.py<br/>def add_user(request):<br/> ...<br/> if request.method == "POST":<br/> uform = UserForm(data = request.POST)<br/> pform = UserProfileForm(data = request.POST)<br/> if uform.is_valid() and pform.is_valid():<br/> user = uform.save()<br/> profile = pform.save(commit = False)<br/> profile.user = user<br/> profile.save()<br/> ....<br/> ...<br/> <br/>#in template<br/><br/> {{ uform.as_p }}<br/> {{ pform.as_p }}<br/> <input type="submit" ...><br/> <br/>

  • Задача. Использование нескольких форм одного типа на одной странице. Например, при создании опроса вам может понадобиться отобразить все вопросы на одной странице.
    Copy Source | Copy HTML<br/>#IN views.py<br/>def survey(request, survey_slug)<br/> ...<br/> questions = survey.questions.all()<br/> question_forms = []<br/> for question in questions:<br/> qform = QuestionForm(question=question, prefix = question.slug)<br/> question_forms.append(qform)<br/> ...<br/> if request.method == "POST":<br/> for question in questions:<br/> qform = QuestionForm(question=question, prefix = question.slug, data = request.POST)<br/> #Validate and do save action<br/> ...<br/> ... <br/>
    В этой ситуации нам очень поможет атрибут prefix.


Подробнее о формах, разумеется, вы можете прочитать в документации.
Tags:
Hubs:
Total votes 44: ↑39 and ↓5+34
Comments33

Articles