ModelForm的基本用法:


一、ModelForm的基本用法示例:

from django import forms
from app01 import models


class BookModelForm(forms.ModelForm):
    #必須是這個類名
    class Meta:
        # 告訴Django這個form類和那個model類對應
        model = models.Book
        # 告訴Django這個form類里面有哪些字段
        fields = "__all__"
        widgets = {
            "publish_date": forms.widgets.DateInput(
                # 給日期字段添加日期類型
                attrs={"type": "date"}
            )
        }
        labels = {
            "title": "書名",
            "price": "價格",
            "publish_date": '出版日期',
            "publisher": "出版社名稱",
            "authors": "作者"
        }
        error_messages = {
            "title": {
                "required": "書名不能為空"
            }
        }

    # 通過修改類的初始化方法達到批量添加共同屬性的目的
    def __init__(self, *args, **kwargs):
        super(BookModelForm, self).__init__(*args, **kwargs)
        # for field_name in self.base_fields:
        for field in iter(self.fields):
            self.fields[field].widget.attrs.update({
                'class': 'form-control'
            })

ModelForm所有屬性:

class Meta:
            model,                           # 對應Model的
            fields=None,                     # 字段
            exclude=None,                    # 排除字段
            labels=None,                     # 提示信息
            help_texts=None,                 # 幫助提示信息
            widgets=None,                    # 自定義插件
            error_messages=None,             # 自定義錯誤信息(整體錯誤信息from django.core.exceptions import NON_FIELD_ERRORS)
            field_classes=None               # 自定義字段類 (也可以自定義字段)
            localized_fields=('birth_date',) # 本地化,如:根據不同時區顯示數據

ModelForm用於驗證用戶數據:is_valid()

        model_form_obj = XXOOModelForm()   //實例化對象
        model_form_obj.is_valid()   // 校驗數據
        model_form_obj.errors.as_json()  //錯誤
        model_form_obj.clean()   //同Form組件中的屬性
        model_form_obj.cleaned_data  // 同Form組件中的屬性

ModelForm用於創建數據:save()

def add_book(request):
    if request.method == "POST":
        #直接傳request.POST,進行ModelForm的實例化傳參
        form_obj = forms.BookModelForm(request.POST)
        if form_obj.is_valid(): # 校驗數據
            form_obj.save()   #直接就可以保存數據到數據庫,包括多對多,多對一,一對一的關系
            return redirect("/book_list/")
    #ModelForm實例化對象
    form_obj = forms.BookModelForm()
    return render(request, "v2/add_book.html", locals())

ModelForm用於初始化:ModelForm(instance=model_obj)

def edit_book(request, pk):
    book_obj = models.Book.objects.filter(id=pk).first()
    #form_obj通過instance設置初始化的值,例如,圖書管理系統中的編輯書籍功能,
    #點擊編輯后跳轉到編輯書籍頁面,跳轉后需要用要編輯的書籍信息填充頁面對應信息。
    #不同於Form組件的是,ModelForm直接就可以傳實例化的對象,而不需要將對象轉化成字典的形式傳。
    form_obj = forms.BookModelForm(instance=book_obj)  
    return render(request, "v2/edit_book.html", locals())

ModelForm用於更新 :ModelForm(request.POST, instance=book_obj)

def edit_book(request, pk):
    book_obj = models.Book.objects.filter(id=pk).first()
    if request.method == "POST":
        #修改數據時,直接可以將用戶數據包request.POST傳進去,
        #再傳一個要修改的對象的示例,ModelForm就可以自動完成修改數據了。
        form_obj = forms.BookModelForm(request.POST, instance=book_obj)
        if form_obj.is_valid():  // 數據校驗
            form_obj.save()   // 直接保存
        return redirect("/book_list/")
    #form_obj通過instance設置初始化的值,例如,圖書管理系統中的編輯書籍功能,
    #點擊編輯后跳轉到編輯書籍頁面,跳轉后需要用要編輯的書籍信息填充頁面對應信息。
    #不同於Form組件的是,ModelForm直接就可以傳實例化的對象,而不需要將對象轉化成字典的形式傳。
    form_obj = forms.BookModelForm(instance=book_obj)  
    return render(request, "v2/edit_book.html", locals())

二、ModelForm和Form組件的應用場景:

  • ModelForm ---- 中小型應用程序。因為ModelForm是依賴於models的。
  • Form ------- 大型應用程序

三、通過ModelForm實現的書籍、作者、出版社的管理代碼示例:

  1. 表結構:
from django.db import models

class Publisher(models.Model):
    name = models.CharField(max_length=12)
    address = models.TextField()

    def __str__(self):
        return self.name

class Author(models.Model):
    name = models.CharField(max_length=12)
    gender = models.SmallIntegerField(
        choices=((0, '女'), (1, '男'), (2, '保密'))
    )
    age = models.IntegerField()

    def __str__(self):
        return self.name

class Book(models.Model):
    title = models.CharField(max_length=32)
    price = models.DecimalField(max_digits=5, decimal_places=2)  # 0~999.99
    publish_date = models.DateField()
    publisher = models.ForeignKey(to="Publisher", on_delete=models.CASCADE)
    authors = models.ManyToManyField(to="Author")

    def __str__(self):
        return self.title
  1. ModelForm類:
from django import forms
from app01 import models

class BookModelForm(forms.ModelForm):
    class Meta:
        # 告訴Django這個form類和那個model類對應
        model = models.Book
        # 告訴Django這個form類里面有哪些字段
        fields = "__all__"
        widgets = {
            "publish_date": forms.widgets.DateInput(
                # 給日期字段添加日期類型
                attrs={"type": "date"}
            )
        }
        labels = {
            "title": "書名",
            "price": "價格",
            "publish_date": '出版日期',
            "publisher": "出版社名稱",
            "authors": "作者"
        }
        error_messages = {
            "title": {
                "required": "書名不能為空"
            }
        }

    # 通過修改類的初始化方法達到批量添加共同屬性的目的
    def __init__(self, *args, **kwargs):
        super(BookModelForm, self).__init__(*args, **kwargs)
        # for field_name in self.base_fields:
        for field_name in iter(self.fields):
            field = self.base_fields[field_name]
            field.widget.attrs.update({
                "class": "form-control",
            })
  1. views 視圖函數:
from django.shortcuts import render,redirect
from app01 import modelform
from app01 import models


def book_list(request):
    book_list = models.Book.objects.all()
    return render(request, 'book_list.html', {'book_list': book_list})


def add_book(request):
    if request.method == "POST":
        # modelform 直接可以將從前端拿到的數據組request.POST
        #當參數傳給實例化的Modelform
        form_obj = modelform.BookModelForm(request.POST)
        # 調用is_valid()方法校驗數據
        if form_obj.is_valid():
            # 直接保存到數據庫中
            form_obj.save()
            return redirect("/book_list/")
    modelform_obj = modelform.BookModelForm()
    return render(request, 'add_book.html', {"modelform_obj": modelform_obj})


def edit_book(request,pk):
    book_obj = models.Book.objects.filter(id=pk).first()
    if request.method == "POST":
        #修改數據時,直接可以將用戶數據包request.POST傳進去,
        #再傳一個要修改的對象的示例,ModelForm就可以自動完成修改數據了。
        form_obj = modelform.BookModelForm(request.POST, instance=book_obj)
        if form_obj.is_valid():
            form_obj.save()
        return redirect("/book_list/")
    # form_obj通過initial設置初始化的值,例如,圖書管理系統中的編輯書籍功能,
    # 點擊編輯后跳轉到編輯書籍頁面,跳轉后需要用要編輯的書籍信息填充頁面對應信息。
    # 不同於Form組件的是,ModelForm直接就可以傳實例化的對象,而不需要將對象轉化成字典的形式傳。
    form_obj = modelform.BookModelForm(instance=book_obj)
                               #locals()是將本地數據鍵值對的簡寫形式
    return render(request, "edit_book.html", locals())
  1. book_list.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>書籍列表</title>
    <link href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.css" rel="stylesheet">
</head>
<body>
<div class="container">
    <div class="row">
        <div class="col-md-8 col-offset-2">
            <a href="/add_book/">添加書籍</a>
            <table border="1">
                <thead>
                <tr>
                    <th>序號</th>
                    <th>id</th>
                    <th>書名</th>
                    <th>價格</th>
                    <th>出版日期</th>
                    <th>出版社</th>
                    <th>作者</th>
                    <th>操作</th>
                </tr>
                </thead>
                {% for book in book_list %}
                    <tr>
                        <td>{{ forloop.counter }}</td>
                        <td>{{ book.id }}</td>
                        <td>{{ book.title }}</td>
                        <td>{{ book.price }}</td>
                        <td>{{ book.publish_date }}</td>
                        <td>{{ book.publisher }}</td>
                        <td>{{ book.authors.all }}</td>
                        <td>
                            <a href="/edit_book/{{ book.id }}/">編輯</a>
                        </td>
                    </tr>
                {% endfor %}
            </table>
        </div>
    </div>
</div>
</body>
</html>
  1. add_book.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>添加書籍</title>
    <link href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.css" rel="stylesheet">
</head>
<body>
<div class="container">
    <div class="row">
        <div class="col-md-6 col-offset-3">
            <form role="form" action="" method="post">
                {% csrf_token %}
                {% for modelform in modelform_obj %}
                    <p>
                        {{ modelform.label }}
                        {{ modelform }}
                    </p>
                {% endfor %}
            <button type="submit" class="btn btn-success">提交</button>
            </form>
        </div>
    </div>
</div>
</body>
</html>
  1. edit_book.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>添加書籍</title>
    <link href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.css" rel="stylesheet">
</head>
<body>
<div class="container">
    <div class="row">
        <div class="col-md-6 col-offset-3">
            <form role="form" action="" method="post">
                {% csrf_token %}
                {% for filed in form_obj %}
                    <p>
                        {{ filed.label }}
                        {{ filed }}
                    </p>
                {% endfor %}
                <button type="submit" class="btn btn-success">提交</button>
            </form>
        </div>
    </div>
</div>
</body>
</html>

四、通過對Form組件和ModelForm的對比

  • ModelForm增加了Form組件和對應數據庫之間的聯系,進而簡化了Form類的代碼
  • ModelForm繼承了Form組件中的所有方法的同時,簡化了前端獲取數據和對應數據庫之間的數據對接,不需要在對數據的內容做過多的操作。

五、ModelForm中的騷操作(同Form組件)

  • 批量添加樣式:
    通過重寫ModelForm類的init方法來實現。
    # 通過修改類的初始化方法達到批量添加共同屬性的目的
    def __init__(self, *args, **kwargs):
        super(BookModelForm, self).__init__(*args, **kwargs)
        # for field_name in self.base_fields:
        for field in iter(self.fields):
            self.fields[field].widget.attrs.update({
                'class': 'form-control'
            })


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM