Django实战1-权限管理功能实现-06:知识扩展-Django表单

在项目中咱们已经使用到Django Form和ModelForm的验证功能,这一节我经过一些例子来了解更多Django表单的用法(本节代码非项目代码,测试完后既可删除)。html

1 使用表单

在【Django实战1-权限管理功能实现-03:用户认证】一节,已经使用到HTML表单功能,经过HTML表单向后台提交用户信息,完成用户的登录认证。
咱们来看下sandboxMP/templates/system/users/login.html内容:前端

{% extends "system/users/user-base.html" %} {% block user-content %} <!-- /.login-logo --> <div class="login-box-body form-"> <p class="login-box-msg"></p> <p></p> <form action="" method="post"> <div class="form-group has-feedback {% if login_form.errors.username %}has-error{% endif %}"> <input name="username" class="form-control" placeholder="用户名或手机号" value="{{ login_form.username.value }}"> <!--type="email"前端控制email输入验证--> <span class="glyphicon glyphicon-envelope form-control-feedback"></span> </div> <div class="form-group has-feedback {% if login_form.errors.password %}has-error{% endif %}"> <input name="password" type="password" class="form-control" placeholder="密码" value="{{ login_form.password.value }}"> <span class="glyphicon glyphicon-lock form-control-feedback"></span> </div> <div class="row"> <div class="col-xs-8"> </div> <!-- /.col --> <div class="col-xs-4"> <button type="submit" class="btn btn-primary btn-block btn-flat">登陆</button> </div> <!-- /.col --> </div> {% csrf_token %} </form> {% if msg %} <!--判断若是后端返回用户验证错误信息,前端页面输出错误信息--> <p class="text-red">{{ msg }}</p> {% endif %} </div> <!-- /.login-box-body --> </div> <!-- /.login-box --> {% endblock %}

登录页面标签说明:数据库

1、<form action="" method="post"> :定义了form的HTTP方法为POST, 和请求地址为当前页 2、<input name="username"> input类型,用户接收用户输入内容,其中name属性定义了input元素的名称,用于对提交到服务器后的表单数据进行识别。 3、<button type="submit">登陆</button>:提交按钮 4、{% csrf_token %}:当提交一个启用CSRF防御的POST表单时,必须使用上面的csrf_token 模板标签 

1.1 在django中建立表单

前面使用到的表单,是经过在模板中建立的HTML表单,咱们还可使用Djang提供的Form类来自动生成表单,并渲染到HTML中。
一、修改sandboxMP/apps/system/forms.py,加入以下内容:django

from django import forms class UserTestForm(forms.Form): username = forms.CharField(label='用户名', max_length=10) password = forms.CharField(label='密码'max_length=10) 

上面经过Form类定义了两个字段,max_length定义了输入字段的最大长度。
Form的实例具备一个is_valid()方法,能够对输入的字段进行验证,当调用这个方法时,若是全部字段输入都合法,它将返回True,并将表单的数据存放到cleaned_data属性中。json

1.2 视图处理

经过视图将定义好的表单数据进行实例化,实现以下功能:
一、若是访问视图的是一个GET请求,建立一个空的表单,并将它渲染到模板中
二、若是是POST请求提交表单,接收表单数据,并使用is_valid()方法进行验证
三、数据验证合法则执行正常业务逻辑,数据不合法则返回错误信息
修改sandboxMP/apps/system/tests.py,加入下面内容:后端

from django.shortcuts import render, HttpResponseRedirect from django.views.generic.base import View from .forms import UserTestForm class FormTestView(View): def get(self, request): test_form = UserTestForm() return render(request, 'system/users/form_test.html', {'test_form': test_form}) def post(self, request): test_form = UserTestForm(request.POST) ret = dict(test_form=test_form) if test_form.is_valid(): # form验证经过后,重定向到项目首页,因为项目IndexView限制登录访问了,若是系统没有登录,这个重定向会先跳到登录页面。 return HttpResponseRedirect('/') return render(request, 'system/users/form_test.html', ret) 

请注意:视图中只是为了演示Form类渲染和验证功能,只要输入数据合法即跳转到首页,并未对用户的登录进行认证。浏览器

1.3 URL配置

修改sandboxMP/sandboxMP/urls.py,添加Form类测视图访问的URL:服务器

from system.tests import FormTestView urlpatterns = [ '''原有内容省略''' path('form_test/', FormTestView.as_view()), ] 

1.4 模板的配置

新建模板:sandboxMP/templates/users/form_test.html,内容以下:架构

<form action="" method="post" novalidate> {% csrf_token %} {{ test_form }} <input type="submit" value="Submit" /> </form> 

运行项目,访问http://127.0.0.1:8000/form_test, 能够看到Django会根据模型类的字段和属性,在HTML中自动生成对应表单标签和标签属性。生成的标签会被放置到{{ test_form }}所在的位置。app

1.5 表单字段

除了上面演示的forms.CharField字段外,Django的表单内置了不少的表单字段,表单内建字段查询:https://docs.djangoproject.com/en/2.1/ref/forms/fields/

1.6 获取表单数据

经过表单提交的数据,一旦经过调用is_valid()成功验证,而后表单的数据将存放到form.cleaned_data字典中。固然,咱们依然能够从reques.POST中直接获取到未验证的数据。
一、修改sandboxMP/apps/system/tests.py,分别经过form.cleaned_data和request.POST来获取表单输入的数据:

class FormTestView(View): def get(self, request): test_form = UserTestForm() return render(request, 'system/users/form_test.html', {'test_form': test_form}) def post(self, request): test_form = UserTestForm(request.POST) ret = dict(test_form=test_form) ret['errors'] = test_form.errors.as_json() if test_form.is_valid(): # 经过form.cleaned_data获取经过表单验证的数据 username = test_form.cleaned_data['username'] password = test_form.cleaned_data['password'] # 依然能够经过request.POST来获取数据 username1= request.POST['username'] return HttpResponseRedirect('/') return render(request, 'system/users/form_test.html', ret) 

二、运行调试,参照下图进行运行调试:

- 在pycharm中开启debug模式 - 在form.is_valid()验证位置打上断点 - 打开浏览器访问http://127.0.0.1:8000/form_test - 在网页中输入用户名,密码,点击【Submit】提交表单数据 - 在pycharm中按F6进行程序调试,能够看到经过is_valid()验证后,能够经过clean_data来获取表单数据,一样也能够经过request.POST来获取表单数据 - 最后记得去掉debug断点 

善用debug调能够有效的查找、分析程序存在的问题。

1.7 其余

表单还支持手动渲染和渲染错误消息,本项目中不会用到表单的渲染功能,这部份内容再也不过多介绍,有兴趣的能够查阅官方文档。

二、模型表单ModelForm

2.1 使用ModelForm

在【Django实战1-权限管理功能实现-05:组织架构的添加】一节中咱们已经使用到了ModelForm, 经过ModelForm能够建立与Djang模型紧密映射的表单。ModelForm的优点在于,咱们已经在ORM中定义好了model模型,不用再写一个forms.Form类来一个一个定义表单中的字段。
。 例如:sandboxMP/apps/system/forms.py中的StructureForm:

from django import forms from .models import Structure class StructureForm(forms.ModelForm): class Meta: model = Structure fields = ['type', 'name', 'parent'] 

上面的例子中
一、建立一个类:StructureForm,它继承了forms.ModelForm;
二、在StructureForm中设置了元类Meta,设置了model属性关联到ORM模型中的Structure;
三、在Meta中设置了fields属性,定义在表单中使用的字段列表,列表里面的值是ORM模型Structure中的字段名。

2.2 ModelForm的字段选择

2.1中咱们经过ModelForm的fields属性,经过列表的形式,添加了要使用的字段。然而有的时候要使用的字段过多,能够将fields属性设置为__all__,将映射的模型中的所有字段都添加到表单中。

from django import forms from .models import Structure class StructureForm(forms.ModelForm): class Meta: model = Structure fields = '__all__' 

固然也可使用exclude属性排除某些字段,而后将剩下的字段做为表单字段。

from django import forms from .models import Structure class StructureForm(forms.ModelForm): class Meta: model = Structure exclude = ['parent', ] 

2.3 ModelForm的验证

与普通的表单验证相似,模型表单也能够调用is_valid()方法。

2.4 save()方法的使用

ModelForm有一个save()方法,这个方法根据表单绑定的数据建立并保存数据库对象。ModelForm的子类能够接受现有的模型实例做为关键字参数instance;若是提供实例,则save()将更新该实例。 若是没有提供,save() 将建立模型的一个新实例。
在【Django实战1-权限管理功能实现-05:组织架构的添加】一节中,咱们已经使用过ModelForm的save()方法。

# sandboxMP/apps/system/views_structure.py中 save()方法的使用 class StructureCreateView(LoginRequiredMixin, View): def get(self, request): ret = dict(structure_all=Structure.objects.all()) return render(request, 'system/structure/structure_create.html', ret) def post(self, request): res = dict(result=False) structure = Structure() structure_form = StructureForm(request.POST, instance=structure) if structure_form.is_valid(): # 表单提交的组织架构信息数据经过structure_form验证后,调用save()方法保存到数据库对象中。 structure_form.save() res['result'] = True return HttpResponse(json.dumps(res), content_type='application/json') 
相关文章
相关标签/搜索