文章目录
-
- 1. 表单类
-
- 1. 自定义表单
- 2. 自定义字段错误信息
- 3. 设置 widget 美化表单
- 2. 表单实例化与初始化
- 3. 模板中使用表单
- 4. 函数视图中使用表单
- 5. 类视图中使用表单
- 6. 表单的验证
- 7. Formset的使用
- 在app目录下新建 forms.py,用于自定义表单
- 表单Form类的作用是把用户输入的数据转化成Python对象格式,便于增删改查操作
1. 表单类
- Django提供了两种自定义表单的方式:继承Form类和ModelForm类
1. 自定义表单
- 继承 Form 类,需要自定义表单中的字段
- 继承 ModelForm 类,依据之前定义好Django模型字段来自动生成表单
from django import forms
from .models import Contact
class ContactForm1(forms.Form):
name = forms.CharField(label="Your Name", max_length=255)
email = forms.EmailField(label="Email address")
class ContactForm2(forms.ModelForm):
class Meta:
model = Contact
fields = ('name', 'email',)
2. 自定义字段错误信息
- 对于继承 Form类 的表单,可以针对每个字段自定义验证错误信息
from django import forms
class LoginForm(forms.Form):
username = forms.CharField(
required=True,
max_length=20,
min_length=6,
error_messages={
'required': '用户名不能为空',
'max_length': '用户名长度不得超过20个字符',
'min_length': '用户名长度不得少于6个字符',
}
)
- 对于继承 ModelForm类 的表单, 可以在Meta选项下来自定义错误信息
from django.forms import ModelForm, Textarea
from myapp.models import Author
class AuthorForm(ModelForm):
class Meta:
model = Author
fields = ('name', 'title', 'birth_date')
widgets = {
'name': Textarea(attrs={
'cols': 80, 'rows': 20}),
}
labels = {
'name': 'Author',
}
help_texts = {
'name': 'Some useful help text.',
}
error_messages = {
'name': {
'max_length': "This writer's name is too long.",
},
}
3. 设置 widget 美化表单
from django import forms
class ContactForm(forms.Form):
name = forms.CharField(
max_length=255,
widget=forms.Textarea(
attrs={
'class': 'custom'},
),
)
BIRTH_YEAR_CHOICES = ('1980', '1981', '1982')
COLORS_CHOICES = (
('blue', 'Blue'),
('green', 'Green'),
('black', 'Black'),
)
class SimpleForm(forms.Form):
birth_year = forms.DateField(
widget=forms.SelectDateWidget(years=list(BIRTH_YEAR_CHOICES))
)
favorite_colors = forms.MultipleChoiceField(
required=False,
widget=forms.CheckboxSelectMultiple,
choices=list(COLORS_CHOICES),
)
2. 表单实例化与初始化
form = ContactForm()
form = ContactForm(
initial={
'name': 'First and Last Name',
},)
default_data = {
'name': 'John', 'email': '[email protected]', }
form = ContactForm(default_data)
form = ContactForm(data=request.POST, files=request.FILES)
contact = Contact.objects.get(id=1)
form = ContactForm(instance = contact, data=request.POST)
3. 模板中使用表单
- 表单以form变量传递给模板,在模板文件中我们可以通过{ { form.as_p }}, { { form.as_li }}, { { form.as_table }} 的方式渲染表单
{
% block content %}
<div class="form-wrapper">
<form method="post" action="" enctype="multipart/form-data">
{
% csrf_token %}
{
% for field in form %}
<div class="fieldWrapper">
{
{
field.errors }}
{
{
field.label_tag }} {
{
field }}
{
% if field.help_text %}
<p class="help">{
{
field.help_text|safe }}</p>
{
% endif %}
</div>
{
% endfor %}
<div class="button-wrapper submit">
<input type="submit" value="Submit" />
</div>
</form>
</div>
{
% endblock %}
4. 函数视图中使用表单
- 设计一个表单让用户完成注册
- 在app目录下新建forms.py, 然后创建一个RegistrationForm
from django import forms
from django.contrib.auth.models import User
class RegistrationForm(forms.Form):
username = forms.CharField(label='Username', max_length=50)
email = forms.EmailField(label='Email',)
password1 = forms.CharField(label='Password', widget=forms.PasswordInput)
password2 = forms.CharField(label='Password Confirmation', widget=forms.PasswordInput)
- 在函数视图views.py中使用表单,并将其向指定模板传递
from django.shortcuts import render, get_object_or_404
from django.contrib.auth.models import User
from .forms import RegistrationForm
from django.http import HttpResponseRedirect
def register(request):
if request.method == 'POST':
form = RegistrationForm(request.POST)
if form.is_valid():
username = form.cleaned_data['username']
email = form.cleaned_data['email']
password = form.cleaned_data['password2']
user = User.objects.create_user(username=username, password=password, email=email)
return HttpResponseRedirect("/accounts/login/")
else:
form = RegistrationForm()
return render(request, 'users/registration.html', {
'form': form})
5. 类视图中使用表单
from django.views.generic.edit import CreateView
from .models import Article
from .forms import ArticleForm
class ArticleCreateView(CreateView):
model = Article
fields = ['title', 'body']
template_name = 'blog/article_form.html'
class ArticleCreateView(CreateView):
model = Article
form_class = ArticleForm
template_name = 'blog/article_form.html'
6. 表单的验证
- 每个forms类可以通过自定义 clean() 方法进行表单验证
- 可以自定义 clean_字段名() 方法只对某些字段进行验证
- 如果数据有效 form.is_valid() == True,则会将数据存储在cleaned_data 字典里
from django import forms
from django.contrib.auth.models import User
import re
def email_check(email):
pattern = re.compile(r"\"?([-a-zA-Z0-9.`?{}]+@\w+\.\w+)\"?")
return re.match(pattern, email)
class RegistrationForm(forms.Form):
username = forms.CharField(label='Username', max_length=50)
email = forms.EmailField(label='Email',)
password1 = forms.CharField(label='Password', widget=forms.PasswordInput)
password2 = forms.CharField(label='Password Confirmation', widget=forms.PasswordInput)
def clean_username(self):
username = self.cleaned_data.get('username')
if len(username) < 6:
raise forms.ValidationError("Your username must be at least 6 characters long.")
elif len(username) > 50:
raise forms.ValidationError("Your username is too long.")
else:
user = User.objects.filter(username__exact=username).first()
if user.exists():
raise forms.ValidationError("Your username already exists.")
return username
def clean_email(self):
email = self.cleaned_data.get('email')
if email_check(email):
filter_result = User.objects.filter(email__exact=email)
if len(filter_result) > 0:
raise forms.ValidationError("Your email already exists.")
else:
raise forms.ValidationError("Please enter a valid email.")
return email
def clean_password1(self):
password1 = self.cleaned_data.get('password1')
if len(password1) < 6:
raise forms.ValidationError("Your password is too short.")
elif len(password1) > 20:
raise forms.ValidationError("Your password is too long.")
return password1
def clean_password2(self):
password1 = self.cleaned_data.get('password1')
password2 = self.cleaned_data.get('password2')
if password1 and password2 and password1 != password2:
raise forms.ValidationError("Password mismatch. Please enter again.")
return password2
7. Formset的使用
- 1个页面上使用多个表单,可以创建一个Formset,表单的集合
from django import forms
class BookForm(forms.Form):
name = forms.CharField(max_length=100)
title = forms.CharField()
pub_date = forms.DateField(required=False)
from django.forms import formset_factory
from .forms import BookForm
BookFormSet = formset_factory(BookForm, extra=2, max_num=1)
- 在视图文件views.py,像使用form一样使用formset
from .forms import BookFormSet
from django.shortcuts import render
def manage_books(request):
if request.method == 'POST':
formset = BookFormSet(request.POST, request.FILES)
if formset.is_valid():
pass
else:
formset = BookFormSet()
return render(request, 'manage_books.html', {
'formset': formset})
<form action=”.” method=”POST”>
{
{
formset }}
</form>