Django——form組件和ModelForm

1、原生form實現書城增刪改查

一、構建模型並完成數據庫遷移

(1)構建書城模型

from django.db import models # Create your models here. # 建立一個圖書管理系統的模型


class Book(models.Model): title = models.CharField(max_length=32) price = models.DecimalField(max_digits=8, decimal_places=2)   # 8個有效數,兩個浮點
    date = models.DateField() publish = models.ForeignKey("Publish", on_delete=models.CASCADE) authors = models.ManyToManyField("Author") def __str__(self): return self.title class Publish(models.Model): name = models.CharField(max_length=32) def __str__(self): return self.name class Author(models.Model): name = models.CharField(max_length=32) def __str__(self): return self.name
models.py

(2)數據庫遷移

$ python3 manage.py makemigrations
$ python3 manage.py migrate

二、運用admin模塊錄入數據

from django.contrib import admin # Register your models here.
from .models import * admin.site.register(Book) admin.site.register(Author) admin.site.register(Publish)
admin.py

  建立超級用戶:php

manage.py@formsDemo2 >  createsuperuser
Username (leave blank to use 'hqs'):  yuan
Email address:  
Warning: Password input may be echoed.
Password:  yuan1234
Warning: Password input may be echoed.
Password (again):  yuan1234
Superuser created successfully.

三、錄入做者、出版社、書籍信息

  

四、代碼

from django.contrib import admin from django.urls import path from django.conf.urls import url from app01 import views urlpatterns = [ path('admin/', admin.site.urls), url(r'^books/$', views.book), url(r'^books/add', views.addbook), url(r'^books/edit/(\d+)', views.editbook), ]
urls.py
from django.shortcuts import render, redirect # Create your views here.
from .models import *


def book(request): book_list = Book.objects.all() return render(request, 'books.html', locals()) def addbook(request): if request.method == "POST": title = request.POST.get("title") price = request.POST.get("price") date = request.POST.get("date") publish_id = request.POST.get("publish_id") # getlist(): Return the list of values for the key.
        author_pk_list = request.POST.getlist("author_pk_list") # 取到用戶輸入的書籍信息後添加到數據庫Book表中
        book_obj = Book.objects.create(title=title, price=price, date=date, publish_id=publish_id) # 直接綁定主鍵,將做者對象添加到這本書的做者集合中
        book_obj.authors.add(*author_pk_list) return redirect("/books/") publish_list = Publish.objects.all() author_list = Author.objects.all() return render(request, "addbook.html", locals()) def editbook(request, edit_book_id): if request.method == "POST": title = request.POST.get("title") price = request.POST.get("price") date = request.POST.get("date") publish_id = request.POST.get("publish_id") # getlist(): Return the list of values for the key.
        author_pk_list = request.POST.getlist("author_pk_list") # 取到用戶輸入的書籍信息後更新到數據庫Book表中
        book_obj = Book.objects.filter(edit_book_id).update(title=title, price=price, date=date, publish_id=publish_id) # 直接綁定主鍵,將做者對象更新到這本書的做者集合中
        book_obj.authors.set(*author_pk_list)   # set()先清空,再設置


        return redirect("/books/") # 去數據庫中取出數據
    edit_book = Book.objects.filter(pk=edit_book_id).first() publish_list = Publish.objects.all() author_list = Author.objects.all() return render(request, "editbook.html", locals())
views.py
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<a href="/books/add"><button>添加書籍</button></a>
<hr>
<table border="1"><!--border給表格加框--> {% for book in book_list %} <tr>
            <td>{{ book.title }}</td>
            <td>{{ book.price }}</td>
            <td>{{ book.date|date:"Y-m-d" }}</td>
            <td>{{ book.publish.name }}</td>
            <td>{{ book.authors.all }}</td>
            <td><a href="/books/edit/{{ book.pk }}">編輯</a></td>
        </tr> {% endfor %} </table>
</body>
</html>
books.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h3>添加頁面</h3>
<form action="" method="post"> {% csrf_token %} <p>書籍名稱 <input type="text" name="title"></p>
    <p>價格 <input type="text" name="price"></p>
    <p>日期 <input type="date" name="date"></p>
    <p>出版社 <select name="publish_id" id=""> {% for publish in publish_list %} <option value="{{ publish.pk }}">{{ publish.name }}</option> {% endfor %} </select>
    </p>
    <p>做者 {# multiple屬性設置多選 #}
        <select name="author_pk_list" id="" multiple> {% for author in author_list %} <option value="{{ author.pk }}">{{ author.name }}</option> {% endfor %} </select>
    </p>
    <input type="submit">
</form>
</body>
</html>
addbock.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h3>編輯頁面</h3>
<form action="" method="post"> {% csrf_token %} <p>書籍名稱 <input type="text" name="title" value="{{ edit_book.title }}"></p>
    <p>價格 <input type="text" name="price" value="{{ edit_book.price }}"></p>
    <p>日期 <input type="date" name="date" value="{{ edit_book.date|date:'Y-m-d' }}"></p>
    <p>出版社 <select name="publish_id" id=""> {% for publish in publish_list %} {% if edit_book.publish == publish %} {# 數據庫有記錄的顯示爲selected狀 #}
                    <option selected value="{{ publish.pk }}">{{ publish.name }}</option> {% else %} {# 數據庫中沒有記錄的顯示爲普通狀態 #}
                    <option value="{{ publish.pk }}">{{ publish.name }}</option> {% endif %} {% endfor %} </select>
    </p>
    <p>做者 {# multiple屬性設置多選 #}
        <select name="author_pk_list" id="" multiple> {% for author in author_list %} {# 判斷是不是數據庫中數的做者 #}
                {% if author in edit_book.authors.all %} <option selected value="{{ author.pk }}">{{ author.name }}</option> {% else %} <option value="{{ author.pk }}">{{ author.name }}</option> {% endif %} {% endfor %} </select>
    </p>
    <input type="submit">
</form>
</body>
</html>
View Code

五、顯示效果

  

  

六、構建表單總結

  假設你想在你的網站上建立一個簡單的表單,以得到用戶的名字。你須要相似這樣的模板:html

<form action="/your-name/" method="post">
    <label for="your_name">Your name: </label>
    <input id="your_name" type="text" name="your_name">
    <input type="submit" value="OK">
</form>

  這是一個很是簡單的表單。實際應用中,一個表單可能包含幾十上百個字段,其中大部分須要預填充,並且咱們預料到用戶未來回編輯-提交幾回才能完成操做。前端

  咱們可能須要在表單提交以前,在瀏覽器端做一些驗證。咱們可能想使用很是複雜的字段,以容許用戶作相似從日曆中挑選日期這樣的事情,等等。python

  這個時候,讓Django 來爲咱們完成大部分工做是很容易的。git

2、利用forms組件實現

參考:正則表達式

  https://www.cnblogs.com/yuanchenqi/articles/7614921.html 
  https://www.cnblogs.com/wupeiqi/articles/6144178.html
數據庫

一、視圖中引入forms組件設計Form類

(1)定義一個Form 類,只帶有三個普通字段

from django import forms
from django.forms import widgets

class BookForm(forms.Form):
    # 三個普通字段類型
    title = forms.CharField(max_length=32, label="書籍名稱")
    price = forms.DecimalField(max_digits=8, decimal_places=2, label="價格")
    date = forms.DateField(label="日期",
                           widget=widgets.TextInput(attrs={"type": "date"})    # <input type="date" >
    )

注意:django

  1)字段容許的最大長度經過max_length 定義。它完成兩件事情。首先,它在HTML 的<input> 上放置一個maxlength="100"(這樣瀏覽器將在第一時間阻止用戶輸入多於這個數目的字符)。它還意味着當Django 收到瀏覽器發送過來的表單時,它將驗證數據的長度。小程序

  2)Form 的實例具備一個is_valid() 方法,它爲全部的字段運行驗證的程序。當調用這個方法時,若是全部的字段都包含合法的數據,它將:瀏覽器

  • 返回True
  • 將表單的數據放到cleaned_data屬性中。

  3)每一個表單字段都有一個對應的Widget 類,它對應一個HTML 表單Widget,例如<input type="text">

  在大部分狀況下,字段都具備一個合理的默認Widget。例如,默認狀況下,CharField 具備一個TextInput Widget,它在HTML 中生成一個<input type="text">

(2)在Form類中添加特殊字段

from django import forms
from django.forms import widgets


class BookForm(forms.Form):
    # 三個普通字段類型
    title = forms.CharField(max_length=32, label="書籍名稱")
    price = forms.DecimalField(max_digits=8, decimal_places=2, label="價格")
    date = forms.DateField(label="日期",
                           widget=widgets.TextInput(attrs={"type": "date"})    # <input type="date" >
    )
    # 特殊字段類型
    # ChoiceField渲染select標籤
    # gender = forms.ChoiceField(choices=((1, "男"), (2, "女"), (3, "其餘")))

    # 出版社:渲染select標籤
    # publish = forms.ChoiceField(choices=Publish.objects.all().values_list("pk", "name"))
    publish = forms.ModelChoiceField(queryset=Publish.objects.all())

    # 做者
    authors = forms.ModelMultipleChoiceField(queryset=Author.objects.all())

注意:

  1)ChoiceField(field)渲染select標籤,通常在數據與數據庫不要緊的時候使用

publish = forms.ChoiceField(choices=Publish.objects.all().values_list("pk", "name"))

  2)ModelChoiceField(ChoiceField)繼承ChoiceFiled,用如下方式改寫,由於傳遞的參數是queryset所以不須要使用values_list了。

  queryset傳遞的值是主鍵值和對象,若是類中有設置__str__則取其中的值。

publish = forms.ModelChoiceField(queryset=Publish.objects.all())

  3)ModelMultipleChoiceField(ModelChoiceField)繼承ModelChoiceField,與數據庫打交道且是多選時使用。

authors = forms.ModelMultipleChoiceField(queryset=Author.objects.all())

二、視圖

addbook視圖函數:

def addbook(request):
    if request.method == "POST":
        form = BookForm(request.POST)  # 實例化BookForm

        if form.is_valid():   # 若是是合格的數據
            print("clean_data", form.cleaned_data)
            # 輸出:clean_data {'title': '水滸傳', 'price': Decimal('88'), 'date': datetime.date(2014, 4, 20),
            #                   'publish': <Publish: 蘋果出版社>, 'authors': <QuerySet [<Author: egon>]>}

            title = form.cleaned_data.get("title")
            price = form.cleaned_data.get("price")
            date = form.cleaned_data.get("date")
            publish = form.cleaned_data.get("publish")
            authors = form.cleaned_data.get("authors")

            # 取到用戶輸入的書籍信息後添加到數據庫Book表中
            book_obj = Book.objects.create(title=title, price=price, date=date, publish=publish)

            # 將做者對象添加到這本書的做者集合中
            book_obj.authors.add(*authors)

            return redirect("/books/")

    form = BookForm()   # 實例化BookForm

    publish_list = Publish.objects.all()
    author_list = Author.objects.all()

    return render(request, "addbook.html", locals())

三、模板

(1)form類只含有三個普通字段

addbook.html:

<form action="" method="post" novalidate>
    {% csrf_token %}
    <div>
        {{ form.title.label }}
        {{ form.title }}
    </div>
    <div>
        {{ form.price.label }}
        {{ form.price }}
    </div>
    <div>
        {{ form.date.label }}
        {{ form.date }}
    </div>
    <input type="submit">
</form>

  根據{{ form }},全部的表單字段和它們的屬性將經過Django 的模板語言拆分紅HTML 標記 。

  form標籤novalidate屬性:novalidate 屬性規定當提交表單時不對其進行驗證。若是使用該屬性,則表單不會驗證表單的輸入。

  Django 原生支持一個簡單易用的跨站請求僞造的防禦。當提交一個啓用CSRF 防禦的POST 表單時,你必須使用上面例子中的csrf_token 模板標籤。

  完整的表單,第一次渲染時,效果以下:

<form action="" method="post">
    <input type="hidden" name="csrfmiddlewaretoken" value="lSKaxqL7dD9gmNfhksqykU1ERnlhMYx5RrjiJ8E34lWibOcOGVw41aBzc4kcyati">
    <div>
        <p>Title</p>
        <input type="text" name="title" maxlength="32" required="" id="id_title">
    </div>
    <div>
        <p>Price</p>
        <input type="number" name="price" step="0.01" required="" id="id_price">
    </div>
    <div>
        <p>Date</p>
        <input type="date" name="date" required="" id="id_date">
    </div>
    <input type="submit">
</form>

(2)form類包含特殊字段

   經過{{ form.publish }}和{{ form.authors }}獲取出版社和做者信息。經過Django 的模板語言拆分紅HTML 標記。

初始addbook.html寫法:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h3>添加頁面</h3>
<form action="" method="post" novalidate>
    {% csrf_token %}
    <div>
        {{ form.title.label }}
        {{ form.title }}
    </div>
    <div>
        {{ form.price.label }}
        {{ form.price }}
    </div>
    <div>
        {{ form.date.label }}
        {{ form.date }}
    </div>
    <div>
        {{ form.publish.label }}
        {{ form.publish }}
    </div>
    <div>
        {{ form.authors.label }}
        {{ form.authors }}
    </div>
    <input type="submit">
</form>
</body>
</html>

  addbook.html精簡後寫法:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h3>添加頁面</h3>
<form action="" method="post" novalidate>
    {% csrf_token %}
    {% for field in form %}
        <div>
            {{ field.label }}
            {{ field }}
        </div>
    {% endfor %}
    <input type="submit">
</form>
</body>
</html>

  顯示效果:

  

3、引入ModelForm組件進一步改寫

一、引入ModelForm組件改寫BookForm類

  views.py:

from django.forms import ModelForm

class BookForm(ModelForm):
    class Meta:
        model = Book
        fields = "__all__"   # 對全部字段轉換

  在視圖函數中,定義一個類,好比就叫BookForm,這個類要繼承ModelForm,在這個類中再寫一個原類Meta(規定寫法,並注意首字母是大寫的)。

  注意對全部字段轉換是寫字符串,其餘時候是寫列表

fields = ["title", "price"]

  改寫addbook視圖函數:

def addbook(request):
    form = BookForm()   # 實例化BookForm
    return render(request, "addbook.html", locals())

  頁面訪問解析效果:

  

二、修改添加和編輯視圖,處理post請求

def addbook(request):
    if request.method == "POST":
        form = BookForm(request.POST)  # 實例化BookForm
        if form.is_valid():   # 若是是合格的數據
            form.save()
            return redirect("/books/")

    form = BookForm()   # 實例化BookForm
    return render(request, "addbook.html", locals())


def editbook(request, edit_book_id):
    edit_book = Book.objects.filter(pk=edit_book_id).first()
    if request.method=="POST":
        # 默認是create操做,若是是想update,須要添加一個instance參數把要編輯的對象傳遞過來
        form = BookForm(request.POST, instance=edit_book)   # 傳遞須要更新的對象
        if form.is_valid():
            form.save()
            return redirect("/books/")

    # 建立form對象,傳入參數就能夠顯示以前客戶寫入的值,ModelForm具有instance參數
    form = BookForm(instance=edit_book)   # 接收實例對象
    return render(request, "editbook.html", locals())

 注意:

(1)ModelForm的instance參數

  能夠接收實例對象,僅對edit視圖作以下改寫,就能夠拿到客戶以前提交的信息。

def editbook(request, edit_book_id):
    # 去數據庫中取出數據
    edit_book = Book.objects.filter(pk=edit_book_id).first()
    # 建立form對象,傳入參數就能夠顯示以前客戶寫入的值,ModelForm具有instance參數
    form = BookForm(instance=edit_book)   # 接收實例對象
    return render(request, "editbook.html", locals())

  顯示效果:

  

(2)處理POST請求,添加和編輯操做代碼

if request.method == "POST":
    form = BookForm(request.POST)  # 實例化BookForm
    if form.is_valid():   # 若是是合格的數據
        form.save()
        return redirect("/books/")

  區別就在於一點:實例化form類的時候,是否傳遞instance參數。

  若是不用ModelForm,編輯的時候要顯示以前的數據,還得挨個取一遍值,若是ModelForm,只須要加一個instance=obj(obj是要修改的數據庫的一條數據的對象)就能夠獲得一樣的效果
  保存的時候要注意,必定要注意有這個對象(instance=obj),不然不知道更新哪個數據。默認狀況下是執行create操做,若是是想update,須要添加一個instance參數把要編輯的對象傳遞過來。

(3)model和form之間耦合

  ModelForm用起來是很是方便的,好比增長修改之類的操做。可是也帶來額外很差的地方,model和form之間耦合了。

  若是不耦合的話,form.save()方法也沒法直接提交保存。 可是耦合的話使用場景一般侷限用於小程序,寫大程序就最好不用了。

(4)添加記錄的方法——save()

  保存數據的時候不須要挨個取數據了,直接save一下,就完成了取數據生成記錄的操做。 

form.model.objects.create(request.POST)

  編輯功能的editbook視圖函數,不須要作任何變更,save一下就執行了更新操做

form = BookForm(request.POST, instance=edit_book)   # 傳遞須要更新的對象
if form.is_valid():
    form.save()   # edit_book.update(request.POST)

三、模板改寫

  因爲編輯和添加模板中的form標籤內的內容徹底同樣,將其拷貝出來放在新建立的form.html模板中:

<form action="" method="post" novalidate>
    {% csrf_token %}
    {% for field in form %}
        <div>
            {{ field.label }}
            {{ field }}
        </div>
    {% endfor %}
    <input type="submit">
</form>

  在addbook.html和editbook.html中改寫以下:

<body>
<h3>編輯頁面</h3>
{% include 'form.html' %}
</body>

注意:

(1){% include %} 標籤容許在(模板中)包含其它的模板的內容。 標籤的參數是所要包含的模板名稱,能夠是一個變量,也能夠是用單/雙引號硬編碼的字符串。

四、修改BookForm類,利用元類屬性設置優化渲染

from django.forms import ModelForm
from django.forms import widgets as wid  # 由於重名,因此起個別名

wid_text = wid.TextInput(attrs={'class':'form-control'})
required_msg = {'required':'不能爲空'}


class BookForm(ModelForm):
    class Meta:
        model = Book
        fields = "__all__"   # 對全部字段轉換
        labels = {
            "title": "書籍名稱",
            "price": "書籍價格",
            "date": "日期",
            "publish": "出版社",
            "authors": "做者"
        }

        # widgets用法,好比把輸入用戶名的input框給爲Textarea
        widgets = {   # 這個是參數widgets
            "title": wid_text,
            "price": wid_text,
            "date": wid.TextInput(attrs={"class": "form-control", 'type': 'date'}),
            "publish": wid.Select(attrs={"class": "form-control"}),
            "authors": wid.SelectMultiple(attrs={"class": "form-control"}),
        }

        # error_messages用法:
        error_messages = {
            'title': {'required': "用戶名不能爲空", },
            'price': {'required': "價格不能爲空", },
            'date': {'required': "日期不能爲空", 'invalid': "日期格式錯誤"},
            'publish': {'required': "出版社不能爲空", },
            'authors': {'required': "做者不能爲空", },
        }

(1)導入widgets模塊用法

  這是由於ModelForm有一個參數是widgets與之重名,因此須要給它一個別名:

from django.forms import widgets as wid  # 由於重名,因此起個別名

  在input標籤添加form-contral樣式,能夠考慮在後臺的widget裏面添加,好比這樣:

from django.forms import widgets as wid #由於重名,因此起個別名
widgets = {
    "name":wid.TextInput(attrs={'class':'form-control'}),
    "age":wid.NumberInput(attrs={'class':'form-control'}),
    "email":wid.EmailInput(attrs={'class':'form-control'})
}

  固然也能夠在js中,找到全部的input框,加上這個樣式,也行。

(2)使用error_messages參數修改錯誤提示

error_messages=None,         錯誤信息 {'required': '不能爲空', 'invalid': '格式錯誤'}
# error_messages用法:
error_messages = {
    'title': {'required': "用戶名不能爲空", },
    'price': {'required': "價格不能爲空", },
    'date': {'required': "日期不能爲空", 'invalid': "日期格式錯誤"},
    'publish': {'required': "出版社不能爲空", },
    'authors': {'required': "做者不能爲空", },
}

五、修改form.html模板和addbook視圖函數,添加錯誤信息顯示

<form action="" method="post" novalidate>
    {% csrf_token %}
    {% for field in form %}
        <div>
            {{ field.label }}
            {{ field }}
            <small>
                <span class="pull-right text-danger has-error">
                    {{ field.errors.0 }}
                </span>
            </small>
        </div>
    {% endfor %}
    <input type="submit">
</form>

  注意在模板中經過{{ field.errors.0 }}取到錯誤提示信息。.0表示只取第一條。視圖函數也須要作修改才能顯示錯誤信息:

def addbook(request):
    form = BookForm()  # 實例化BookForm
    if request.method == "POST":
        form = BookForm(request.POST)  # 實例化BookForm
        if form.is_valid():   # 若是是合格的數據
            form.save()
            return redirect("/books/")
    # form = BookForm()  # 實例化BookForm

    return render(request, "addbook.html", locals())

   須要注意的是,要把form=BookForm()這一步移到最上方,不然校驗失敗返回的form對象就變成沒有值的form對象了,也能夠改寫爲下面更清晰的寫法:

def addbook(request):
    if request.method == "POST":
        form = BookForm(request.POST)  # 實例化BookForm
        if form.is_valid():   # 若是是合格的數據
            form.save()
            return redirect("/books/")
        else:
            # 檢驗失敗,不寫下面的語句,返回的form對象就變成沒有值的form對象了
            return render(request, "addbook.html", locals())

    form = BookForm()  # 實例化BookForm

    return render(request, "addbook.html", locals())

  顯示效果:

  

 

4、前端form表單,後臺forms組件

  前端手寫一個form表單,後臺使用forms組件,進行校驗也是能夠的!!

  注意: <p>名稱 <input type="text" name="title"></p>  和   title = forms.CharField()

views.py:

from django import forms

class BookForms(forms.Form):
    title = forms.CharField()
    price = forms.FloatField()


def addbook(request):
    form = BookForms()
    if request.method == 'POST':
        form = BookForms(request.POST)
        # form = BookForm({'title':'php','price':111,'xxx':'egon'})
        if form.is_valid():
            print('clean_data',form.cleaned_data)
            # clean_data {'title': '水滸傳', 'price': 123.0}
        else:
            print('error',form.errors)

    return render(request,'addbook.html',locals())

addbook.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<h3>添加書籍</h3>

<form action="" method="post" novalidate>
    {% csrf_token %}
    <p>名稱 <input type="text" name="title"></p>
    <p>價格 <input type="text" name="price"></p>
    <p>xxx <input type="text" name="xxx"></p>

    <input type="submit">
</form>

<form action="" method="post" novalidate>
    {% csrf_token %}
    {{ form.as_p }}
    {{ form.as_table }}
    {{ form.as_ul }}
    <input type="submit">
</form>

</body>
</html>

5、modelform詳解

Django之Form組件

Django-組件拾遺

6、form組件補充

一、Django內置字段以下

Field
    required=True,               是否容許爲空
    widget=None,                 HTML插件
    label=None,                  用於生成Label標籤或顯示內容
    initial=None,                初始值
    help_text='',                幫助信息(在標籤旁邊顯示)
    error_messages=None,         錯誤信息 {'required': '不能爲空', 'invalid': '格式錯誤'}
    show_hidden_initial=False,   是否在當前插件後面再加一個隱藏的且具備默認值的插件(可用於檢驗兩次輸入是否一直)
    validators=[],               自定義驗證規則
    localize=False,              是否支持本地化
    disabled=False,              是否能夠編輯
    label_suffix=None            Label內容後綴
 
 
CharField(Field)
    max_length=None,             最大長度
    min_length=None,             最小長度
    strip=True                   是否移除用戶輸入空白
 
IntegerField(Field)
    max_value=None,              最大值
    min_value=None,              最小值
 
FloatField(IntegerField)
    ...
 
DecimalField(IntegerField)
    max_value=None,              最大值
    min_value=None,              最小值
    max_digits=None,             總長度
    decimal_places=None,         小數位長度
 
BaseTemporalField(Field)
    input_formats=None          時間格式化   
 
DateField(BaseTemporalField)    格式:2015-09-01
TimeField(BaseTemporalField)    格式:11:12
DateTimeField(BaseTemporalField)格式:2015-09-01 11:12
 
DurationField(Field)            時間間隔:%d %H:%M:%S.%f
    ...
 
RegexField(CharField)
    regex,                      自定製正則表達式
    max_length=None,            最大長度
    min_length=None,            最小長度
    error_message=None,         忽略,錯誤信息使用 error_messages={'invalid': '...'}
 
EmailField(CharField)      
    ...
 
FileField(Field)
    allow_empty_file=False     是否容許空文件
 
ImageField(FileField)      
    ...
    注:須要PIL模塊,pip3 install Pillow
    以上兩個字典使用時,須要注意兩點:
        - form表單中 enctype="multipart/form-data"
        - view函數中 obj = MyForm(request.POST, request.FILES)
 
URLField(Field)
    ...
 
 
BooleanField(Field)  
    ...
 
NullBooleanField(BooleanField)
    ...
 
ChoiceField(Field)
    ...
    choices=(),                選項,如:choices = ((0,'上海'),(1,'北京'),)
    required=True,             是否必填
    widget=None,               插件,默認select插件
    label=None,                Label內容
    initial=None,              初始值
    help_text='',              幫助提示
 
 
ModelChoiceField(ChoiceField)
    ...                        django.forms.models.ModelChoiceField
    queryset,                  # 查詢數據庫中的數據
    empty_label="---------",   # 默認空顯示內容
    to_field_name=None,        # HTML中value的值對應的字段
    limit_choices_to=None      # ModelForm中對queryset二次篩選
     
ModelMultipleChoiceField(ModelChoiceField)
    ...                        django.forms.models.ModelMultipleChoiceField
 
 
     
TypedChoiceField(ChoiceField)
    coerce = lambda val: val   對選中的值進行一次轉換
    empty_value= ''            空值的默認值
 
MultipleChoiceField(ChoiceField)
    ...
 
TypedMultipleChoiceField(MultipleChoiceField)
    coerce = lambda val: val   對選中的每個值進行一次轉換
    empty_value= ''            空值的默認值
 
ComboField(Field)
    fields=()                  使用多個驗證,以下:即驗證最大長度20,又驗證郵箱格式
                               fields.ComboField(fields=[fields.CharField(max_length=20), fields.EmailField(),])
 
MultiValueField(Field)
    PS: 抽象類,子類中能夠實現聚合多個字典去匹配一個值,要配合MultiWidget使用
 
SplitDateTimeField(MultiValueField)
    input_date_formats=None,   格式列表:['%Y--%m--%d', '%m%d/%Y', '%m/%d/%y']
    input_time_formats=None    格式列表:['%H:%M:%S', '%H:%M:%S.%f', '%H:%M']
 
FilePathField(ChoiceField)     文件選項,目錄下文件顯示在頁面中
    path,                      文件夾路徑
    match=None,                正則匹配
    recursive=False,           遞歸下面的文件夾
    allow_files=True,          容許文件
    allow_folders=False,       容許文件夾
    required=True,
    widget=None,
    label=None,
    initial=None,
    help_text=''
 
GenericIPAddressField
    protocol='both',           both,ipv4,ipv6支持的IP格式
    unpack_ipv4=False          解析ipv4地址,若是是::ffff:192.0.2.1時候,可解析爲192.0.2.1, PS:protocol必須爲both才能啓用
 
SlugField(CharField)           數字,字母,下劃線,減號(連字符)
    ...
 
UUIDField(CharField)           uuid類型
    ...

二、Django內置插件

TextInput(Input)
NumberInput(TextInput)
EmailInput(TextInput)
URLInput(TextInput)
PasswordInput(TextInput)
HiddenInput(TextInput)
Textarea(Widget)
DateInput(DateTimeBaseInput)
DateTimeInput(DateTimeBaseInput)
TimeInput(DateTimeBaseInput)
CheckboxInput
Select
NullBooleanSelect
SelectMultiple
RadioSelect
CheckboxSelectMultiple
FileInput
ClearableFileInput
MultipleHiddenInput
SplitDateTimeWidget
SplitHiddenDateTimeWidget
SelectDateWidget

三、經常使用選擇插件

# 單radio,值爲字符串
# user = fields.CharField(
#     initial=2,
#     widget=widgets.RadioSelect(choices=((1,'上海'),(2,'北京'),))
# )
 
# 單radio,值爲字符串
# user = fields.ChoiceField(
#     choices=((1, '上海'), (2, '北京'),),
#     initial=2,
#     widget=widgets.RadioSelect
# )
 
# 單select,值爲字符串
# user = fields.CharField(
#     initial=2,
#     widget=widgets.Select(choices=((1,'上海'),(2,'北京'),))
# )
 
# 單select,值爲字符串
# user = fields.ChoiceField(
#     choices=((1, '上海'), (2, '北京'),),
#     initial=2,
#     widget=widgets.Select
# )
 
# 多選select,值爲列表
# user = fields.MultipleChoiceField(
#     choices=((1,'上海'),(2,'北京'),),
#     initial=[1,],
#     widget=widgets.SelectMultiple
# )
 
 
# 單checkbox
# user = fields.CharField(
#     widget=widgets.CheckboxInput()
# )
 
 
# 多選checkbox,值爲列表
# user = fields.MultipleChoiceField(
#     initial=[2, ],
#     choices=((1, '上海'), (2, '北京'),),
#     widget=widgets.CheckboxSelectMultiple
# )

6、django請求流程

  Django 和其餘 Web 框架的 HTTP 處理的流程大體相同,Django 處理一個 Request 的過程是首先經過中間件,而後再經過默認的 URL 方式進行的。咱們能夠在 Middleware 這個地方把全部 Request 攔截住,用咱們本身的方式完成處理之後直接返回 Response。

 

 

 

  

一、http協議

請求協議格式:請求首行,請求頭,請求體!
響應協議格式:響應首行,響應頭,響應體!

二、HTTP請求處理流程

1. 加載配置

  Django 的配置都在 「Project/settings.py」 中定義,能夠是 Django 的配置,也能夠是自定義的配置,而且都經過 django.conf.settings 訪問,很是方便。

2. 啓動

  最核心動做的是經過 django.core.management.commands.runfcgi 的 Command 來啓動,它運行 django.core.servers.fastcgi 中的 runfastcgi,runfastcgi 使用了 flup 的 WSGIServer 來啓動 fastcgi 。而 WSGIServer 中攜帶了 django.core.handlers.wsgi 的 WSGIHandler 類的一個實例,經過 WSGIHandler 來處理由 Web 服務器(好比 Apache,Lighttpd 等)傳過來的請求,此時纔是真正進入 Django 的世界。

3. 處理 Request

  當有 HTTP 請求來時,WSGIHandler 就開始工做了,它從 BaseHandler 繼承而來。WSGIHandler 爲每一個請求建立一個 WSGIRequest 實例,而 WSGIRequest 是從 http.HttpRequest 繼承而來。接下來就開始建立 Response 了。

4. 建立 Response

  BaseHandler 的 get_response 方法就是根據 request 建立 response,而具體生成 response 的動做就是執行 urls.py 中對應的view函數了,這也是 Django 能夠處理「友好 URL 」的關鍵步驟,每一個這樣的函數都要返回一個 Response 實例。此時通常的作法是經過 loader 加載 template 並生成頁面內容,其中重要的就是經過 ORM 技術從數據庫中取出數據,並渲染到 Template 中,從而生成具體的頁面了。

5. 處理 Response

  Django 返回 Response 給 flup,flup 就取出 Response 的內容返回給 Web 服務器,由後者返回給瀏覽器。

  總之,Django 在 fastcgi 中主要作了兩件事:處理 Request 和建立 Response,而它們對應的核心就是「 urls 分析」、「模板技術」和「 ORM 技術」。

三、流程圖說明

  如圖所示,一個 HTTP 請求,首先被轉化成一個 HttpRequest 對象,而後該對象被傳遞給 Request 中間件處理,若是該中間件返回了Response,則直接傳遞給 Response 中間件作收尾處理。不然的話 Request 中間件將訪問 URL 配置,肯定哪一個 view 來處理,在肯定了哪一個 view 要執行,可是尚未執行該 view 的時候,系統會把 request 傳遞給 view 中間件處理器進行處理,若是該中間件返回了 Response,那麼該 Response 直接被傳遞給 Response 中間件進行後續處理,不然將執行肯定的 view 函數處理並返回 Response,在這個過程當中若是引起了異常並拋出,會被 Exception 中間件處理器進行處理。

相關文章
相關標籤/搜索