1. 程式人生 > >from和modelform的用法和介紹

from和modelform的用法和介紹

一 form

1. form的作用

  1. 生成HTML程式碼
  2. 幫我們做資料有效性的校驗
  3. 保留上次輸入內容,顯示錯誤提示

2. form元件校驗資料有效性
  1. 內建的校驗規則
  1. require=True 該欄位必填
  2. max_length 該欄位的最大長度
  3. min_length 該欄位的最小長度

 

 2. 自定義校驗規則
  1. 如手機號的格式 利用內建的正則校驗器
  from django.core.validators import RegexValidator
  validators=[RegexValidator(r'^1[356789]\d{9}$', "手機號碼格式不正確")],

 


3. 使用鉤子函式做校驗
 1. 區域性鉤子(hook)
           在form類內部定義一個 clean_欄位名() 方法

 例子

#自定義一個區域性鉤子函式含有alex的關鍵字不能提交
    def clean_title(self):
        value=self.cleaned_data.get("title")  #獲取書名
        if "alex" in value:
            raise ValidationError("ALEX以備和諧")
        
else: return value

2. 全域性鉤子
       在form類內部定義一個 clean() 方法

4. form組合如何給html標籤設定預設值

  1. 每一個欄位設定預設值
  initial="預設值"

例項:關於使用form的例子,使用form之前可以自己寫一個單獨的form類,我這裡一新增book為例:

1 form.py

 from django import forms
  from app01 import models
  from django.core.exceptions import ValidationError #註冊功能
 
from django.core.validators import RegexValidator # 檢驗手機號碼是否正確 # 自己定義一個form類 class BookForm(forms.Form): title=forms.CharField( max_length=12, min_length=2, # 如果想讓網頁顯示中文就加上label label="書名", initial="填寫書名", # 給tttle生成的input標籤加上一個class類 widget=forms.widgets.TextInput(attrs={"class":"form-control"}) ) publisher_date=forms.DateField( label="出版日期", # widget 外掛 widget=forms.widgets.DateInput(attrs={"type":"date","class":"form-control"}) ) phone=forms.CharField( max_length=11, validators=[RegexValidator(r'^1[356789]\d{9}$',"手機號碼格式不正確")], # 限制手機號格式 widget = forms.widgets.TextInput(attrs={"class": "form-control"}) ) # 用modelchoicefield可以實時顯示到頁面上面當資料庫增加的時候 publisher = forms.ModelChoiceField( queryset=models.Publisher.objects.all(), widget=forms.widgets.Select(attrs={"class": "form-control"}), ) authors=forms.ModelMultipleChoiceField( queryset=models.Author.objects.all(), widget=forms.widgets.SelectMultiple(attrs={"class": "form-control"}) ) #自定義一個區域性鉤子函式含有alex的關鍵字不能提交 def clean_title(self): value=self.cleaned_data.get("title") #獲取書名 if "alex" in value: raise ValidationError("ALEX以備和諧") else: return value

2 views.py裡面的配置做了一些改變

首先要匯入你剛才自己定義的BookForm

from app01.forms import BookForm 
def add_book(request):
    form_obj=BookForm()
    if request.method=="POST":
        form_obj=BookForm(request.POST)
        if form_obj.is_valid(): #做資料有效性校驗
            # 因為有多對多的欄位,所以需要額外處理
            authors=form_obj.cleaned_data.pop("authors")
            # 建立新書籍物件
            book_obj=models.Book.objects.create(**form_obj.cleaned_data)
            # 講書籍物件和作者建立關聯
            book_obj.authors.add(*authors)

            return redirect("/book_list/")
    return render(request,"add_book.html",locals())

編輯功能

def edit_book(request,pk):
    book_obj=models.Book.objects.filter(id=pk).first()
    from django.forms import model_to_dict # 匯入這個模組
    book_dict=model_to_dict(book_obj) # 轉換成字典格式
    book_dict["publisher_date"]=book_obj.publisher_date.strftime("%Y-%m-%d") # 時間轉換成字串格式

    form_obj=BookForm(book_dict)
    if request.method=="POST":
        form_obj=BookForm(request.POST) # 接受使用者傳來的資料
        if form_obj.is_valid(): # 判斷資料是否正常
            book_obj.title=form_obj.cleaned_data.get("title")
            book_obj.publisher_id=form_obj.cleaned_data.get("publisher_date")
            book_obj.publisher_id=form_obj.cleaned_data.get("publisher")
            book_obj.save()
            book_obj.authors.set(form_obj.cleaned_data.get("authors"))
            return redirect("/book_list")
    return render(request,"edit_book.html",locals())

3 html裡面也做了一些改變:(一些類的名字也都在forms裡面給自動新增上了)

1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>新增書籍</title>
 6     <link href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.css" rel="stylesheet">
 7 </head>
 8 <body>
 9 <div class="container">
10     <div class="row">
11         <div class="col-md-8 col-md-offset-2">
12             <h1>新增書籍</h1>
13             <form action="" method="post" novalidate autocomplete="off">
14                 {% for field in form_obj %}
15                     <div class="form-group">
16                         <label for="{{ field.id_for_label }}">{{ field.label }}</label>
17                         {{ field }}
18                         <p>{{ field.errors.0 }}</p>
19 
20                     </div>
21                 {% endfor %}
22                  <input type="submit" class="btn btn-success">
23             </form>
24 
25         </div>
26 
27     </div>
28 
29 </div>
30 
31 </body>
32 </html>
View Code

二 model form

1. 必須繼承forms.ModelForm

2. class Meta:
  model = "一對一關聯的model類名"
  fields = "__all__"
3. 例項化
  1. BookModelForm(instance=book_obj)
  2. BookModelForm(request.POST, instance=book_obj)
4. form_obj.save()

要想使用modelform,也必須先寫個modelform

modelform例子:

1 modelform.py

from django import forms
from django.core.validators import RegexValidator
from django.core.exceptions import ValidationError
from app01 import models

class BookModelForm(forms.ModelForm):
    class Meta:
        model=models.Book
        fields="__all__" #model類裡面所有的欄位都展示
        # fields="title" # 指定展示某些欄位
        # exclude=["title"] # 除了知道欄位,其他欄位都展示
        # labels可以設定在網頁上面顯示的文字
        labels={
            "title":"書名",
            "publisher_date":"建立日期",
            "phone":"手機號",
            "publisher":"出版社",
            "authors":"作者",

        }
        widgets={ # 設定每個欄位的外掛資訊
            "title": forms.widgets.TextInput(attrs={"class": "form-control"}),
            "phone": forms.widgets.TextInput(attrs={"class": "form-control"}),
            "publisher": forms.widgets.Select(attrs={"class": "form-control"}),
            "authors": forms.widgets.SelectMultiple(attrs={"class": "form-control"}),

        }
        error_messages = {  # 設定每個欄位的報錯提示資訊
            "publisher": {
                "required": "必須給我選一個出版社!"
            },
            "authors":{
                "required":"必須選擇一個作者"

            }
        }
View Code

 views.py裡面設定:

要先匯入你剛才寫的那個

from app01.forms import BookModelForm

新增

def add_book(request):
    form_obj = BookModelForm()
    if request.method == "POST":
        form_obj = BookModelForm(request.POST)
        if form_obj.is_valid():
            form_obj.save()
            return redirect("/book_list/")
    return render(request, "add_book.html", locals())

編輯

def edit_book(request, pk):
    book_obj = models.Book.objects.filter(id=pk).first()
    print("我是book_obj", book_obj)
    # instance例項
    form_obj = BookModelForm(instance=book_obj)  # 例項化的form_obj
    if request.method == "POST":
        # 獲取使用者提交過來的資料,用request.POST傳過來的資料去更新book_obj這本書
        form_obj = BookModelForm(request.POST, instance=book_obj)
        if form_obj.is_valid():
            form_obj.save()
            return redirect("/book_list/")
    return render(request, "edit_book.html", locals())

3 html編輯和新增內容都是一樣的

1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>新增書籍</title>
 6     <link href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.css" rel="stylesheet">
 7 </head>
 8 <body>
 9 
10 <div class="container">
11     <div class="row">
12         <div class="col-md-8 col-md-offset-2">
13             <h1>新增書籍</h1>
14 
15             <form action="" method="post" novalidate autocomplete="off">
16                 {% csrf_token %}
17 
18                 {% for field in form_obj %}
19                     <div class="form-group">
20                         <label for="{{ field.id_for_label }}">{{ field.label }}</label>
21                         {{ field }}
22                         <p>{{ field.errors.0 }}</p>
23                     </div>
24                 {% endfor %}
25                 <input type="submit" class="btn btn-success">
26             </form>
27         </div>
28     </div>
29 </div>
30 
31 </body>
32 </html>