django Modelform 使用

前言:css

  爲何要用form去驗證呢?html

  咱們提交的是form表單,在看前端源碼時若是檢查到POST URL及咱們提交的字段,若是沒有驗證咱們是否能夠直接POST數據到URL,後臺並無進行校驗,直接處理,那樣會不會對咱們系統產生影響?答案是確定的,FORM的做用就是起到必定的數據保護做用加一層校驗將不合法數據丟棄前端

1.針對上一章 django form表單驗證 補充

form表單補充,select框python

#!/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('手機號碼格式錯誤')

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

 注:mysql

  widget 生成前端展現 .SELECT選擇下拉框,attrs屬性class前端顯示類web

二. 經過model form來自定義表單

1. 字段類型

 生成的表單類中將具備和指定的模型字段對應的表單字段,順序爲fields 屬性中指定的順序。sql

 

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. 數據模型django

建立:bootstrap

 1 from django.db import models
 2 
 3 
 4 # Create your models here.
 5 
 6 
 7 class Publisher(models.Model):
 8     name = models.CharField(max_length=30, unique=True)
 9     address = models.CharField(max_length=50)
10     city = models.CharField(max_length=60)
11     state_province = models.CharField(max_length=60)
12     country = models.CharField(max_length=60)
13     website = models.URLField()
14 
15     def __str__(self):
16         return self.name
17 
18 
19 class Author(models.Model):
20     first_name = models.CharField(max_length=32)
21     last_name = models.CharField(max_length=32)
22     email = models.EmailField()
23 
24     def __str__(self):
25         name = self.first_name + self.last_name
26         return name
27 
28 
29 class Book(models.Model):
30     name = models.CharField(max_length=128)
31     authors = models.ManyToManyField(Author)
32     publisher = models.ForeignKey(Publisher)
33     publish_date = models.DateField()
34 
35     def __str__(self):
36         return self.authors
model.py
 1 DATABASES = {
 2     'default': {
 3         'ENGINE': 'django.db.backends.mysql',
 4         'NAME': os.environ.get("MYSQL_NAME", 'modelform'),
 5         'USER': os.environ.get("MYSQL_USER", 'root'),
 6         'PASSWORD': os.environ.get("MYSQL_PASSWD", 'password'),
 7         'HOST': os.environ.get("MYSQL_HOST", '192.168.1.102'),
 8         'PORT': os.environ.get("MYSQL_PORT", 3306),
 9     }
10 }
settings DATABASES配製

生成:

  python manage.py makemigrations

  python manage.py migrate

只是舉例詳見參考

https://docs.djangoproject.com/en/1.11/topics/db/models/

http://www.cnblogs.com/jl-bai/p/5798860.html

注:

報錯:

  django.core.exceptions.ImproperlyConfigured: Error loading MySQLdb module: No module named 'MySQLdb'

緣由:無mysql客戶端

解決方案:

  在project 的root_dir 下__init__文件中寫入

import pymysql
pymysql.install_as_MySQLdb()

(一)數據前端展現 

2. 後臺VIEWS

from django.views.generic.base import TemplateView
from app01.forms import BookModelForm


class 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 forms
from app01.models import Book


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

 

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>

訪問:

 (二) 模型表單的驗證

1. 驗證模型

與普通的表單驗證類型相似,模型表單的驗證在調用is_valid() 或訪問errors 屬性時隱式調用,或者經過full_clean() 顯式調用,儘管在實際應用中你將不多使用後一種方法。

模型的驗證(Model.full_clean())在表單驗證這一步的內部觸發,緊跟在表單的clean() 方法調用以後。

警告

  Clean 過程會以各類方式修改傳遞給模型表單構造函數的模型實例。例如,模型的日期字段將轉換成日期對象。驗證失敗可能致使模型實例處於不一致的狀態,因此不建議從新使用它。

1.1 重寫clean() 方法

能夠重寫模型表單的clean() 來提供額外的驗證,方法和普通的表單同樣。

模型表單實例包含一個instance 屬性,表示與它綁定的模型實例。

警告

ModelForm.clean() 方法設置一個標識符, 使得模型驗證 這一步驗證標記爲unique、 unique_together 或unique_for_date|month|year 的模型字段的惟一性。

若是你須要覆蓋clean() 方法並維持這個驗證行爲,你必須調用父類的clean() 方法。

django form表單驗證 中定義clean方法相同

模型error_messages 的注意事項

表單字段級別或表單級別的錯誤信息永遠比模型字段級別的錯誤信息優先。

模型字段的錯誤信息只用於模型驗證步驟引起ValidationError 的時候,且不會有對應的表單級別的錯誤信息。

2. save()方法

每一個ModelForm還具備一個save() 方法。這個方法根據表單綁定的數據建立並保存數據庫對象。模型表單的子類能夠用關鍵字參數instance 接收一個已經存在的模型實例;若是提供,save() 將更新這個實例。若是沒有提供,save() 將建立模型的一個新實例:

 1 class Index(TemplateView):
 2     template_name = "index.html"
 3 
 4     def get(self, request, *args, **kwargs):
 5         form = BookModelForm()
 6         return self.render_to_response(context={"form": form})
 7 
 8     def post(self,request):
 9         form = BookModelForm()
10         if form.is_valid():
11             form.save()
12             return redirect("home")
13         return self.render_to_response(context={"form": form})
save()

若是表單沒有驗證,save() 調用將經過檢查form.errors 來進行驗證。若是表單中的數據不合法,將引起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 屬性顯式設置全部將要在表單中編輯的字段,若是不這樣作,當表單不當心容許用戶設置某些特定的字段,特別是有的字段添加到模型中的時候,將很容易致使安全問題。

另一種方式是自動包含全部的字段,或者排除某些字段。這種基本方式的安全性要差不少,並且已經致使大型的網站受到嚴重的利用。

3.1 設置fields 屬性爲特殊的值'__all__' 以表示須要使用模型的全部字段。例如:
class BookModelForm(forms.ModelForm):
    class Meta:
        model = Book
        fields = '__all__'
3.2 設置ModelForm 內聯的Meta 類的exclude 屬性爲一個要從表單中排除的字段的列表
class BookModelForm(forms.ModelForm):
    class Meta:
        model = Book
        exclude = ()
exclude = () 與 fields = '__all__' 達到效果相同選取全部字段
若是 exclude=['name'],那麼排除「name"字段其餘字段都會顯示
3.3 多個外鍵對同一個模型
若是一個模型在同一個模型中包含多個外鍵,則須要使用fk_name手動解決歧義。例如,考慮如下模型:
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()

要解決此問題,您可使用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/

相關文章
相關標籤/搜索