Django 的 model form 组件

Django 的 model form 组件

Model Form 组件的由来

之前介绍过 Django 的 Form 组件(Django的Form表单)使用方法,Form 组件能够帮我们做三件事:

  1. 生成页面可用的HTML标签

  2. 对用户提交的数据进行校验

  3. 保留上次输入内容

我们发现,form 类中的字段和 model 类中的字段及其相似,但 form 表单和 model 类并没有什么关系。对于每一个 model 类,我们都需要为其创建一个对应的 form 类,还要根据该 model 类定义校验。

这种方式增添了很多重复劳动,所以出现了 model form 组件,它可以优雅地生成 form 类,并且在校验方面更简单。

创建 model form

要用到的 model 类有:

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, verbose_name="价格")
    date = models.DateField()
    publish = models.ForeignKey(to="Publish")
    authors = models.ManyToManyField(to="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

直接在视图层中创建 model form

# views.py

# 导入 ModelForm
from django.forms import ModelForm
from django.forms import widgets as wid    # 避免重名


class Book(ModelForm):
    class Meta:
        # 对应的Model类
        model = models.Book
        # 字段,all表示列出所有字段
        fields = "__all__"

        # labels 自定义显示的名字,
        labels = {
            "title": "书名",
            "publish": "出版社",
            "date": "出版日期",
            "authors": "作者",
        }
		
		# error_messages用法:
        error_messages = {
            'title': {'required': "书名不能为空", },
            'date': {'required': "出版日期不能为空", },
        }
		
        widgets = {
            "title": wid.TextInput(attrs={"class": "form-control"}),
            "date": wid.TextInput(attrs={"type": "date"})
        }

展示数据

视图函数中的使用

在视图函数中将该类实例化并传到前端。

def book(request):
    book_list = models.Book.objects.all()
    # book = Book()
    return render(request, 'book.html', locals())

模板中的使用

前端只需要 {{book_list.as_p }} 一下,所有的字段就都出来了,可以用 as_p 显示全部,也可以通过 for 循环这 book_list ,拿到的是一个个 input 框,这种方法支持加 class 样式类。


<table border="1">
    {% 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>
               {% for author in book.authors.all %}
                   {{ author.name }}
               {% endfor %}

           </td>
           <td><a href="/book/edit/{{book.pk}}"><button>编辑</button></a></td>
       </tr>
    {% endfor %}

</table>

在后台给在前端显示的字段加属性。

widgets = {
	"title": wid.TextInput(attrs={"class": "form-control"}),
	"date": wid.TextInput(attrs={"type": "date"})
}

添加数据

视图函数中的使用

使用 model form 类在添加时变的十分简单,通过 request.POST 创建一个 Book 对象,判断其是否通过验证,如果通过验证,只需简单的 book.save() 就能保存到数据库中。

def add_book(request):
    if request.method == "POST":
        book = Book(request.POST)
        if book.is_valid():
            book.save()
            return redirect('/book/')
    book = Book()
    return render(request, 'add.html', locals())

模板中的使用

模板中的使用与上面的相同。

<form action="" method="post" novalidate>
     {% csrf_token %}
{#    一个as_p就能将所有HTML标签自动加上#}
     {{ book.as_p }}

    <input type="submit" value="提交">
</form>

编辑数据

视图函数中的使用

在编辑功能中我们希望编辑页面能显示原来的数据,用 model form 类很容易就能实现。

根据要编辑书籍的 id 值取出相应的书籍对象并加上 instance 字段用该对象创建 Book 实例对象,即可实现。

def edit_book(request, id):
    book_obj = models.Book.objects.filter(pk=id).first()
    if not book_obj:
        return HttpResponse("无该书籍")
    if request.method == "POST":
        book = Book(request.POST, instance=book_obj)
        if book.is_valid():
            book.save()
            return redirect('/book/')
    book = Book(instance=book_obj)
    return render(request, 'edit.html', locals())

模板中的使用

模板中的使用与上面的相同。

<form action="" method="post" novalidate>
     {% csrf_token %}
{#    一个as_p就能将所有HTML标签自动加上#}
     {{ book.as_p }}

    <input type="submit" value="提交">
</form>

GitHub 地址:https://github.com/protea-ban/oldboy/tree/master/9day84

posted @ 2018-11-01 17:14  banshaohuan  阅读(109)  评论(0编辑  收藏  举报