網絡應用開發的5項基礎核心技術包括,,,和Form(表單)的使用。今天小編我就來拼個老命給你來介紹下第五項核心基礎知識之表單forms的設計與使用吧, 并重點介紹下表單的驗證。想持續了解后續 Web開發技術請訂閱我的公眾號【與大咖之路】。
什么是表單?何時使用表單?
在web開發里表單的使用必不可少。表單用于讓用戶提交數據或上傳文件,表單也用于讓用戶編輯已有數據。的表單Forms類的作用是把用戶輸入的數據轉化成對象格式,便于后續操作(比如存儲,修改)。
自定義表單
類似模型,表單也由各種字段組成。表單可以自定義(forms.Form),也可以由模型創建(forms.)。值得注意的是模型里用的是來描述一個字段, 而表單用的是label。
下面是兩個的例子。一個自定義,一個從Model創建。
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',)
的常用做法是在app文件夾下創建一個forms.py,專門存放app中所定義的各種表單,這樣方便集中管理表單。如果要使用上述表單,我們可以在視圖views.py里把它們像模型一樣進來直接使用。
表單實例化
下面方法可以實例化一個空表單,但里面沒有任何數據,可以通過 {{ form }}在模板中渲染。
用戶提交的數據可以通過以下方法與表單結合,生成與數據結合過的表單(Bound forms)。只能對Bound forms進行驗證。
模板文件中使用form
模板文件中我們可以通過{{ form.as_p }}, {{ form.as_li }} 和 {{ form. }}中渲染表單。如果你想詳細控制每個field的格式,你可以采取以下方式。
{% block content %}class="form-wrapper">
?
{% endblock %}
表單實際使用案例
我們現在需要設計一個表單讓用戶完成注冊。我們先在app目錄下新建forms.py,然后創建一個。代碼如下:
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)
當然你也可以不用新建forms.py而直接在html模板里寫表單,但我并不建議這么做。用forms.py的好處顯而易見:
我們使用的視圖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自帶create_user方法創建用戶,不需要使用save()
? ? ? ? ? ?user = User.objects.create_user(username=username, password=password, email=email)
? ? ? ? ? ?# 如果直接使用objects.create()方法后不需要使用save()
? ? ? ? ? ?return HttpResponseRedirect("/accounts/login/")
? ?else:
? ? ? ?form = RegistrationForm()
? ?return render(request, 'users/registration.html', {'form': form})
模板是.html這樣子的。如果你需要通過表單上傳圖片或文件,一定不要忘了給form加="/form-data"屬性。
我們來看下是怎么工作的:
表單的驗證
每個forms類可以通過clean方法自定義表單驗證。如果你只想對某些字段進行驗證,你可以通過字段名方式自定義表單驗證。如果用戶提交的數據未通過驗證,會返回,并呈現給用戶。如果用戶提交的數據有效form.(),則會將數據存儲在里。
在上述用戶注冊的案例里,我們在通過clean方法添加了用戶名驗證設置form表單可以選擇多個文件,郵箱格式驗證和密碼驗證。代碼如下。
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)
? ?# Use clean methods to define custom validation rules
? ?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:
? ? ? ? ? ?filter_result = User.objects.filter(username__exact=username)
? ? ? ? ? ?if len(filter_result) > 0:
? ? ? ? ? ? ? ?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
通用視圖里使用表單
在基于類的視圖(Class Based View)里使用表單也非常容易,只需定義就好了。下面是一個創建一篇新文章的例子。
from django.views.generic.edit import CreateView
from .models import Article
from .forms import ArticleForm
class ArticleCreateView(CreateView):
? ?model = Article
? ?form_class = ArticleForm
? ?template_name = 'blog/article_create_form.html'
自定義表單輸入的
forms的每個字段你都可以選擇你喜歡的輸入,比如多選,復選框。你還可以定義每個的css屬性。如果你不指定,會使用默認的,有時比較丑。
比如下面這段代碼定義了表單姓名字段的輸入控件為,還指定了其樣式css。
from django import forms
class ContactForm(forms.Form):
? ?name = forms.CharField(
? ? ? ?max_length=255,
? ? ? ?widget=forms.Textarea(
? ? ? ? ? ?attrs={'class': 'custom'},
? ? ? ?),
? ?)
設置可以是你的表單大大美化,方便用戶選擇輸入。比如下面案例里對年份使用了,顏色則使用了復選框le。單選可以用和。常見文本輸入可以用和。
from django import forms
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=BIRTH_YEAR_CHOICES))
? ?favorite_colors = forms.MultipleChoiceField(
? ? ? ?required=False,
? ? ? ?widget=forms.CheckboxSelectMultiple,
? ? ? ?choices=COLORS_CHOICES,
? ?)
表單數據初始化
有時我們需要對表單設置一些初始數據,我們可以通過方法設置form表單可以選擇多個文件,如下所示。
form = ContactForm(
? ?initial={
? ? ? ?'name': 'First and Last Name',
? ?},)
其編輯修改類應用場景中,我們還要給表單提供現有對象的數據,而不是渲染一張空表單,這時我們可這么做。該方法僅適用于由模型創建的,而不適用于自定義的表單。
contact = Contact.objects.get(id=1)
form = ?ContactForm(instance = contact)
對于自定義的表單,可以設置。
default_data = {'name': 'John', 'email': 'someone@hotmail.com', }
form = ContactForm(default_data)
的使用
有的時候用戶需要在1個頁面上使用多個表單,比如一次性提交添加多本書的信息,這時我們可以使用。這是一個表單的集合。
創建一個我們可以這么做:
from django import forms
class BookForm(forms.Form):
? ?name = forms.CharField(max_length=100)
? ?title = forms.CharField()
? ?pub_date = forms.DateField(required=False)
# forms.py - build a formset of books
from django.forms import formset_factory
from .forms import BookForm
# extra: 額外的空表單數量
# max_num: 包含表單數量(不含空表單)
BookFormSet = formset_factory(BookForm, extra=2, max_num=1)
在視圖文件views.py里,我們可以像使用form一樣使用。
# views.py - formsets example.
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():
? ? ? ? ? ?# do something with the formset.cleaned_data
? ? ? ? ? ?pass
? ?else:
? ? ? ?formset = BookFormSet()
? ?return render(request, 'manage_books.html', {'formset': formset})
模板里可以這樣使用。