前言:
為什么要用form去驗(yàn)證呢?
我們提交的是form表單,在看前端源碼時(shí)如果檢查到POST URL及我們提交的字段,如果沒(méi)有驗(yàn)證我們是否可以直接POST數(shù)據(jù)到URL,后臺(tái)并沒(méi)有進(jìn)行校驗(yàn),直接處理,那樣會(huì)不會(huì)對(duì)我們系統(tǒng)產(chǎn)生影響?答案是肯定的,F(xiàn)ORM的作用就是起到一定的數(shù)據(jù)保護(hù)作用加一層校驗(yàn)將不合法數(shù)據(jù)丟棄
1.針對(duì)上一章 django form表單驗(yàn)證 補(bǔ)充
form表單補(bǔ)充,select框
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | #!/usr/bin/env python # -*- coding: utf-8 -*- import re from django import forms from django.core.exceptions import ValidationError def phone_validate(value): phone_re = re. compile (r '^(13[0-9]|15[012356789]|17[0678]|18[0-9]|14[57])[0-9]{8}$' ) if not phone_re.match(value): raise ValidationError( '手機(jī)號(hào)碼格式錯(cuò)誤' ) class TestForm(forms.Form): user_type_choice = ( ( 0 , u '普通用戶' ), ( 1 , u '管理員' ), ) user_type = forms.IntegerField(widget = forms.widgets.Select(choices = user_type_choice, attrs = { 'class' : "form-control" })) |
注:
widget 生成前端展示 .SELECT選擇下拉框,attrs屬性class前端顯示類
二. 通過(guò)model form來(lái)自定義表單
1. 字段類型
生成的表單類中將具有和指定的模型字段對(duì)應(yīng)的表單字段,順序?yàn)?tt>fields 屬性中指定的順序。
Form field | |
---|---|
AutoField | Not represented in the form |
BigIntegerField | IntegerField with min_value set to -9223372036854775808 and max_value set to 9223372036854775807. |
BooleanField | BooleanField |
CharField | CharField with max_length set to the model field’s max_length |
CommaSeparatedIntegerField | CharField |
DateField | DateField |
DateTimeField | DateTimeField |
DecimalField | DecimalField |
EmailField | EmailField |
FileField | FileField |
FilePathField | FilePathField |
FloatField | FloatField |
ForeignKey | ModelChoiceField (see below) |
ImageField | ImageField |
IntegerField | IntegerField |
IPAddressField | IPAddressField |
GenericIPAddressField | GenericIPAddressField |
ManyToManyField | ModelMultipleChoiceField (see below) |
NullBooleanField | NullBooleanField |
PositiveIntegerField | IntegerField |
PositiveSmallIntegerField | IntegerField |
SlugField | SlugField |
SmallIntegerField | IntegerField |
TextField | CharField with widget=forms.Textarea |
TimeField | TimeField |
URLField | URLField |
完整示例:
1. 數(shù)據(jù)模型
創(chuàng)建:
model.py
settings DATABASES配制
生成:
python manage.py makemigrations
python manage.py migrate
只是舉例詳見(jiàn)參考
https://docs.djangoproject.com/en/1.11/topics/db/models/
http://www.cnblogs.com/jl-bai/p/5798860.html
注:
報(bào)錯(cuò):
django.core.exceptions.ImproperlyConfigured: Error loading MySQLdb module: No module named 'MySQLdb'
原因:無(wú)mysql客戶端
解決方案:
在project 的root_dir 下__init__文件中寫入
import pymysql pymysql.install_as_MySQLdb()
(一)數(shù)據(jù)前端展示
2. 后臺(tái)VIEWS
from django.views.generic.base import TemplateViewfrom app01.forms import BookModelFormclass Index(TemplateView): template_name = "index.html" def get(self, request, *args, **kwargs): form = BookModelForm() return self.render_to_response(context={"form": form})
3. ModelForm
#!/usr/bin/env python# -*- coding: utf-8 -*-from django import formsfrom app01.models import Bookclass BookModelForm(forms.ModelForm): class Meta: model = Book fields = ['name', 'authors', 'publish_date'] widgets = { 'name': forms.TextInput(attrs={'class': "form-control"}), 'authors': forms.Select(attrs={'class': "form-control"}), 'publish_date': forms.DateInput(attrs={'class': "form-control", 'placeholder': "YYYY-MM-DD"}) }
4. 前端展示
{% load staticfiles %} {% load i18n admin_static %}<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>django model form</title> <link href="{% static 'css/bootstrap.css' %}" rel="stylesheet"/></head><body><div style="width: 980px;margin: 0 auto"> <div class="col-lg-6"> <form action="{% url 'index' %}" method="POST">{% csrf_token %} {{ form }} <input class="btn btn-primary m-r-5 m-b-5" type="submit" value="提 交"> </form> </div></div></body></html>
訪問(wèn):
(二) 模型表單的驗(yàn)證
1. 驗(yàn)證模型
與普通的表單驗(yàn)證類型類似,模型表單的驗(yàn)證在調(diào)用is_valid() 或訪問(wèn)errors 屬性時(shí)隱式調(diào)用,或者通過(guò)full_clean() 顯式調(diào)用,盡管在實(shí)際應(yīng)用中你將很少使用后一種方法。
模型的驗(yàn)證(Model.full_clean())在表單驗(yàn)證這一步的內(nèi)部觸發(fā),緊跟在表單的clean() 方法調(diào)用之后。
警告
Clean 過(guò)程會(huì)以各種方式修改傳遞給模型表單構(gòu)造函數(shù)的模型實(shí)例。例如,模型的日期字段將轉(zhuǎn)換成日期對(duì)象。驗(yàn)證失敗可能導(dǎo)致模型實(shí)例處于不一致的狀態(tài),所以不建議重新使用它。
1.1 重寫clean() 方法
可以重寫模型表單的clean() 來(lái)提供額外的驗(yàn)證,方法和普通的表單一樣。
模型表單實(shí)例包含一個(gè)instance 屬性,表示與它綁定的模型實(shí)例。
警告
ModelForm.clean() 方法設(shè)置一個(gè)標(biāo)識(shí)符, 使得模型驗(yàn)證 這一步驗(yàn)證標(biāo)記為unique、 unique_together 或unique_for_date|month|year 的模型字段的唯一性。
如果你需要覆蓋clean() 方法并維持這個(gè)驗(yàn)證行為,你必須調(diào)用父類的clean() 方法。
與django form表單驗(yàn)證 中定義clean方法相同
模型error_messages 的注意事項(xiàng)
表單字段級(jí)別或表單級(jí)別的錯(cuò)誤信息永遠(yuǎn)比模型字段級(jí)別的錯(cuò)誤信息優(yōu)先。
模型字段的錯(cuò)誤信息只用于模型驗(yàn)證步驟引發(fā)ValidationError 的時(shí)候,且不會(huì)有對(duì)應(yīng)的表單級(jí)別的錯(cuò)誤信息。
2. save()方法
每個(gè)ModelForm還具有一個(gè)save() 方法。這個(gè)方法根據(jù)表單綁定的數(shù)據(jù)創(chuàng)建并保存數(shù)據(jù)庫(kù)對(duì)象。模型表單的子類可以用關(guān)鍵字參數(shù)instance 接收一個(gè)已經(jīng)存在的模型實(shí)例;如果提供,save() 將更新這個(gè)實(shí)例。如果沒(méi)有提供,save() 將創(chuàng)建模型的一個(gè)新實(shí)例:
save()
如果表單沒(méi)有驗(yàn)證,save() 調(diào)用將通過(guò)檢查form.errors 來(lái)進(jìn)行驗(yàn)證。如果表單中的數(shù)據(jù)不合法,將引發(fā)ValueError —— 例如,如果form.errors 為True。
3. 先擇用到的字段
class BookModelForm(forms.ModelForm): class Meta: model = Book fields = ['name', 'authors', 'publish_date'] widgets = { 'name': forms.TextInput(attrs={'class': "form-control"}), 'authors': forms.Select(attrs={'class': "form-control"}), 'publish_date': forms.DateInput(attrs={'class': "form-control", 'placeholder': "YYYY-MM-DD"}) }
在ModelForm中我們通常使用fields 屬性顯式設(shè)置所有將要在表單中編輯的字段,如果不這樣做,當(dāng)表單不小心允許用戶設(shè)置某些特定的字段,特別是有的字段添加到模型中的時(shí)候,將很容易導(dǎo)致安全問(wèn)題。
另外一種方式是自動(dòng)包含所有的字段,或者排除某些字段。這種基本方式的安全性要差很多,而且已經(jīng)導(dǎo)致大型的網(wǎng)站受到嚴(yán)重的利用。
3.1 設(shè)置fields 屬性為特殊的值'__all__' 以表示需要使用模型的所有字段。例如:
class BookModelForm(forms.ModelForm): class Meta: model = Book fields = '__all__'
3.2 設(shè)置ModelForm 內(nèi)聯(lián)的Meta 類的exclude 屬性為一個(gè)要從表單中排除的字段的列表
class BookModelForm(forms.ModelForm): class Meta: model = Book exclude = ()
fields = '__all__' 達(dá)到效果相同選取所有字段 如果 exclude=['name'],那么排除“name"字段其他字段都會(huì)顯示
3.3 多個(gè)外鍵對(duì)同一個(gè)模型
如果一個(gè)模型在同一個(gè)模型中包含多個(gè)外鍵,則需要使用fk_name手動(dòng)解決歧義。例如,考慮以下模型:
class Friendship(models.Model): from_friend = models.ForeignKey(Friend, related_name='from_friends') to_friend = models.ForeignKey(Friend, related_name='friends') length_in_months = models.IntegerField()
要解決此問(wèn)題,您可以使用fk_name到inlineformset_factory()
FriendshipFormSet = inlineformset_factory(Friend, Friendship, fk_name='from_friend', ... fields=('to_friend', 'length_in_months'))
具體參考:
https://docs.djangoproject.com/en/1.11/topics/forms/modelforms/
http://www.cnblogs.com/jl-bai/p/6711345.html