Django(三)
一、Form表單
?
在實際的生產環境中比如登錄和驗證的時候,我們一般都使用Jquery+ajax來判斷用戶的輸入是否為空,假如JS被禁用的話,咱們這個認證屏障是不是就消失了呢?(雖然一般不會禁用掉但是還是存在風險)所以我們一般做兩種認證一種是前端做一遍認證,在后端做一遍認證。
如果前端中要涉及到很多input,提交到后臺,后臺要一一取出,分別做驗證,這是件很痛苦的事。
def register(request):if request.method == "POST":ret = {"status":False,"msg":""}u = request.POST.get('user',None)e = request.POST.get('email',None)p = request.POST.get('password',None)p2 = request.POST.get('password2',None)#這里有個問題,如果,這個from表單有20個input,你在這里是不是的取20次?count = models.UserInfo.objects.filter(user=u).count()if count == 0:if p == p2:print("注冊成功")models.UserInfo.objects.create(user=u, email=e, password=p)data_list = models.UserInfo.objects.all()ret["status"] = Trueret["msg"] = "注冊成功,請登錄"return HttpResponse(json.dumps(ret))# return redirect('/index/')else:print('diff')ret["msg"] = "兩次輸入密碼不一致"return HttpResponse(json.dumps(ret))elif len(u) > 0 and count >= 1:print('用戶名已經存在' )ret["msg"] = "用戶名已經存在"return HttpResponse(json.dumps(ret))else:return render( request, 'cmdb/register.html', )#驗證:#輸入不能為空,并且有的可以為空有的不可以為空#如果email = xxxx 這樣合法嗎'''你在這里是不是需要做一大堆的輸入驗證啊?并且有很多這種頁面會存在這種情況,如果每個函數都這樣做估計就累死了'''if request.method == 'GET':return render( request, 'cmdb/register.html', ) 在樣能解決這個問題呢?通過Django的form來實現,其他語言也有叫做(模型綁定)
Django的form的作用:
1、生成html標簽
2、用來做用戶提交的驗證
1、生成html標簽
views
from django import forms
class LoginForm(forms.Form):user = forms.CharField(required=True, error_messages={'required': '用戶名不能為空.'})pwd = forms.CharField(required=True,min_length=6,max_length=10,error_messages={'required': '密碼不能為空.', 'min_length': "至少6位"})num = forms.IntegerField(error_messages={'required': '數字不能空.','invalid': '必須輸入數字'})phone = forms.CharField(validators=[mobile_validate, ],)test = forms.CharField(widget=forms.Textarea(attrs={'class': 'c1'}))def login(request):if request.POST:objPost = LoginForm(request.POST)ret = objPost.is_valid()# print(objPost)print(ret)if ret:print(objPost.clean())else:from django.forms.utils import ErrorDict#print(type(obj.errors),obj.errors.as_json())# obj1.errorsprint(objPost.errors.as_json())return render(request, 'login.html',{'obj1': objPost})else:objGet = LoginForm()return render(request, 'login.html',{'obj1': objGet}) ?
html
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title><style>.error-msg{color: red;}</style>
</head>
</head>
<body><form action="/app01/login/" method="POST"><div><div>{{ obj1.user }}{% if obj1.errors.user %}<span class="error-msg">{{ obj1.errors.user.0 }}</span>{% endif %}</div><div>{{ obj1.pwd }}<span class="error-msg">{{ obj1.errors.pwd.0 }}</span></div><div>{{ obj1.num }}<span class="error-msg">{{ obj1.errors.num.0 }}</span></div><div>{{ obj1.phone }}<span class="error-msg">{{ obj1.errors.phone.0 }}</span></div><div>{{ obj1.test }}<span class="error-msg">{{ obj1.errors.test.0 }}</span></div><input type="submit" value="提交"></div></form>
</body>
</html> ?2、簡單的form表單驗證用戶輸入的內容
def login(request):if request.POST:#獲取用戶輸入一句話就搞定objPost = LoginForm(request.POST)'''咱們把post過來的數據當參數傳給LoginForm咱們定義的這個類,LoginForm會自動會去你提交的數據user/pwd/num/phone 自動的封裝到objPost里,封裝到這個對象里我們就可以判斷輸入是否合法'''ret = objPost.is_valid()# print(objPost)print(ret)if ret:print(objPost.clean())else:from django.forms.utils import ErrorDict#print(type(obj.errors),obj.errors.as_json())# obj1.errorsprint(objPost.errors.as_json())return render(request, 'login.html',{'obj1': objPost})#然后把對象傳給htmlelse:objGet = LoginForm() #創建了這個對象return render(request, 'login.html',{'obj1': objGet})
from django.views.decorators.csrf import csrf_exempt,csrf_protect ?
當我們輸入不合法的時候,(在創建類設置的需求)為空、或者不是email格式的時候!
這樣在后端我們是不是就有一套驗證的機制?就可以通過is_valid()來判斷用戶輸入是否合法!如果不合法就把返回信息發送過去,如果合法獲取數據操作即可!
捕獲錯誤信息并返回
from django import formsclass LoginForm(forms.Form):user = forms.CharField(required=True, error_messages={'required': '用戶名不能為空.'})pwd = forms.CharField(required=True,min_length=6,max_length=10,error_messages={'required': '密碼不能為空.', 'min_length': "至少6位"})num = forms.IntegerField(error_messages={'required': '數字不能空.','invalid': '必須輸入數字'})phone = forms.CharField(validators=[mobile_validate, ],)test = forms.CharField(widget=forms.Textarea(attrs={'class': 'c1'})) def login(request):
if request.POST:
#獲取用戶輸入一句話就搞定
objPost = LoginForm(request.POST)
'''
咱們把post過來的數據當參數傳給LoginForm咱們定義的這個類,LoginForm會自動會去你提交的數據
user/pwd/num/phone 自動的封裝到objPost里,封裝到這個對象里我們就可以判斷輸入是否合法
'''
ret = objPost.is_valid()
# print(objPost)
print(ret)
if ret:
print(objPost.clean())
#通過驗證,獲取提交的數據
'''
{'user': 'asfd', 'num': 1, 'pwd': 'dsafss', 'test': '32', 'phone': '13331525685'}
'''
else:
from django.forms.utils import ErrorDict
#print(type(obj.errors),obj.errors.as_json())
# obj1.errors
print(objPost.errors)
'''
<ul class="errorlist"><li>phone<ul class="errorlist"><li>手機號碼格式錯誤</li></ul></li></ul>
'''
return render(request, 'login.html',{'obj1': objPost})#然后把對象傳給html,在把錯誤信息傳遞過去
else:
objGet = LoginForm() #創建了這個對象
return render(request, 'login.html',{'obj1': objGet})#然后把對象傳給html
?
html標簽,使用 login 中定義的obj1 對應的errors輸出
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title><style>.error-msg{color: red;}</style>
</head>
</head>
<body><form action="/app01/login/" method="POST"><div><div>{{ obj1.user }}{% if obj1.errors.user %}<span class="error-msg">{{ obj1.errors.user.0 }}</span>{% endif %}</div><div>{{ obj1.pwd }}<span class="error-msg">{{ obj1.errors.pwd.0 }}</span></div><div>{{ obj1.num }}<span class="error-msg">{{ obj1.errors.num.0 }}</span></div><div>{{ obj1.phone }}<span class="error-msg">{{ obj1.errors.phone.0 }}</span></div><div>{{ obj1.test }}<span class="error-msg">{{ obj1.errors.test.0 }}</span></div><input type="submit" value="提交"></div></form>
</body>
</html> 這樣如果,我都按照要求提交,就可以取到數據了?這樣咱們就不用自己去拿數據是
| 1 | {'user': 'asfd', 'num': 1, 'pwd': 'dsafss', 'test': '32', 'phone': '13331525685'} |
?3、form表單定制化
3.1、自定義報錯內容
在form里有一個參數:error_messages ?在他這里就可以定義報錯內容
class UserInfo(forms.Form):email = forms.EmailField(required=True,error_messages={'required':u'郵箱不能為空'}) #required是否可以為空,如果為False說明可以為空host = forms.CharField(error_messages={'required':u'主機不能為空'}) #如果required不寫默認為Tureport = forms.CharField(error_messages={'required':u'端口不能為空'})mobile = forms.CharField(error_messages={'required':u'手機不能為空'},widget=forms.TextInput(attrs={'class':'form-control','placeholder':u'手機號碼'})#給input添加屬性#這里默認是TextInput,標簽) 效果:
3.2給userinfo增加一個備注
class UserInfo(forms.Form):email = forms.EmailField(required=True,error_messages={'required':u'郵箱不能為空'}) #required是否可以為空,如果為False說明可以為空host = forms.CharField(error_messages={'required':u'主機不能為空'}) #如果required不寫默認為Tureport = forms.CharField(error_messages={'required':u'端口不能為空'})#默認mobile里有一個默認為空的機制,我們在原有的參數里增加怎們自定義的方法mobile = forms.CharField(validators=[mobile_validate,],#應用咱們自己定義的規則error_messages={'required':u'手機不能為空'},widget=forms.TextInput(attrs={'class':'form-control','placeholder':u'手機號碼'})#這里默認是TextInput,標簽)#咱們在新增一個備注memo = forms.CharField(required=False,widget=forms.Textarea(attrs={'class':'form-control','placeholder':u'備注'})) 效果如下:
3.3?生成select標簽
class UserInfo(forms.Form):email = forms.EmailField(required=True,error_messages={'required':u'郵箱不能為空'}) #required是否可以為空,如果為False說明可以為空host = forms.CharField(error_messages={'required':u'主機不能為空'}) #如果required不寫默認為Tureport = forms.CharField(error_messages={'required':u'端口不能為空'})#默認mobile里有一個默認為空的機制,我們在原有的參數里增加怎們自定義的方法mobile = forms.CharField(validators=[mobile_validate,],#應用咱們自己定義的規則error_messages={'required':u'手機不能為空'},widget=forms.TextInput(attrs={'class':'form-control','placeholder':u'手機號碼'})#這里默認是TextInput,標簽)#咱們在新增一個備注memo = forms.CharField(required=False,widget=forms.Textarea(attrs={'class':'form-control','placeholder':u'備注'}))user_type_choice = ((0, u'普通用戶'),(1, u'高級用戶'),)user_type = forms.IntegerField(widget=forms.widgets.Select(choices=user_type_choice,attrs={'class':'form-control'})) ?
3.4、關于后端驗證
這個后端驗證是必須要有驗證機制的,前端可以不寫但是后端必須要寫!前端的JS是可以被禁用掉到。
3.5 Django 優化錯誤信息顯示
設置顯示error的樣式
error_msg = user_input_obj.errors.as_data()#這里原來什么都沒寫,默認是ul的樣式,默認是as_ul(),如果我們寫成as_data()返回的就是一個原生的字符串#還有一個as_json
?
實例:
import re
from django import forms
from django.core.exceptions import ValidationError#自定義方法
def mobile_validate(value):mobile_re = re.compile(r'^(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$') #正則匹配if not mobile_re.match(value):raise ValidationError('手機號碼格式錯誤') #如果沒有匹配到主動出發一個錯誤class UserInfo(forms.Form):user_type_choice = ((0, u'普通用戶'),(1, u'高級用戶'),)user_type = forms.IntegerField(widget=forms.widgets.Select(choices=user_type_choice,attrs={'class':'form-control'}))email = forms.EmailField(required=True,error_messages={'required':u'郵箱不能為空'}) #required是否可以為空,如果為False說明可以為空host = forms.CharField(error_messages={'required':u'主機不能為空'}) #如果required不寫默認為Tureport = forms.CharField(error_messages={'required':u'端口不能為空'})#默認mobile里有一個默認為空的機制,我們在原有的參數里增加怎們自定義的方法mobile = forms.CharField(validators=[mobile_validate,],#應用咱們自己定義的規則error_messages={'required':u'手機不能為空'},widget=forms.TextInput(attrs={'class':'form-control','placeholder':u'手機號碼'})#這里默認是TextInput,標簽)#咱們在新增一個備注memo = forms.CharField(required=False,widget=forms.Textarea(attrs={'class':'form-control','placeholder':u'備注'})) def user_list(request):
obj = UserInfo() #創建了這個對象
if request.method == 'POST':
#獲取用戶輸入一句話就搞定
user_input_obj = UserInfo(request.POST)
if user_input_obj.is_valid(): #判斷用戶輸入是否合法
data = user_input_obj.clean() #獲取用戶輸入
print(data)
else:
#如果發生錯誤,捕捉錯誤
error_msg = user_input_obj.errors.as_data()#這里原來什么都沒寫,默認是ul的樣式,默認是as_ul(),如果我們寫成as_data()返回的就是一個原生的字符串
#還有一個as_json
print(error_msg) #打印一下然后看下他的類型
#然后把錯誤信息返回
return render(request,'user_list.html',{'obj':obj,'errors':error_msg,})#然后把對象傳給html,在把錯誤信息傳遞過去
return render(request,'user_list.html',{'obj':obj,})#然后把對象傳給html
?
?
html
{% load mytag %}<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Shuai</title>
</head>
<body><form action="/app01/user_list/" method="post"><p>用戶類型:{{ obj.user_type }}<span>{% error_message errors.user_type %}</span></p><p>主機:{{ obj.host }}<span>{% errors.host %}</span></p><p>端口:{{ obj.port }}<span>{% error_message errors.port %}</span></p><p>郵箱:{{ obj.email }}<span>{% error_message errors.email %}</span></p><p>手機:{{ obj.mobile }}<span>{% error_message errors.mobile %}</span></p><p>備注:{{ obj.memo }}<span>{% error_message errors.memo %}</span></p><input type="submit" value="submit"/></form>
</body>
</html>? ?
?
?
?
二、CSRF 跨站請求
?
viwes.py
from django.views.decorators.csrf import csrf_exempt,csrf_protect @csrf_exempt def csrf(request):return render(request,'csrf.html')
?
csrf.html
<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title></title> </head> <body><form action="/csrf/" method="post">{% csrf_token %}<input type="text" name="v" /><input type="submit" value="提交" /></form><input type="button" value="Ajax提交" οnclick="DoAjax();" /><script src="/static/jquery-2.1.4.min.js"></script><script src="/static/jquery.cookie.js"></script><script>// 去cookie中獲取值var csrftoken = $.cookie('csrftoken');function csrfSafeMethod(method) {// these HTTP methods do not require CSRF protectionreturn (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));}$.ajaxSetup({ #用于ajax請求綁定cookiebeforeSend: function(xhr, settings) {if (!csrfSafeMethod(settings.type) && !this.crossDomain) {xhr.setRequestHeader("X-CSRFToken", csrftoken);}}});function DoAjax(){$.ajax({url: '/csrf/',type: 'POST',data: {'k1': 'v1'},success: function (data) {console.log(data);}})}</script></body> </html>
?
?
三、cookie?
?1.cookie設置
viwes.py
def cookie(request):print(request.COOKIES)obj = render(request, 'cookie.html')obj.set_cookie('k3','v3',path='/cookie/') #瀏覽器設置cookiereturn obj
?
?
?
?
?
?
?
2.cookie登陸(cookie內容可以串改,登陸不使用cookie登陸,cookie一般保存不敏感的信息)
viwes.py?
def log(request):if request.method == 'POST':u = request.POST.get('user')p = request.POST.get('pwd')if u == 'alex' and p == '123':print(u)red = redirect('/index/')red.set_cookie('username', u)return redelse:return render(request, 'log.html')else:return render(request, 'log.html')
?
?
log.html
<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title></title> </head> <body><form action="/log/" method="POST"><input type="text" name="user"><input type="text" name="pwd"><input type="submit" value="提交" /></form> </body> </html>
?
?
四、session登陸
viwes.py
USER_LIST = ['alex','eric','wangminglong', 'hu']def session_login(request):if request.method == 'POST':u = request.POST.get('user')p = request.POST.get('pwd')if p == '123' and u in USER_LIST:request.session['user'] = ureturn redirect('/session_index/')return render(request,'session_login.html')""" def session_index(request):user = request.session.get('user',None)if not user:return redirect('/session_login/')else:return render(request,'session_index.html',{'user': user}) """ def auth(func):def inner(request, *args,**kwargs):# print(request,args,kwargs)user = request.session.get('user', None)print(user)if not user:return redirect('/session_login/')return func(request, *args,**kwargs)return inner@auth def session_index(request):user = request.session.get('user', None)return render(request,'session_index.html',{'user': user})@auth def session_logout(request):del request.session['user']return redirect('/session_login/')
?
session_login.html
<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title></title> </head> <body><h1>歡迎:{{ user }}登錄</h1><a href="/session_logout/">注銷</a> </body> </html>
?
session_index.html
<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title></title> </head> <body><form action="/session_login/" method="POST"><input type="text" name="user"><input type="text" name="pwd"><input type="submit" value="提交" /></form> </body> </html>
?
?
顯示 登陸成功后
?數據自動實現?
?
轉載于:https://www.cnblogs.com/wudalang/p/5872389.html
總結
- 上一篇: 现在煤气多少钱一公斤?
- 下一篇: 登陆问题