除了在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. flutter问题集锦

    现在的多平台开发很多啦,目前主流的救赎react native 和weex了,其他的旧的就不说了,新出来的gomobile目前基本无人使用,底层的很多原生对接还没有完善,flutter发布了第一版正式 ...

  2. jumperver源码理解以及部分修改

    一  admin后台处理以及展示修改    jumpserver 默认不开放admin后台(获取是我没用使用正确的打开方式,) 打开方式 找到程序的入口 urls.py 修改,另外主要看下settin ...

  3. Java检查异常和非检查异常,运行时异常和非运行时异常的区别

    通常,Java的异常(包括Exception和Error)分为检查异常(checked exceptions)和非检查的异常(unchecked exceptions).其中根据Exception异常 ...

  4. JavaSpring【五、AOP基础】

    概念: AOP--面向切面编程,通过预编译/动态代理实现程序功能的统一维护 主要功能是:日志.性能统计.安全控制.事务处理.异常处理 实现方式 预编译--AspectJ 动态代理--SpringAOP ...

  5. dedecms:限制栏目列表生成的最大页数防止被采集

    dedecms:限制栏目列表生成的最大页数防止被采集 如果您的网站数据量较大,列表很多的话甚至达到上千页,生成列表时就特别耗费时间,这个缺点可以被优化掉:网站好不容易建起来,担心网站内容被采集走,如果 ...

  6. php的小数位数最长多少位

    在php中, echo 0.1234567890123456;exit; // 结果为:0.12345678901235, 整数部分为0时,最多到14位小数,如果后面还有,就自动四舍五入 echo 7 ...

  7. OpenCV_contrib里的Text(自然场景图像中的文本检测与识别)

    平台:win10 x64 +VS 2015专业版 +opencv-3.x.+CMake 待解决!!!Issue说明:最近做一些字符识别的事情,想试一下opencv_contrib里的Text(自然场景 ...

  8. RocketMQ顺序消息

    rocketmq的顺序消息需要满足2点: 1.Producer端保证发送消息有序,且发送到同一个队列.2.consumer端保证消费同一个队列. 生产端: RocketMQ可以严格的保证消息有序.但这 ...

  9. java 使用POI导出百万级数据

    先看结果吧,这只是测试其中有很多因数影响了性能. 表总数为:7千多万,测试导出100万 表字段有17个字段 最终excel大小有60多兆 总耗时:126165毫秒 差不多2分多钟 其核心简单来说就是分 ...

  10. Linux的.a、.so和.o文件及链接时的命名

    在说明Linux的.a..so和.o文件关系之前,先来看看windows下obj,lib,dll,exe的关系 windows下obj,lib,dll,exe的关系 lib是和dll对应的.lib是静 ...