除了在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. 安卓开发之ListView入门

    <!--这个地方最好用match_parent 这样效率高--> <ListView android:layout_width="match_parent" an ...

  2. FlowPortal BPM 安装环境的配置

    l  操作系统:Windows Server 2003 及以上: l  IIS: 在Internet信息服务(IIS)管理器中将ISAPI和CGI限制全部设为“允许” l  需要安装.Net Fram ...

  3. python命令行获取参数

    python命令行获取参数 import sys # python获取参数 input_file = sys.argv[1] output_file = sys.argv[2] print(input ...

  4. Winform 多项目共用AssemblyInfo解决方案

    Winform 多项目共用AssemblyInfo解决方案: 操作步骤如下: 第一步:复制任何项目中的AssemblyInfo.cs文件至指定目录 第二步:删除所有项目的AssemblyInfo.cs ...

  5. 一篇关于ajax跨域问题的解决方案

    这几天没事,我有一个好友,让我帮他做一个机器人对话demo, 我说 看看有没有时间(其实自己一脸懵逼) 然后百度了一下,发现了一个机器人  -(连接就不弄出来了,可以私底下交流) ,,我是用这个的 好 ...

  6. PMM 监控 MySQL

    Percona Monitoring and Management (PMM)是一款开源的用于监控 MySQL 和 MongoDB 性能的开源平台,通过 PMM 客户端收集到的 DB 监控数据用第三方 ...

  7. Swagger保姆级教学

    Swagger保姆级教学 Swagger 简介 Swagger 是一个规范和完整的框架,用于生成.描述.调用和可视化 RESTful 风格的 Web 服务.总体目标是使客户端和文件系统作为服务器以同样 ...

  8. 我的第一个Node.js项目

    Node.js的安装通常有两种方式:自己编译源代码和使用编译好的文件,我这里使用编译好的文件目前我的home目录下有刚下载来的node-v4.2.3-linux-x641.首先解压缩 tar xvf ...

  9. 低级键盘钩子,在WIN7以上版本的问题

    最近在项目用到低级键盘钩子.发现一个很奇怪的事情,在开发环境和测试环境下都正常运行的键盘钩子, 到了现场环境,总是偶发性出现 键盘钩子不能用了,而且退出时产生1404 错误. 后经过阅读MSDN 的R ...

  10. CentOS7下tftp服务安装配置

    1.软件包安装 root用户或者普通用户使用sudo权限执行如下命令: yum install xinetd tftp tftp-server # root 用户执行 sudo yum install ...