有時我們需要使用get,post等方式在前台HTML頁面提交一些資料到後台處理例;
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Form</title> </head> <body> <p> <form action="url" method="post" enctype="multipart/form-data">{% csrf_token %} <input type="text" name="username"/> <input type="password" name="password"/> <input type="submit" value="submit"/> </form> </p> </body>
前端提交後台獲取:
from django.shortcuts import render,HttpResponse,redirect from app01 import models def Login(request): if request.method == "POST": username = request.POST.get("username") password = request.POST.get("password") return HttpResponse("Hello,%s"%(username))
這樣就完成了基本的功能,基本上可以用了。未依照要求(例如手機號要輸資料11位元長度,密碼的複雜度等),還有就是提交後再回來已經輸入的資料也會沒了
當然如果我們手動將輸入之後的資料在views 中都取得到再傳遞到網頁,這樣是可行的,但是很不方便,所以Django 提供了更簡單易用的forms 來解決驗證等這一系列的問題
,在這裡不得不提Django的插件庫真的很強大,簡單易擴展,上面的內容只是引進為什麼要使用form,下面著重記錄django form的使用
二.form表單驗證應用
需要在django的APP中新建一個模組form.py,具體內容如下
class RegisterForm(forms.Form): email = forms.EmailField(required=True, error_messages={'required': "邮箱不能为空"}) password = forms.CharField(max_length=120, min_length=6, required=True, error_messages={'required': "密码不能为空"}) invite_code = forms.CharField(required=True,error_messages={'required': "验证码不能为空"})
前端頁面
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>register</title> </head> <body> <p> <form action="url" method="post" enctype="multipart/form-data"> <input type="text" name="username"/> <input type="password" name="password"/> <input type="text" name="code"/> <input type="submit" value="submit"/> </form> </p> </body>
後台views處理
def register(request): if request.method == "POST": f = Reg_Form(request.POST) if f.is_valid(): user = f.cleaned_data["username"] pwd = f.cleaned_data["password"] code = f.cleaned_data["code"] res_code = request.session.get("code", None) result = models.UserInfo.objects.filter(userexact=user,pwdexact=pwd) if code.upper() == res_code.upper() and result: models.UserInfo.objects.filter(userexact=user).update(status=1) request.session["user"] = user return redirect("/home") else: return render(request, "register.html", {"error": f.errors, "form": f})else:return render(request, "register.html")
Reg_Form(request.POST) 使用form類別來處理提交的資料來驗證資料的合法性,is_valid()合法後的邏輯處理,驗證後的資料保存在實例化後返回的cleaned_data中,
cleaned_data是個字典的資料格式,
錯誤訊息保存在form.errors中比如說想在views中查看所有報錯資訊print(f.errors),如果只想在views中查看所有報錯資訊print(f.errors),如果只想看用戶的可以
print(form.errors['username'][0])
錯誤訊息我們可以透過模板渲染回前端頁面,例
<form action="/form/" method="POST"> {% csrf_token %} <p class="input-group"> {#接收后台传过来的form对象,自动生成input标签#} {{ form.user }} {#从后台传过来的error是字典,直接{{ error.user.0 }}呈现错误信息#} {#如果后台返回了错误信息,将错误信息放入span标签,在页面显示,否则不显示#} {% if error.username.0 %} <span>{{ error.userusername.0 }}</span> {% endif %} </p> <p class="input-group"> {{ form.password }} {% if error.pwd.0 %} <span>{{ error.password .0 }}</span> {% endif %} </p> <p> <input type="submit" value="提交" /> </p> </form>
三.自生成input框
Form類
class RegisterForm(forms.Form): style = 'form-control input-lg' phone = forms.CharField(widget=forms.TextInput(attrs={'class': style, 'name': 'title'})), required=True, error_messages={'required': ugettext_lazy('*Required')}) code = forms.CharField(widget=forms.NumberInput(attrs={'placeholder': '验证码', 'class': style}), min_length=4, max_length=4, required=True, error_messages={'required': ugettext_lazy('*Required')}) password = forms.CharField(widget=forms.PasswordInput(attrs={'placeholder': '请输入密码', 'class': style}), min_length=6, required=True, error_messages={'required': ugettext_lazy('*Required')})
views
def register(request): if request.method == "POST": f = RegisterForm(request.POST) if f.is_valid(): user = f.cleaned_data["username"] pwd = f.cleaned_data["password"] code = f.cleaned_data["code"] res_code = request.session.get("CheckCode", None) result = models.UserInfo.objects.filter(userexact=user,pwdexact=pwd) if code.upper() == res_code.upper() and result: models.UserInfo.objects.filter(userexact=user).update(status=1) request.session["user"] = user return redirect("/home") else: return render(request, "login.html", {"error": f.errors, "form": f}) else: return render(request, "login.html", {"error": f.errors, "form": f}) else: # 如果不是post提交数据,就不传参数创建对象,并将对象返回给前台,直接生成input标签,内容为空 f = Log_Form() return render(request, "login.html", {"form": f})
Form類
<body> <form action="/form/" method="POST"> {% csrf_token %} <p class="input-group"> {# 接收后台传过来的form对象,自动生成input标签#} {{ form.user }} {# 从后台传过来的error是字典,直接{{ error.user.0 }}呈现错误信息#} {# 如果后台返回了错误信息,将错误信息放入span标签,在页面显示,否则不显示#} <p class="input-group"> {{ form.email }} {% if error.email.0 %} <span>{{ error.email.0 }}</span> {% endif %} </p> <p class="input-group"> {{ form.password }} {% if error.password.0 %} <span>{{ error.password.0 }}</span> {% endif %} </p> <p class="input-group"> {{ form.code }} {% if error.book_type.0 %} <span>{{ error.code.0 }}</span> {% endif %} </p> <p> <input type="submit" value="提交" /> </p> </form> </body> </html>
Exception Value: argument of type 'NoneType' is not iterable.
可能是cleaned_data中某個欄位值應該是個列表,實際上卻是空值。 clean方法重寫時一定不要忘了return cleaned_data這樣重寫可以使用戶提交的資料在form類中執行檢測完後返回資料給用戶,資料合法後進行邏輯處理,不需要再進行處理返回用戶,更方便更合理補充:5.form的四種初始化方式①實例化oneform(initial={'onefield':value})②定義字段時給定值oneformfield = 初始化值CharField(initial=value)③重寫Form類別的init()方法:self.fields['onefield'].initial = value④當給form傳參在stanse(即oneform(instanse=onemodel_instance))時,前三種初始化方法會全部失效,即使重寫init時,先呼叫父類別的init再使用方法③,仍然無效(不是很爽)。 這時想重新初始化欄位值只能在init()裡 self.initial['title'] = value,直接對Form類別的initial屬性字典賦值。
from django import forms class RegisterForm(forms.Form): email = forms.EmailField(required=True, error_messages={'required': "邮箱不能为空"}) password = forms.CharField(max_length=120, min_length=6, required=True, error_messages={'required': "密码不能为空"}) invite_code = forms.CharField(required=True,error_messages={'required': "验证码不能为空"}) def clean(self): # 用户名 try: email = self.cleaned_data['email'] except Exception as e: raise forms.ValidationError(u"注册账号需为邮箱格式") # 验证邮箱 user = User.objects.filter(username=email) if user: # 邮箱已经被注册了 raise forms.ValidationError(u"邮箱已被注册") # 密码 try: password = self.cleaned_data['password'] except Exception as e: print('except: ' + str(e)) raise forms.ValidationError(u"请输入至少6位密码") return self.cleaned_data