前言:

  為什么要用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
AutoFieldNot represented in the form
BigIntegerFieldIntegerField with min_value set to -9223372036854775808 and max_value set to 9223372036854775807.
BooleanFieldBooleanField
CharFieldCharField with max_length set to the model field’s max_length
CommaSeparatedIntegerFieldCharField
DateFieldDateField
DateTimeFieldDateTimeField
DecimalFieldDecimalField
EmailFieldEmailField
FileFieldFileField
FilePathFieldFilePathField
FloatFieldFloatField
ForeignKeyModelChoiceField (see below)
ImageFieldImageField
IntegerFieldIntegerField
IPAddressFieldIPAddressField
GenericIPAddressFieldGenericIPAddressField
ManyToManyFieldModelMultipleChoiceField (see below)
NullBooleanFieldNullBooleanField
PositiveIntegerFieldIntegerField
PositiveSmallIntegerFieldIntegerField
SlugFieldSlugField
SmallIntegerFieldIntegerField
TextFieldCharField with widget=forms.Textarea
TimeFieldTimeField
URLFieldURLField

 

完整示例:

1. 數(shù)據(jù)模型

創(chuàng)建:

seo優(yōu)化培訓(xùn),網(wǎng)絡(luò)推廣培訓(xùn),網(wǎng)絡(luò)營(yíng)銷培訓(xùn),SEM培訓(xùn),網(wǎng)絡(luò)優(yōu)化,在線營(yíng)銷培訓(xùn) model.py

seo優(yōu)化培訓(xùn),網(wǎng)絡(luò)推廣培訓(xùn),網(wǎng)絡(luò)營(yíng)銷培訓(xùn),SEM培訓(xùn),網(wǎng)絡(luò)優(yōu)化,在線營(yíng)銷培訓(xùn) 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

seo優(yōu)化培訓(xùn),網(wǎng)絡(luò)推廣培訓(xùn),網(wǎng)絡(luò)營(yíng)銷培訓(xùn),SEM培訓(xùn),網(wǎng)絡(luò)優(yōu)化,在線營(yíng)銷培訓(xùn)

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})

seo優(yōu)化培訓(xùn),網(wǎng)絡(luò)推廣培訓(xùn),網(wǎng)絡(luò)營(yíng)銷培訓(xùn),SEM培訓(xùn),網(wǎng)絡(luò)優(yōu)化,在線營(yíng)銷培訓(xùn)

3. ModelForm

seo優(yōu)化培訓(xùn),網(wǎng)絡(luò)推廣培訓(xùn),網(wǎng)絡(luò)營(yíng)銷培訓(xùn),SEM培訓(xùn),網(wǎng)絡(luò)優(yōu)化,在線營(yíng)銷培訓(xùn)

#!/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"})
        }

seo優(yōu)化培訓(xùn),網(wǎng)絡(luò)推廣培訓(xùn),網(wǎng)絡(luò)營(yíng)銷培訓(xùn),SEM培訓(xùn),網(wǎng)絡(luò)優(yōu)化,在線營(yíng)銷培訓(xùn)

 

4. 前端展示

seo優(yōu)化培訓(xùn),網(wǎng)絡(luò)推廣培訓(xùn),網(wǎng)絡(luò)營(yíng)銷培訓(xùn),SEM培訓(xùn),網(wǎng)絡(luò)優(yōu)化,在線營(yíng)銷培訓(xùn)

{% 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>

seo優(yōu)化培訓(xùn),網(wǎng)絡(luò)推廣培訓(xùn),網(wǎng)絡(luò)營(yíng)銷培訓(xùn),SEM培訓(xùn),網(wǎng)絡(luò)優(yōu)化,在線營(yíng)銷培訓(xùn)

訪問(wèn):

seo優(yōu)化培訓(xùn),網(wǎng)絡(luò)推廣培訓(xùn),網(wǎng)絡(luò)營(yíng)銷培訓(xùn),SEM培訓(xùn),網(wǎng)絡(luò)優(yōu)化,在線營(yíng)銷培訓(xù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í)例:

seo優(yōu)化培訓(xùn),網(wǎng)絡(luò)推廣培訓(xùn),網(wǎng)絡(luò)營(yíng)銷培訓(xùn),SEM培訓(xùn),網(wǎng)絡(luò)優(yōu)化,在線營(yíng)銷培訓(xùn) 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. 先擇用到的字段

  

seo優(yōu)化培訓(xùn),網(wǎng)絡(luò)推廣培訓(xùn),網(wǎng)絡(luò)營(yíng)銷培訓(xùn),SEM培訓(xùn),網(wǎng)絡(luò)優(yōu)化,在線營(yíng)銷培訓(xùn)

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"})
        }

seo優(yōu)化培訓(xùn),網(wǎng)絡(luò)推廣培訓(xùn),網(wǎng)絡(luò)營(yíng)銷培訓(xùn),SEM培訓(xùn),網(wǎng)絡(luò)優(yōu)化,在線營(yíng)銷培訓(xùn)

在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_nameinlineformset_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