Form介绍

我们之前在HTML页面中利用form表单向后端提交数据时,都会写一些获取用户输入的标签并且用form标签把它们包起来。

与此同时我们在好多场景下都需要对用户的输入做校验,比如校验用户是否输入,输入的长度和格式等正不正确。如果用户输入的内容有错误就需要在页面上相应的位置显示对应的错误信息.。

Django form组件就实现了上面所述的功能。

总结一下,其实form组件的主要功能如下:

  • 生成页面可用的HTML标签
  • 对用户提交的数据进行校验
  • 保留上次输入内容

普通方式手写图书管理系统的增加书籍和编辑书籍功能

views.py,

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":
title = request.POST.get("title")
price = request.POST.get("price")
publish_date = request.POST.get("publish_date")
publisher = request.POST.get("publisher")
authors = request.POST.get("authors")
# 数据库中的数据
book_obj = models.Book.objects.create(
title=title,
price=price,
publish_date=publish_date,
publisher_id=publisher,
)
book_obj.authors.add(*authors)
return redirect("/book_list/")
publisher_list = models.Publisher.objects.all()
author_list = models.Author.objects.all()
return render(request,"add_book.html",{"publisher_list":publisher_list,"author_list":author_list}) # 编辑出版社
def edit_book(request, pk):
book_obj = models.Book.objects.filter(id=pk).first()
if request.method == "POST":
title = request.POST.get("title")
price = request.POST.get("price")
publish_date = request.POST.get("publish_date")
publisher = request.POST.get("publisher")
authors = request.POST.getlist("authors") # 什么时候用getlist/多选的checkbox也是
book_obj.title = title
book_obj.price = price
book_obj.publish_date = publish_date
book_obj.publisher_id = publisher
book_obj.save()
book_obj.authors.set(authors)
return redirect("/book_list/")
publisher_list = models.Publisher.objects.all()
author_list = models.Author.objects.all()
return render(request, "edit_book.html", locals())

book_list.html:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>书籍列表</title>
<link rel="stylesheet" href="/static/plugins/bootstrap-3.3.7/css/bootstrap.css">
<link rel="stylesheet" href="/static/css/pub.css">
</head>
<body>
{% include 'nav.html' %}
<div class="container-fluid">
<div class="row">
<div class="col-sm-3 col-md-2 sidebar">
<ul class="nav nav-sidebar">
<li><a href="/publisher/">出版社管理 <span class="sr-only">(current)</span></a></li>
<li class="active"><a href="/book_list/">书籍管理</a></li>
<li><a href="/author_list/">作者管理</a></li>
</ul>
</div>
<div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main"> <div class="panel panel-primary">
<div class="panel-heading">
<h2 class="panel-title">书籍列表</h2>
</div> <div class="panel-body">
<div class="row">
<div class="col-lg-3">
<div class="input-group">
<input type="text" class="form-control" placeholder="搜索">
<span class="input-group-btn">
<button class="btn btn-primary" type="button">Go</button>
</span>
</div><!-- /input-group -->
</div> <div class="pull-right col-lg-1">
<a href="/add_book/" class="btn btn-info ">添加</a>
</div>
</div>
<div class="table-responsive">
<table class="table table-striped table-hover">
<thead>
<tr>
<th>序号</th>
<th>ID</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.id }}</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 %}
{% if forloop.last %}
{{ author.name }}
{% else %}
{{ author.name }} |
{% endif %}
{% endfor %}
</td>
<td>
<a href="/del_book/{{ book.id }}" class="btn btn-danger btn-sm">删除</a>
<a href="/edit_book/{{ book.id }}" class="btn btn-warning btn-sm">编辑</a>
</td>
</tr> {% endfor %} </tbody>
</table>
</div> <div class="pull-right">
<nav aria-label="...">
<ul class="pagination">
<li class="disabled"><a href="#" aria-label="Previous"><span aria-hidden="true">«</span></a>
</li>
<li class="active"><a href="#">1 <span class="sr-only">(current)</span></a></li>
<li><a href="#">2</a></li>
<li><a href="#">3</a></li>
<li><a href="#">4</a></li>
<li><a href="#">5</a></li>
<li><a href="#" aria-label="Next"><span aria-hidden="true">»</span></a></li>
</ul>
</nav>
</div> </div>
</div>
</div>
</div>
</div> </body>
</html>

edit_book.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>编辑书籍</title>
<link rel="stylesheet" href="/static/plugins/bootstrap-3.3.7/css/bootstrap.css"> </head>
<body>
{% include 'nav.html' %}
<div class="container" style="margin-top: 100px">
<div class="row">
<div class="col-lg-6 col-lg-offset-3">
<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="panel-title">编辑书籍</h3>
</div> <div class="panel-body"> <div class="row">
<form class="form-horizontal" method="post" action="">
{% csrf_token %}
<input type="text" name="id" value="{{ edit_book.id }}" style="display: none">
<div class="form-group">
<label for="publisher" class="col-sm-2 control-label">名称</label>
<div class="col-sm-9">
<input type="text" class="form-control" id="publisher" name="title"
value="{{ book_obj.title }}">
</div>
</div>
<div class="form-group">
<label for="price" class="col-sm-2 control-label">价格</label>
<div class="col-sm-9">
<input type="text" class="form-control" id="price" name="price"
value="{{ book_obj.price }}">
</div>
</div>
<div class="form-group">
<label for="date" class="col-sm-2 control-label">日期</label>
<div class="col-sm-9">
<input type="date" class="form-control" id="date" name="date"
value="{{ book_obj.publish_date|date:'Y-m-d' }}">
</div>
</div>
<div class="form-group">
<label for="publisher" class="col-sm-2 control-label">出版社</label>
<div class="col-sm-9">
<select name="publish" id="" class="form-control">
{% for publish in publisher_list %}
{% if publish.id == book_obj.publisher_id %}
<option value="{{ publish.id }}" selected>{{ publish.name }}</option>
{% else %}
<option value="{{ publish.id }}">{{ publish.name }}</option>
{% endif %}
{% endfor %}
</select>
</div>
</div>
<div class="form-group">
<label for="publisher" class="col-sm-2 control-label">作者</label>
<div class="col-sm-9">
<select name="authors" id="" class="form-control">
{% for author in author_list %}
{% if author in book_obj.authors.all %}
<option selected value="{{ author.id }}">{{ author.name }}</option>
{% else %}
<option value="{{ author.id }}">{{ author.name }}</option>
{% endif %}
{% endfor %}
</select>
</div>
</div> <div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-default">提交</button>
</div>
</div>
<div class="row">
<p class="text-center text-danger">{{ err_msg }}</p> </div>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
</body>
</html>

add_book.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>添加书籍</title>
<link rel="stylesheet" href="/static/plugins/bootstrap-3.3.7/css/bootstrap.css"> </head>
<body>
{% include 'nav.html' %}
<div class="container" style="margin-top: 100px">
<div class="row">
<div class="col-lg-6 col-lg-offset-3">
<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="panel-title">增加书籍</h3>
</div> <div class="panel-body"> <div class="row">
<form class="form-horizontal" method="post" action="">
{% csrf_token %}
<div class="form-group">
<label for="publisher" class="col-sm-2 control-label">名称</label>
<div class="col-sm-9">
<input type="text" class="form-control" id="publisher" name="title">
</div>
</div>
<div class="form-group">
<label for="price" class="col-sm-2 control-label">价格</label>
<div class="col-sm-9">
<input type="text" class="form-control" id="price" name="price">
</div>
</div>
<div class="form-group">
<label for="publish_date" class="col-sm-2 control-label">日期</label>
<div class="col-sm-9">
<input type="date" class="form-control" id="publish_date" name="publish_date">
</div>
</div>
<div class="form-group">
<label for="publisher" class="col-sm-2 control-label">出版社</label>
<div class="col-sm-9">
<select name="publisher" id="" class="form-control"> {% for publish in publisher_list %}
<option value="{{ publish.id }}">{{ publish.name }}</option>
{% endfor %}
</select>
</div>
</div>
<div class="form-group">
<label for="authors" class="col-sm-2 control-label">作者</label>
<div class="col-sm-9">
<select name="authors" id="" class="form-control"> {% for author in author_list %}
<option value="{{ author.id }}">{{ author.name }}</option>
{% endfor %}
</select>
</div>
</div> <div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-default">提交</button>
</div>
</div>
<div class="row">
<p class="text-center text-danger">{{ err_msg }}</p> </div>
</form>
</div>
</div>
</div>
</div>
</div>
</div> </body>
</html>

nav.html:

<nav class="navbar navbar-inverse navbar-fixed-top">
<div class="container-fluid">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar"
aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#">图书管理系统</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav navbar-right">
<li><a href="#">Dashboard</a></li>
<li><a href="#">Settings</a></li>
<li><a href="#">Profile</a></li>
<li><a href="#">Help</a></li>
</ul>
<form class="navbar-form navbar-right">
<input type="text" class="form-control" placeholder="Search...">
</form>
</div>
</div>
</nav>

2、用form组件实现增改查:

要带入from django.forms.models import model_to_dict实现默认值的显示:

views.py代码:

# y用form组件的增加书籍
def add_book1(request):
# 获取前端提交的数据
if request.method == "POST":
# 不用一步一步写了,直接获取就行了
form_obj = forms.BookForm(request.POST)
# 进行校验
if form_obj.is_valid():
# 因为authors是关联表里边的,不是书籍这张表里的,所以要把这个弹出去
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/")
publisher_list = models.Publisher.objects.all()
author_list = models.Author.objects.all()
form_obj = forms.BookForm()
return render(request, "add_book1.html", locals()) # y用form组件的编辑书籍
def edit_book1(request, pk):
book_obj = models.Book.objects.filter(id=pk).first()
obj_dict = model_to_dict(book_obj)
print(obj_dict) # 能把你想要修改的那个对象获取出来
if request.method == "POST":
form_obj = forms.BookForm(request.POST)
if form_obj.is_valid():
title = form_obj.cleaned_data.get("title")
price = form_obj.cleaned_data.get("price")
publish_date = form_obj.cleaned_data.get("publish_date")
publisher = form_obj.cleaned_data.get("publisher")
authors = form_obj.cleaned_data.get("authors")
book_obj.title = title
book_obj.price = price
book_obj.publish_date = publish_date
book_obj.publisher_id = publisher
book_obj.save()
book_obj.authors.set(authors)
return redirect("/book_list/")
form_obj = forms.BookForm(initial=obj_dict) # 这个就是你原来的默认值
publisher_list = models.Publisher.objects.all()
author_list = models.Author.objects.all()
return render(request, "edit_book1.html", locals())

html代码,编辑和增加都一样:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>添加书籍</title>
</head>
<body> <form action="" method="post">
{% csrf_token %}
{% for filed in form_obj %}
<p>
{{ filed.label }}
{{ filed }}
</p>
{% endfor %}
{{ form_obj.errors }}
<p>
<input type="submit">
</p>
</form>
</body>
</html>

form.py中的一个属性也要改变:

class BookForm(forms.Form):
title = forms.CharField(max_length=32, label="书名")
price = forms.DecimalField(max_digits=5, decimal_places=2)
publish_date = forms.DateField( # 这个是因为返回的页面要是date格式的
widget=forms.widgets.DateInput(
attrs={"type": "date"}
)
)
publisher = forms.ModelChoiceField(
# choices=models.Publisher.objects.all().values_list("id","name"),
# widget=forms.widgets.Select(), # 单选
queryset=models.Publisher.objects.all() # 单选这个是和你模型绑定
)
authors = forms.ModelMultipleChoiceField(
# choices=models.Author.objects.all().values_list("id", "name"),
# widget=forms.widgets.SelectMultiple(), # 多选
queryset=models.Author.objects.all() # 单选这个是和你模型绑定
)

form组件中遇到的知识点:

用form组件实现增改查
1. 在页面展示html时
{% for filed in form_obj %}
<p>
{{ filed.label }}
{{ filed }}
</p>
{% endfor %} 2. ChoiceField -> ModelChoiceField -> ModelMultipleChoiceField
1. ModelChoiceField
生成select标签
option选项是从queryset中获取的
2. ModelMultipleChoiceField
生成多选的select标签
option选项是从queryset中获取 3. form_obj如何设置初始化的值
from django.forms.models import model_to_dict --> Django 内置的把ORM对象转换成字典的工具函数
obj_dict = model_to_dict(book_obj)
form_obj = forms.BookForm(initial=obj_dict)

3.使用modelform,使用这个简单明了,就是在form.py写:

from django import forms
from app01 import models class BookForm(forms.Form):
title = forms.CharField(max_length=32, label="书名")
price = forms.DecimalField(max_digits=5, decimal_places=2)
publish_date = forms.DateField( # 这个是因为返回的页面要是date格式的
widget=forms.widgets.DateInput(
attrs={"type": "date"}
)
)
publisher = forms.ModelChoiceField(
# choices=models.Publisher.objects.all().values_list("id","name"),
# widget=forms.widgets.Select(), # 单选
queryset=models.Publisher.objects.all() # 单选这个是和你模型绑定
)
authors = forms.ModelMultipleChoiceField(
# choices=models.Author.objects.all().values_list("id", "name"),
# widget=forms.widgets.SelectMultiple(), # 多选
queryset=models.Author.objects.all() # 单选这个是和你模型绑定
) # modelform
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": "价格"
}

views.py代码:

# y用modelform的增加书籍
def add_book2(request):
# 获取前端提交的数据
if request.method == "POST":
# 不用一步一步写了,直接获取就行了
form_obj = forms.BookModelForm(request.POST)
# 进行校验
if form_obj.is_valid():
form_obj.save()
return redirect("/book_list/")
form_obj = forms.BookModelForm()
return render(request, "add_book1.html", locals()) # y用modelform的编辑书籍
def edit_book2(request, pk):
book_obj = models.Book.objects.filter(id=pk).first()
if request.method == "POST":
form_obj = forms.BookModelForm(request.POST, instance=book_obj)
if form_obj.is_valid():
form_obj.save()
return redirect("/book_list/")
form_obj = forms.BookModelForm(instance=book_obj) # 实例:直接传,不需要转成字典类型
return render(request, "edit_book1.html", locals())

modelform的简介的更多相关文章

  1. Django之modelform简介

    在django中内置了form类和model类,当页面中的form值和model字段值完全一样时,此时可以通过model生成一个完全一样的form,Django中的modelForm就因此而生. 目标 ...

  2. Django之modelform组件

    一.简介与基本使用 简介:django中的modelform组件同时具有model和form作用,但是耦合度比较高,当项目需要拆分时候就比较困难了,所以在使用modelform时候需要先考虑项目的扩展 ...

  3. Django之ModelForm

    简介 Model + Form ==> ModelForm.model和form的结合体,所以有以下功能: 验证 数据库操作 Form回顾 models.py class UserType(mo ...

  4. Django之Form、ModelForm 组件

    Django之Form.ModelForm 组件 一.Form组件: django框架提供了一个form类,来处理web开发中的表单相关事项.众所周知,form最常做的是对用户输入的内容进行验证,为此 ...

  5. Django—ModelForm

    简介 Model + Form ==> ModelForm.model和form的结合体,所以有以下功能: 验证 数据库操作 Form回顾 models.py class UserType(mo ...

  6. forms组件补充与ModelForm简单使用与cookie与session

    目录 forms组件钩子函数 forms组件字段参数 字段参数 validators详解 choices详解 widget详解 forms组件字段类型 ModelForm简单使用 cookie与ses ...

  7. ASP.NET Core 1.1 简介

    ASP.NET Core 1.1 于2016年11月16日发布.这个版本包括许多伟大的新功能以及许多错误修复和一般的增强.这个版本包含了多个新的中间件组件.针对Windows的WebListener服 ...

  8. MVVM模式和在WPF中的实现(一)MVVM模式简介

    MVVM模式解析和在WPF中的实现(一) MVVM模式简介 系列目录: MVVM模式解析和在WPF中的实现(一)MVVM模式简介 MVVM模式解析和在WPF中的实现(二)数据绑定 MVVM模式解析和在 ...

  9. Cassandra简介

    在前面的一篇文章<图形数据库Neo4J简介>中,我们介绍了一种非常流行的图形数据库Neo4J的使用方法.而在本文中,我们将对另外一种类型的NoSQL数据库——Cassandra进行简单地介 ...

随机推荐

  1. AT2134 Zigzag MST 最小生成树

    正解:最小生成树 解题报告: 先放下传送门QAQ 然后这题,首先可以发现这神奇的连边方式真是令人头大,,,显然要考虑转化掉QAQ 大概看一下可以发现点对的规律是,左边++,交换位置,再仔细想下,就每个 ...

  2. kali蓝牙连接

    http://blog.csdn.net/hailangnet/article/details/47723181 http://www.aiuxian.com/article/p-3012084.ht ...

  3. 【Selenium】selenium中隐藏元素如何定位?

    前言 面试题:selenium 中隐藏元素如何定位?这个是很多面试官喜欢问的一个题,如果单纯的定位的话,隐藏元素和普通不隐藏元素定位没啥区别,用正常定位方法就行了 但是吧~~~很多面试官自己都搞不清楚 ...

  4. 张小龙2018PRO版微信公开课演讲全文 透露2018微信全新计划

    大家好!我是张小龙.欢迎大家来到微信公开课. 刚刚出现的是我打游戏的画面,被大家看到了,那个不是我最好的水平,因为有点紧张,我最高分曾打到6000多分.当然我是练习了很久了,并不是我比大家更厉害,而是 ...

  5. ACM-最短路之中的一个个人的旅行——hdu2066

    版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/lx417147512/article/details/27235809 ************** ...

  6. MySQL的并行复制多线程复制MTS(Multi-Threaded Slaves)

    MySQL的并行复制多线程复制MTS(Multi-Threaded Slaves) http://www.tuicool.com/articles/m2Unmeq 姜承饶 简称MTS:基于binlog ...

  7. unix下命令窗分屏工具

    运行 sudo apt-get install terminator 效果 新建分屏窗口:右键鼠标选择

  8. 012-Future、FutureTask、CompletionService 、CompletableFuture

    一.概述 创建线程的两种方式,一种是直接继承Thread,另外一种就是实现Runnable接口.这两种方式都有一个缺陷就是:在执行完任务之后无法获取执行结果.如果需要获取执行结果,就必须通过共享变量或 ...

  9. Python Socket通信黏包问题分析及解决方法

    参考:http://www.cnblogs.com/Eva-J/articles/8244551.html#_label5 1.黏包的表现(以客户端远程操作服务端命令为例) 注:只有在TCP协议通信的 ...

  10. shell for 循环数组

    name=(aa bb) ;i<${#name[*]};i++)) do name=${name[i]} echo "$name" done