最初開始搞用戶登錄驗證的時候感覺沒什么難的,不就是增刪改查中的查詢數據庫么,但是還是遇到許多小問題,而且感覺在查詢數據庫的時候,要把前端的數據一條一條的進行比對,會導致我的代碼很丑,而且方式很不智,所以進行了一些優化。
除此之外,我還加入了驗證碼的功能,同時使用form表單驗證,功能應該是大致完善了。
check_code.py:

#!/usr/bin/python from PIL import Image,ImageDraw,ImageFont,ImageFilter import random import string ttf='C:\Windows\Fonts' def getCheckChar(): ran=string.ascii_letters+string.digits #ascii_letters 生成隨機字母(大小寫),digits生成數字 check_char='' for i in range(4): check_char+=random.choice(ran) print(check_char) return check_char def getImg(code): img=Image.new('RGB',(120,30),(255,255,255)) draw=ImageDraw.Draw(img) font = ImageFont.truetype('C:\Windows\Fonts\Monaco.ttf', 18) code=code color=random.randint(50, 150), random.randint(50, 150), random.randint(50, 150) for t in range(4): draw.text((28*t,0),code[t],color,font) # draw.text((60,0),code,color,font) #干擾點 chance=min(100, max(0, int(2))) for w in range(120): for h in range(30): tmp = random.randint(0, 100) if tmp > 100 - chance: draw.point((w, h), fill=(0, 0, 0)) #干擾線 for i in range(3): # 起始點 begin = (random.randint(0, 120), random.randint(0, 30)) # 結束點 end = (random.randint(0, 120), random.randint(0, 30)) draw.line([begin, end], fill=(0, 0, 0)) #圖形扭曲參數 params = [1 - float(random.randint(1, 2)) / 100, 0, 0, 0, 1 - float(random.randint(1, 10)) / 100, float(random.randint(1, 2)) / 500, 0.001, float(random.randint(1, 2)) / 500 ] img = img.transform((120,30), Image.PERSPECTIVE,params, Image.BILINEAR) img=img.filter(ImageFilter.EDGE_ENHANCE_MORE) # img.save(''.join(code)+'.jpg','jpeg') return img if __name__ == '__main__': code=getCheckChar() getImg(code)
這個py文件我單獨的寫出來了,和views.py在同一目錄下,作用是生成驗證碼,包括字符串和圖片,要import的模塊是pillow,對應的PIL
tty是字體文件,我用的是 Monaco.ttf ,自己下載的,注意要對應好它所在的位置
保存的話,如果你想單獨用保存可以使用save方法保存,在views里我直接將圖片保存在了內存里。
其他的都是pillow的正常操作了,什么大小啦濾鏡啦,不贅述了。
views.py:
from django.shortcuts import render,HttpResponse,redirect from EMsystem import models from EMsystem import check_code from io import BytesIO def getcheck_code(request): code = check_code.getCheckChar() img = check_code.getImg(code) f = BytesIO() img.save(f, 'PNG') request.session['check_code']=code return HttpResponse(f.getvalue()) from django import forms from django.forms import fields #上傳文件用 class FM(forms.Form): #這里要接受后端需要的,不需要的數據不會關注 teacher_id=forms.CharField(error_messages={'required':"不能為空"}) #表單中的name要與變量名一樣 password=forms.CharField( min_length=5, error_messages={'required':"不能為空", 'min_length':'密碼長度不小於5',}, ) def login_page(request): if request.method=="GET": return render(request,'login.html') if request.method=='POST': obj=FM(request.POST) if obj.is_valid(): print(obj.cleaned_data) check_dic=models.teacher_list.objects.filter(**obj.cleaned_data).first() if check_dic is None: return render(request,'login.html') else: checkcode=request.POST.get('checkcode') if checkcode.upper()==request.session['check_code'].upper(): request.session['userid']=obj.cleaned_data['teacher_id'] request.session['is_login']=True return render(request,'welcome.html') else: return render(request, 'login.html', {'err_checkcode': "驗證碼錯誤"}) else: return render(request,'login.html',{'obj':obj}) def welcome(request): if request.session.get('is_login',None): return render(request,'welcome.html') else: return redirect('/login/')
視圖函數里寫了四個函數:
getcheck_code:作用是生成驗證碼,同時保存到session中,圖片保存到內存里並以HttpResponse提交到前端。
FM:作用是表單驗證,這是django自帶的form操作,用於檢驗前端的數據格式是否正確(前面的博文有介紹)。
login_page:作用是驗證數據庫和session中的驗證碼,這里直接使用了form的兩個方法:
is_valid:檢驗字段是否正確
cleaned_data:將正確的結果以字典的形式返回
拿到cleaned_data之后直接懟到數據庫里面filter一下,看是否為空,如果為空說明用戶名密碼不匹配,否則驗證成功
check_dic=models.teacher_list.objects.filter(**obj.cleaned_data).first()
注意如果遇到session報 " KeyError "的問題就在terminal里執行以下兩條命令,然后重啟服務就可以了:
python manage.py makemigrations
python manage.py migrate
welcome:驗證通過后訪問的主頁,如果直接訪問該頁面的話,會先檢查is_login這個session是否為True(有關session的使用方法在前面的博文里)
驗證成功之后返回welcome.html
HTML:
login.html:

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="login.html" method="POST"> {% csrf_token %} <p>username: <input type="text" name="teacher_id">{{ obj.errors.userid.0}}</p> <p>password:<input type="password" name="password">{{ obj.errors.password.0 }}<p> <p> 驗證碼: <input type="text" name="checkcode">{{ err_checkcode }} <span> <img src="/checkcode.html" onclick="chageCheckcode(this)"> </span> </p> <input type="submit" value="login"> </form> <script src="/static/jquery-1.12.4.js"></script> <script> function chageCheckcode(ths) { console.log(ths.src) ths.src=ths.src+'?' } </script> </body> </html>
urls.py:
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^welcome/',views.welcome),
url(r'^login/',views.login_page),
url(r'^checkcode.html$',views.getcheck_code),
]
這樣就實現了登錄認證功能