在項目中咱們已經使用到Django Form和ModelForm的驗證功能,這一節我經過一些例子來了解更多Django表單的用法(本節代碼非項目代碼,測試完後既可刪除)。html
在【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 模板標籤
前面使用到的表單,是經過在模板中建立的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
經過視圖將定義好的表單數據進行實例化,實現以下功能:
一、若是訪問視圖的是一個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類渲染和驗證功能,只要輸入數據合法即跳轉到首頁,並未對用戶的登錄進行認證。瀏覽器
修改sandboxMP/sandboxMP/urls.py,添加Form類測視圖訪問的URL:服務器
from system.tests import FormTestView urlpatterns = [ '''原有內容省略''' path('form_test/', FormTestView.as_view()), ]
新建模板: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
除了上面演示的forms.CharField字段外,Django的表單內置了不少的表單字段,表單內建字段查詢:https://docs.djangoproject.com/en/2.1/ref/forms/fields/
經過表單提交的數據,一旦經過調用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調能夠有效的查找、分析程序存在的問題。
表單還支持手動渲染和渲染錯誤消息,本項目中不會用到表單的渲染功能,這部份內容再也不過多介紹,有興趣的能夠查閱官方文檔。
在【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.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', ]
與普通的表單驗證相似,模型表單也能夠調用is_valid()方法。
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')