如何使用Django實現用戶登錄驗證


  最初開始搞用戶登錄驗證的時候感覺沒什么難的,不就是增刪改查中的查詢數據庫么,但是還是遇到許多小問題,而且感覺在查詢數據庫的時候,要把前端的數據一條一條的進行比對,會導致我的代碼很丑,而且方式很不智,所以進行了一些優化。

  除此之外,我還加入了驗證碼的功能,同時使用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)
View 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>
View Code

 

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),
]

這樣就實現了登錄認證功能


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM