除了在html中自己手写form表单外,django还可以通过 继承django.forms.Form 或django.forms.ModelForm两个类来自动生成form表单,下面依次利用三种方式来实现form表单,实现向数据库中添加书籍的页面,效果如下:

  首先在models类中定义了Book,Author和Publish类,并定义了关联关系,publish,author和book分别为一对多和多对多关系,代码如下:

class Book(models.Model):
title = models.CharField(max_length=64)
price = models.DecimalField(max_digits=5,decimal_places=2,default=0)
author = models.ManyToManyField(to='Author')
publish = models.ForeignKey(to='Publish')
def __str__(self):
return self.title class Author(models.Model):
name = models.CharField(max_length=128)
age = models.IntegerField()
def __str__(self):
return self.name class Publish(models.Model):
name = models.CharField(max_length=255)
address = models.CharField(max_length=255)
def __str__(self):
return self.name

1 原生form表单

       在html页面中手写表单,很简单,直接上代码,对应的Html和视图函数如下:

addbook.html

<form action="" method="post">
{% csrf_token %}
<p >
<label>书籍标题:</label>
<input type="text" name="title" class="form-control"/>
</p>
<p>
<label>价格:</label>
<input type="number" name="price" class="form-control"/>
</p>
<p>
<label>出版社:</label>
<select name="publish" class="form-control">
{% for publish in publishs %}
<option value="{{ publish.pk }}">{{ publish.name }}</option>
{% endfor %}
</select>
</p>
<p>
<label>作者:</label>
<select multiple="multiple" name="author" class="form-control">
{% for author in authors %}
<option value="{{ author.pk }}">{{ author.name }}</option>
{% endfor %}
</select>
</p>
<input type="submit" value="保存"/>
</form>

views.py

def addbook(request):
authors = models.Author.objects.all()
publishs = models.Publish.objects.all()
if request.method=='POST':
title = request.POST.get('title')
price = request.POST.get('price')
author = request.POST.getlist('author')
publish = request.POST.get('publish')
# print author, publish
book_obj = models.Book.objects.create(title=title,price=price,publish_id=publish)
book_obj.author.add(*author) #此时添加的为author的id值 [u'1', u'3]
# for i in author:
# book_obj.author.add(int(i))
# book_obj.save()
return redirect('/listbook/')
return render(request,'addbook.html',locals())

2 继承django.forms.Form类

model 字段和form字段的对应关系

Model field Form field
AutoField Not represented in the form
BigAutoField Not represented in the form
BigIntegerField IntegerField with min_value set to -9223372036854775808 and max_value set to 9223372036854775807.
BinaryField CharField, if editable is set to True on the model field, otherwise not represented in the form.
BooleanField BooleanField, or NullBooleanField if null=True.
CharField CharField with max_length set to the model field’s max_length and empty_value set to None if null=True.
DateField DateField
DateTimeField DateTimeField
DecimalField DecimalField
EmailField EmailField
FileField FileField
FilePathField FilePathField
FloatField FloatField
ForeignKey ModelChoiceField (see below)
ImageField ImageField
IntegerField IntegerField
IPAddressField IPAddressField
GenericIPAddressField GenericIPAddressField
ManyToManyField ModelMultipleChoiceField (see below)
NullBooleanField NullBooleanField
PositiveIntegerField IntegerField
PositiveSmallIntegerField IntegerField
SlugField SlugField
SmallIntegerField IntegerField
TextField CharField with widget=forms.Textarea
TimeField TimeField
URLField URLField

首先定义一个BookForm类,继承forms.Form,根据models中定义的Book类,逐个定义相应的字段,字段中可以定义相应的参数,如required=True,表示默认为True,字段不能为空;label定义标签;initial设置初始值;以及error_messages和widget等,参数详细使用见https://docs.djangoproject.com/zh-hans/2.0/ref/forms/fields/。

BookForm类如下:


class BookForm(forms.Form):
title=forms.CharField(
label='书籍标题',
max_length=32,
widget=forms.widgets.TextInput(attrs={'class':'form-control'})
)
price = forms.DecimalField(
label='价格',
widget=forms.widgets.TextInput(attrs={'type':'number','class':'form-control'})
) # 设置type来改变类型,显示数字输入框 publish = forms.ModelChoiceField(
label='出版社',
queryset=models.Publish.objects.all(),
widget=forms.widgets.Select(attrs={'class': 'form-control'})
)
# gender=forms.ChoiceField(choices=((1,"男"),(2,"女"),(3,"其他")))
# publish=forms.ChoiceField(choices=Publish.objects.all().values_list("pk","title"))
#ModelChoiceField继承了ChoiceField
author = forms.ModelMultipleChoiceField(
label='作者',
queryset=models.Author.objects.all(),
widget=forms.widgets.SelectMultiple(attrs={'class': 'form-control'})
)

  定义好BookForm类后只需在视图函数中进行实例化,并将实例传给前端html,就能自动生成表单,视图函数和html代码如下。BookForm类除了能自动生成前端表单外,还能对数据进行校验,若校验通过,is_valid()方法返回True,并将校验后的数据以字典形式封装到cleaned_data中

views.py

def addbook(request):
if request.method=='POST':
form = BookForm(request.POST)
if form.is_valid():
author = form.cleaned_data.pop('author')
# print form.cleaned_data, author
book_obj = models.Book.objects.create(**form.cleaned_data)
for i in author:
book_obj.author.add(i) #此时添加的为author queryset对象
book_obj.save()
return redirect('/listbook/')
form = BookForm()
return render(request,'addbook.html',locals())

addbook.html

<form  action="" method="post">
{% csrf_token %}
{% for field in form %}
<div >
{{ field.label }}
{{ field }}
</div>
{% endfor %}
<input type="submit" value="保存"/>
</form>

3 继承django.forms.ModelForm类

定义一个BookModelForm类,继承forms.ModelForm,相比forms.Form其更加简单,不用逐个定义字段,只需将Book类和需要显示的字段传入,也可以自定义label,widget等参数,详细使用见 https://docs.djangoproject.com/en/2.1/topics/forms/modelforms/

BookModelForm类如下:

    class Meta:
model = models.Book
fields = '__all__' # 类似于fields = ['title','price','publish','author'],可以自定义需要显示的字段,__all__为所有字段
labels = {
'title': '书籍名称',
'price': '价格',
'author':'作者',
'publish': '出版社'
}
widgets = {
'title':forms.widgets.TextInput(attrs={'class':'form-control'}),
'price':forms.widgets.TextInput(attrs={'class':'form-control','type':'number'}),
'author': forms.widgets.SelectMultiple(attrs={'class': 'form-control'}),
'publish': forms.widgets.Select(attrs={'class':'form-control'})
} #必须按定义的字段顺序排列

  和forms.Form一样,在视图函数中向前端传入BookModelForm实例对象,就能自动生成form表单,但其对表单数据处理更加简单,可以直接调用save方法,而且若未对表单数据校验时,save方法会对数据进行校验,另外可以通过BookModelForm(request.POST,instance=a)形式来传入单个实例,储存一条数据记录,如下:

>>> a = Article.objects.get(pk=1)
>>> f = ArticleForm(request.POST, instance=a)
>>> f.save()

  具体的视图函数和前端代码如下:

views.py

def addbook(request):
form = BookModelForm()
if request.method=='POST':
form = BookModelForm(request.POST) # 参数中还可以传单个实例,来储存一条数据
form.save() # 若未进行数据校验时,save()方法会对数据进行校验
return redirect('/listbook/')
return render(request,'addbook.html',locals())

addbook.html

<form  action="" method="post">
{% csrf_token %}
{% for field in form %}
<div >
{{ field.label }}
{{ field }}
</div>
{% endfor %}
<input type="submit" value="保存"/>
</form>

相关参考博客:http://www.cnblogs.com/yuanchenqi/articles/8034442.html

http://www.cnblogs.com/yuanchenqi/articles/7614921.html

Django中三种方式写form表单的更多相关文章

  1. java:JavaScript2:(setTimeout定时器,history.go()前进/后退,navigator.userAgent判断浏览器,location.href,五种方法获取标签属性,setAttribute,innerHTML,三种方法获取form表单信息,JS表单验证,DOM对象,form表单操作)

    1.open,setTimeout,setInterval,clearInterval,clearTimeout <!DOCTYPE> <html> <head> ...

  2. jQuery中.bind() .live() .delegate() .on()的区别 和 三种方式写光棒事件 动画

    地狱的镰刀 bind(type,[data],fn) 为每个匹配元素的特定事件绑定事件处理函数. $("a").bind("click",function(){ ...

  3. JavaScript--------------------jQuery中.bind() .live() .delegate() .on()的区别 和 三种方式写光棒事件 动画

    bind(type,[data],fn) 为每个匹配元素的特定事件绑定事件处理函数. $("a").bind("click",function(){alert( ...

  4. Jobs(三) HTML的form表单提交中文后,后台取出乱码的问题

    解决form表单中提取的中文在后台乱码的问题有两种情况: form表单以GET方式提交: form表单以POST方式提交 一. 解决以GET方式提交的中文乱码问题,可以更改Tomcat服务器的配置文件 ...

  5. jquery下的提交,点击按钮没反应,post方法不执行 JSON方式在FORM表单下不起作用

    jquery下的提交,点击按钮没反应,post方法不执行 JSON方式在FORM表单下不起作用

  6. Django学习笔记(6)——Form表单

    知识储备:HTML表单form学习 表单,在前端页面中属于最常见的一个东西了.基本上网站信息的提交都用到了表单,所以下面来学习Django中优雅的表单系统:Form 表单的主要作用是在网页上提供一个图 ...

  7. SpringMVC中使用bean来接收form表单提交的参数时的注意点

    这是前辈们对于SpringMVC接收表单数据记录下来的总结经验: SpringMVC接收页面表单参数 springmvc请求参数获取的几种方法 下面是我自己在使用时发现的,前辈们没有记录的细节和注意点 ...

  8. ajax无刷新方式对form表单进行赋值!

    /** * 把json数据填充到from表单中 */ <form id="editForm" action="user.php"> 用户名:< ...

  9. django中写form表单时csrf_token的作用

    之前在学习django的时候,在template中写form时,出现错误.百度,google后要加{% csrf_token %}才可以,之前一直也没研究,只是知道要加个这个东西,具体是什么也不明白. ...

随机推荐

  1. cookie 和session的关联关系

    session 1.1 数据存储,存服务器端, 浏览器解决http无状态问题的一种解决方案 登录,同一客户端访问服务端的时候,服务端都知道是这一个客户端 cookie 2.1 数据存储 , 存客户端 ...

  2. 7.使用EXPLAIN 来分析SQL和表结构_2

    possible_keys    ------   显示可能应用在这张表的索引,一个或多个 查询涉及到的字段上若存在索引,则该索引将被列出,但不一定被实际查询使用 key   ------   实际使 ...

  3. 第四章、前端之BOM和DOM

    目录 第四章.前端之BOM和DOM 一.解释BOM和DOM 二.window对象 三.window子对象 四.弹出框 五.计时相关 六.HTML的DOM树 七.查找元素 八.节点操作 九.JS操作CS ...

  4. Hadoop_18_MapRduce 内部的shuffle机制

    1.Mapreduce的shuffle机制: Mapreduce中,map阶段处理的数据如何传递给Reduce阶段,是mapreduce框架中最关键的一个流程,这个流程就叫shuffle 将mapta ...

  5. gdb 使用finish命令(缩写fin)

    gdb 使用finish命令(缩写fin) gdb 使用finish命令(缩写fin) gdb 使用finish命令(缩写fin) 跳出跟踪的函数

  6. vue今日总结

    ''' 复习 ''' """ 1.vue框架的优势 中文API 单一面应用 - 提升移动端app运行速度 数据的双向绑定 - 变量全局通用 数据驱动 - 只用考虑数据,不 ...

  7. tensorflow.python.framework.errors_impl.PermissionDeniedError: /data; Permission denied

    在linux系统中,tensorflow跑mnist数据集出现错误,本应该自动下载的数据集 将mnist自动下载的路径,由/data/mnist之前的/删掉即可.改为data/mnist.

  8. 完整开发vue后台管理系统小结

    最近业余帮朋友做两个vue项目,一个是面向用户纯展示系列的(后统称A项目),一个是后端管理系统类的(后统称B项目).两者在技术上都没难度,这里对开发过程遇到的问题.取舍等做一个小节. 关于项目搭建 目 ...

  9. wavefronts

    https://www.g-truc.net/post-0597.html https://michaldrobot.com/2014/04/01/gcn-execution-patterns-in- ...

  10. 《SVG精髓》笔记(一)

    本文是基于<SVG精髓>一书的简单总结,文中的demo均为该书提供,目的是方便大家使用时快速查阅. 1. 坐标系统 视口(viewport):文档使用的画布区域,表示SVG可见区域的大小, ...