一、创建ModelForm
- from django.forms import ModelForm
- from appxx import models
- from django.forms import widgets as wdt # 因为重名,所以起个别名
- #定义一个类,比如BookForm,这个类要继承ModelForm,在这个类中再写一个原类Meta(规定写法,注意首字母是大写的)
- #在这个原类中,有以下属性(部分):
- class BookForm(ModelForm):
- class Meta:
- model = models.Book # 对应的Model中的类
- fields = "__all__" # 字段,如果是__all__,就表示列出所有的字段,或者使用列表列出想要的字段
- exclude = None # 排除的字段
- # error_messages用法
- error_messages = {
- "title": {"required": "书名不能为空"},
- "price": {"required": "售价不能为空"},
- }
- # widgets用法,比如把输入用户名的input框给为Textarea
- widgets = {
- "name": wdt.Textarea(attrs={"class": "c1"}) # 还可以自定义属性
- }
- #labels,自定义在前端显示的名字
- labels= {
- "title": "书名",
- "price": "售价",
- }
然后在 url 对应的视图函数中实例化这个类,把这个对象传给前端:
- def add_book(request):
- form = forms.BookForm()
- return render(request, "add_book.html", {"form": form})
然后在前端像Form组件那样渲染页面
二、添加数据
保存数据的时候,不用挨个取数据了,只需要 save 一下即可。
- from django.shortcuts import render,redirect
- from appxx import models
- from appxx import forms
-
-
- def add_book(request):
- if request.method == "POST":
- form = forms.BookForm(request.POST)
- if form.is_valid():
- form.save()
- return redirect("/book/")
- form = forms.BookForm()
- return render(request, "add_book.html", {"form": form})
三、编辑数据
如果不使用 ModelForm,编辑的时候得显示之前的数据,还得挨个取一遍值;如果使用 ModelForm,只需要加一个instance=obj(obj是要修改的数据库的一条数据的对象)就可以得到同样的效果。
保存的时候要注意,一定要注意有这个对象(instance=obj),否则不知道更新哪一个数据。
- from django.shortcuts import render,redirect
- from appxx import models
- from appxx import forms
-
-
- def edit_book(request, edit_book_id):
- edit_book= models.Book.objects.filter(id=edit_book_id).first()
- if request.method == "POST":
- form = forms.BookForm(request.POST, instance=edit_book)
- if form.is_valid():
- form.save()
- return redirect("/book/")
- form = forms.BookForm(instance=edit_book)
- return render(request, "edit_book.html", {"form": form})
总结: 从上边可以看到 ModelForm 用起来是非常方便的,比如增加修改之类的操作。但是也带来额外不好的地方,model和form之间耦合了。如果不耦合的话,form.save()方法也无法直接提交保存。 但是耦合的话使用场景通常局限用于小程序,写大程序就最好不用了。
四、完整示例代码
项目结构

urls.py
- from django.conf.urls import url
- from django.contrib import admin
- from appxx import views
-
-
- urlpatterns = [
- url(r'^admin/', admin.site.urls),
- url(r"^book/$", views.book),
- url(r"^book/add/", views.add_book),
- url(r"^book/edit/(\d+)/", views.edit_book),
- ]
views.py
- from django.shortcuts import render,redirect
- from appxx import models
- from appxx import forms
-
-
- def book(request):
- book_list = models.Book.objects.all()
- return render(request, "book.html", {"book_list": book_list})
-
-
- def add_book(request):
- if request.method == "POST":
- form = forms.BookForm(request.POST)
- if form.is_valid():
- form.save()
- return redirect("/book/")
- form = forms.BookForm()
- return render(request, "add_book.html", {"form": form})
-
-
- def edit_book(request, edit_book_id):
- edit_book= models.Book.objects.filter(id=edit_book_id).first()
- if request.method == "POST":
- form = forms.BookForm(request.POST, instance=edit_book)
- if form.is_valid():
- form.save()
- return redirect("/book/")
- form = forms.BookForm(instance=edit_book)
- return render(request, "edit_book.html", {"form": form})
models.py
- from django.db import models
-
-
- class Book(models.Model):
- id = models.AutoField(primary_key=True)
- title = models.CharField(max_length=32)
- price = models.DecimalField(max_digits=5, decimal_places=2)
- publish_date = models.DateField()
- publisher = models.ForeignKey(to="Publisher")
- authors = models.ManyToManyField(to="Author")
-
- def __str__(self):
- return self.title
-
-
- class Publisher(models.Model):
- id = models.AutoField(primary_key=True)
- name = models.CharField(max_length=32)
-
- def __str__(self):
- return self.name
-
-
- class Author(models.Model):
- id = models.AutoField(primary_key=True)
- name = models.CharField(max_length=32)
-
- def __str__(self):
- return self.name
forms.py
- from django.forms import ModelForm
- from appxx import models
- from django.forms import widgets as wdt
-
-
- class BookForm(ModelForm):
- class Meta:
- model = models.Book
- fields = "__all__"
- labels = {
- "title": "书名",
- "price": "售价",
- "publish_date": "出版日期",
- "publisher": "出版社",
- "authors": "作者"
- }
- widgets = {
- "title": wdt.TextInput(attrs={"class": "form-control"}),
- "price": wdt.TextInput(attrs={"class": "form-control"}),
- "publish_date": wdt.TextInput(attrs={"class": "form-control", "type": "date"}),
- "publisher": wdt.Select(attrs={"class": "form-control"}),
- "authors": wdt.SelectMultiple(attrs={"class": "form-control"}),
-
- }
- error_messages = {
- "title": {"required": "书名不能为空"},
- "price": {"required": "售价不能为空"},
- "publish_date": {"required": "出版日期不能为空"},
- "publisher": {"required": "出版社不能为空"},
- "authors": {"required": "作者不能为空"},
- }
book.html
- <!DOCTYPE html>
- <html lang="zh-cn">
- <head>
- <meta charset="UTF-8">
- <title>展示书籍</title>
- <link rel="stylesheet" href="/static/bootstrap/css/bootstrap.min.css" rel="external nofollow" rel="external nofollow" >
- </head>
- <body>
- <div class="container">
- <div class="row">
- <div class="col-md-6 col-md-offset-3">
- <span><a class="btn btn-primary" href="/book/add/" rel="external nofollow" >添加</a></span>
- <table class="table table-striped table-bordered">
- <thead>
- <tr>
- <th>序号</th>
- <th>书名</th>
- <th>售价</th>
- <th>出版日期</th>
- <th>出版社</th>
- <th>作者</th>
- <th>操作</th>
- </tr>
- </thead>
- <tbody>
- {% for book in book_list %}
- <tr>
- <td>{{ forloop.counter }}</td>
- <td>{{ book.title }}</td>
- <td>{{ book.price }}</td>
- <td>{{ book.publish_date }}</td>
- <td>{{ book.publisher.name }}</td>
- <td>
- {% for author in book.authors.all %}
- {{ author.name }}
- {% endfor %}
- </td>
- <td>
- <span><a class="btn btn-warning" href="/book/edit/{{ book.pk }}/" rel="external nofollow" >编辑</a></span>
- <span><a class="btn btn-danger" href="">删除</a></span>
- </td>
- </tr>
- {% endfor %}
- </tbody>
- </table>
- </div>
- </div>
- </div>
- </body>
- </html>
add_book.html和edit_book.html(两个页面代码一样)
- <!DOCTYPE html>
- <html lang="zh-cn">
- <head>
- <meta charset="UTF-8">
- <title>添加书籍</title>
- <link rel="stylesheet" href="/static/bootstrap/css/bootstrap.min.css" rel="external nofollow" rel="external nofollow" >
- <style>
- .panel-title {
- font-weight: bolder;
- }
-
- .panel {
- margin-top: 30px;
- }
- </style>
- </head>
- <body>
- <div class="container">
- <div class="row">
- {# panel开始 #}
- <div class="panel panel-danger col-sm-6 col-md-6 col-sm-offset-3 col-md-offset-3">
- <div class="panel-heading">
- <h3 class="panel-title">添加书籍</h3>
- </div>
- {# panel-body开始 #}
- <div class="panel-body">
- {# form开始 #}
- <form class="form-horizontal" action="" method="post" novalidate>
- {% csrf_token %}
- <div class="form-group">
- <label class="col-md-2 control-label"
- for="{{ form.title.id_for_label }}">{{ form.title.label }}</label>
- <div class="col-md-10">
- {{ form.title }}
- </div>
- </div>
- <div class="form-group">
- <label class="col-md-2 control-label"
- for="{{ form.price.id_for_label }}">{{ form.price.label }}</label>
- <div class="col-md-10">
- {{ form.price }}
- </div>
- </div>
- <div class="form-group">
- <label class="col-md-2 control-label"
- for="{{ form.publish_date.id_for_label }}">{{ form.publish_date.label }}</label>
- <div class="col-md-10">
- {{ form.publish_date }}
- </div>
- </div>
- <div class="form-group">
- <label class="col-md-2 control-label"
- for="{{ form.publisher.id_for_label }}">{{ form.publisher.label }}</label>
- <div class="col-md-10">
- {{ form.publisher }}
- </div>
- </div>
- <div class="form-group">
- <label class="col-md-2 control-label"
- for="{{ form.authors.id_for_label }}">{{ form.authors.label }}</label>
- <div class="col-md-10">
- {{ form.authors }}
- </div>
- </div>
- <div class="form-group">
- <div class="col-md-offset-2 col-md-10">
- <button type="submit" class="btn btn-success">提交</button>
- <a class="btn btn-warning pull-right" href="/book/" rel="external nofollow" >取消</a>
- </div>
- </div>
- </form>
- {# form结束 #}
- </div>
- {# panel-body结束 #}
- </div>
- {# panel结束 #}
- </div>
- </div>
- </body>
- </html>
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持w3xue。