This page looks best with JavaScript enabled

Django Forms Functionality

 ·  ☕ 3 min read

1. Automatically Generating HTML Form Elements

A Widget is the tool used to render an HTML element.

  • Specifying a widget
1
2
3
4
5
6
from django import forms

class CommentForm(forms.Form):
    name = forms.CharField()
    url = forms.URLField()
    comment = forms.CharField(widget=forms.Textarea)

Output of CommentForm().as_table()

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
<tr>
  <th><label for="id_name">Name:</label></th>
  <td><input id="id_name" name="name" type="text" /></td>
</tr>
\n
<tr>
  <th><label for="id_url">Url:</label></th>
  <td><input id="id_url" name="url" type="url" /></td>
</tr>
\n
<tr>
  <th><label for="id_comment">Comment:</label></th>
  <td>
    <textarea cols="40" id="id_comment" name="comment" rows="10">\r\n</textarea>
  </td>
</tr>

The form field is specified to use the Textarea widget rather than the default TextInput widget.

  • Customizing widget styles
1
2
3
4
class CommentFormClass(forms.Form):
    name = forms.CharField(widget=forms.TextInput(attrs={'class': 'special'}))
    url = forms.URLField()
    comment = forms.CharField(widget=forms.TextInput(attrs={'size': '40'}))

Output of CommentFormClass().as_table()

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
<tr>
  <th><label for="id_name">Name:</label></th>
  <td><input class="special" id="id_name" name="name" type="text" /></td>
</tr>
\n
<tr>
  <th><label for="id_url">Url:</label></th>
  <td><input id="id_url" name="url" type="url" /></td>
</tr>
\n
<tr>
  <th><label for="id_comment">Comment:</label></th>
  <td><input id="id_comment" name="comment" size="40" type="text" /></td>
</tr>
  • Output form

Usually, in a function in views.py, we instantiate the Form and then pass it into the template.

1
2
3
4
5
from django.shortcuts import render
from .forms import CommentForm
    pass
    form = CommentForm()
    return render(request, 'my_template.html', {'form': form})

Used in the template, my_template.html. Based on {{ form }}, all form fields and attributes are split into HTML markup by Django’s template language.

1
2
3
4
<form action="/my_template_data/" method="post">
  {% csrf_token %} {{ form }}
  <input type="submit" value="Submit" />
</form>

Optional form rendering items:

{{ form.as_table }} renders them as a table inside tr tags

{{ form.as_p }} renders them inside p tags

{{ form.as_ul }} renders them inside ul tags

2. Checking the Validity of Form Data

To validate submitted data quickly and effectively. Django Forms provides support for checking the validity of form data.

The validation flow

  • Inherit from form.Form and create a custom Form class MyForm
  • Use request.POST to instantiate the MyForm class
  • Validity check, is_valid()
  • Get the valid data or return an error message

Here is a simple example:

forms.py

1
2
3
from django import forms
class Contact(forms.Form):
    email = forms.EmailField(error_messages={'required':u'邮箱不能为空'})

views.py

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
from django.http import HttpResponse
from .forms import Contact
def my_view(request):
    form = Contact(request.POST)
    if not form.is_valid():
        return HttpResponse(
            json.dumps({
                "result": False,
                "data": [],
                "message": form.errors,
                "code": -1
            }), content_type='application/json')
    else:
        return HttpResponse(
            json.dumps({
                "result": True,
                "data": [],
                "message": form.cleaned_data.get('email'),
                "code": -1
            }), content_type='application/json')

If the interface obtains the email field from the POST data and it is a valid email address, it returns True. Otherwise, it returns an error message.

2.1 Inheriting from Form

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
import re
from django import forms
from django.core.validators import validate_email
from django.core.exceptions import ValidationError

class ContactForm(forms.Form):
    cn8_re = re.compile(ur'^[-_\w\u4e00-\u9fa5]{3,16}$')
    SEXUAL_CHOICES = (
    (0, u'男'),
    (1, u'女')
    )
    # 正则校验
    nick_name = forms.RegexField(min_length=3, max_length=16, label=u'昵称',
                                 error_messages={
                                     'required': u'昵称不能为空,长度3~16中英文及_-',
                                     'invalid': u'请输入合法昵称(3~16位以内中英文字符).'
                                 }, regex=cn8_re)
    # 指定函数校验validate_email,可以指定多个
    email = forms.EmailField(validators=[validate_email])
    # 指定为Choice
    gender = forms.ChoiceField(choices=SEXUAL_CHOICES, required=False, label=u'性别')
    # 指定长度
    password_0 = forms.RegexField(min_length=8, max_length=20, label=u'密码',
                                  error_messages=''egex=pwd_regex)
    password_1 = forms.RegexField(min_length=8, max_length=20, label=u'确认密码',
                                  error_messages='pwd_error_msg', regex=pwd_regex)
    # 重载clean函数,实现自定义的校验
    def clean(self):
        if self.cleaned_data.get('password_0') != self.cleaned_data.get('password_1'):
            self.add_error('password_1', u"两次密码输入不匹配.")
            raise ValidationError(u"两次密码输入不匹配.")

        return self.cleaned_data

Django Forms provides a large number of Fields for data validity checking — ‘Field’, ‘CharField’, ‘IntegerField’, ‘DateField’, ‘TimeField’, ‘DateTimeField’, ‘DurationField’, ‘RegexField’, ‘EmailField’, ‘FileField’, ‘ImageField’, ‘URLField’, ‘BooleanField’… enough to cover the vast majority of scenarios.

2.2 Combining with a Model

If the data submitted by POST is meant to operate on Model data, why not keep it simple and initialize the Form’s fields directly from a Model? Of course that works.

models.py

1
2
3
4
from django.db import models
class Contact(models.Model):
    title = models.CharField(max_length=30)
    content = models.CharField(max_length=20)

form.py

1
2
3
4
5
6
from django.forms import ModelForm
from .models import Contact
class ConotactForm(ModelForm):
    class Meta:
        model = Contact
        field = ('title','content')  #只显示model中指定的字段

The Form only needs to inherit from the ModelForm class and specify the mapped Model in Meta, and Django Forms will automatically add the fields specified by field to the Form. There is no need, as when inheriting from forms.Form, to add one field at a time.


微信公众号
WRITTEN BY
微信公众号