• Django之modelform组件


    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 in iter(self.fields):
                self.fields[field].widget.attrs.update({
                    'class': 'form-control'
                })
    

    2. 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',) # 本地化,如:根据不同时区显示数据
    

    3. 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组件中的属性
    

    4. 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())
    

    5. ModelForm用于初始化:ModelForm(instance=model_obj)

    def edit_book(request, pk):
        book_obj = models.Book.objects.filter(id=pk).first()
        #form_obj通过initial设置初始化的值,例如,图书管理系统中的编辑书籍功能,
        #点击编辑后跳转到编辑书籍页面,跳转后需要用要编辑的书籍信息填充页面对应信息。
        #不同于Form组件的是,ModelForm直接就可以传实例化的对象,而不需要将对象转化成字典的形式传。
        form_obj = forms.BookModelForm(instance=book_obj)  
        return render(request, "v2/edit_book.html", locals())
    

    6. 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通过initial设置初始化的值,例如,图书管理系统中的编辑书籍功能,
        #点击编辑后跳转到编辑书籍页面,跳转后需要用要编辑的书籍信息填充页面对应信息。
        #不同于Form组件的是,ModelForm直接就可以传实例化的对象,而不需要将对象转化成字典的形式传。
        form_obj = forms.BookModelForm(instance=book_obj)  
        return render(request, "v2/edit_book.html", locals())
    

    7. ModelForm和Form组件的应用场景:

    • ModelForm ---- 中小型应用程序。因为ModelForm是依赖于models的。
    • Form ------- 大型应用程序

    8. 通过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">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <link href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.css" rel="stylesheet">
        <title>查看书籍</title>
    </head>
    <body>
    <div class="container">
        <div class="row">
            <div class="col-md-8 col-md-offset-2">
                <div class="alert alert-success text-center" role="alert">
                    <h1 class="text-center">图书管理系统</h1>
                </div>
                <div class="panel panel-default panel-primary">
                    <div class="panel-heading ">查看书籍</div>
                    <div class="panel-body">
                        <table class=" table table-striped">
                            <thead>
                            <tr>
                                <td>编号</td>
                                <td>书名</td>
                                <td>出版时间</td>
                                <td>价格</td>
                                <td>出版社</td>
                                <td>作者</td>
                                <td>操作</td>
                            </tr>
                            </thead>
                            {% for book in book_obj %}
                                <tbody>
                                <tr>
                                    <td>{{ forloop.counter }}</td>
                                    <td>{{ book.title }}</td>
                                    <td>{{ book.publishDate|date:"Y-m-d" }}</td>
                                    <td>{{ book.price}}</td>
                                    <td>{{ book.publishes.name }}</td>
                                    <td>{{ book.author_name }}</td>
                                    <td>
                                        <a href="{% url 'edit' book.pk %}" class="btn btn-danger">编辑</a>
                                        <a href="{% url 'delete' book.pk %}" class="btn btn-warning">删除</a>
                                    </td>
                                </tr>
                                </tbody>
                            {% endfor %}
                        </table>
                        <a href="{% url 'add' %}" class="btn btn-success pull-right">添加书籍</a>
                    </div>
                </div>
            </div>
        </div>
    </div>
    </body>
    </html>
    
    1. add_book.html
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <link href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.css" rel="stylesheet">
        <title>Title</title>
    </head>
    <body>
    <div class="container">
        <div class="row">
            <div class="col-md-8 col-md-offset-2">
                <form action="" method="post">
                    {% csrf_token %}
                    {% for field in new_book %}
                        <div class="form-group">
                            {{ field.label }}
                            {{ field }}
                        </div>
                    {% endfor %}
                    <button type="submit" class="btn btn-success pull-right">保存</button>
                </form>
            </div>
        </div>
    </div>
    </body>
    </html>
    
    1. edit_book.html
    {% extends "add_book.html" %}
    

    9. 通过对Form组件和ModelForm的对比

    • ModelForm增加了Form组件和对应数据库之间的联系,进而简化了Form类的代码
    • ModelForm继承了Form组件中的所有方法的同时,简化了前端获取数据和对应数据库之间的数据对接,不需要在对数据的内容做过多的操作。

    10. 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'
                })
    
    希望你眼眸有星辰,心中有山海,从此以梦为马,不负韶华
  • 相关阅读:
    TypeScript 2.0 正式发布
    亚太物联网市场前景巨大 2020年预计达到793亿美元
    亚太物联网市场前景巨大 2020年预计达到793亿美元
    亚太物联网市场前景巨大 2020年预计达到793亿美元
    亚太物联网市场前景巨大 2020年预计达到793亿美元
    QTP VBScript RegExp对象的运用
    QTP VBScript RegExp对象的运用
    QTP VBScript RegExp对象的运用
    base64 编码和解码
    nginx 4层负载多个端口
  • 原文地址:https://www.cnblogs.com/daviddd/p/12051115.html
Copyright © 2020-2023  润新知