2020-04-30--Django項(xiàng)目4-登錄功能的初步實(shí)現(xiàn)

static資源文件

首先把static文件夾粘貼到項(xiàng)目中,

注意一定要在pycharm中進(jìn)行粘貼,否則可能無效。

配置static資源文件

STATIC_URL = '/static/'          //在html頁面引用時(shí)要使用這個(gè)內(nèi)容

#添加:
#配置靜態(tài)資源
STATICFILES_DIRS = [
    os.path.join(BASE_DIR, 'static'),      //與目錄名稱相同
]                 

模板html

把index.html和login.html粘貼到templates文件夾下:


配置html與static資源文件關(guān)聯(lián)

打開index.html,按ctrl+r鍵,批量替換replace all代碼。
這是django自帶的路徑特性--- /static/***

./static        -->       /static

login.html同理替換。

顯示頁面

index.html

上一步我們關(guān)聯(lián)了html頁面和static靜態(tài)資源文件,
所以要先配置url和view,否則django不會(huì)識(shí)別關(guān)聯(lián)的路徑特性---/static/

(1)使用之前的方法

我們直接在MXOnline/urls.py下進(jìn)行配置:

from apps.users import views
#相比于django1.8,2.2版本的url配置相對(duì)簡(jiǎn)單。
path('',views.index),

編寫視圖view:
打開apps/user/views.py文件

def index(request):
    return render(request,'index.html')

啟動(dòng)項(xiàng)目:

127.0.0.1:8000
(2)使用新的方法

在django中為了開發(fā)方便,已經(jīng)有了為顯示模板的一些類,我們直接拿過來調(diào)用即可,不用再自定義視圖函數(shù)進(jìn)行顯示了。
打開MXOnline/urls.py:

from django.contrib import admin
from django.urls import path

import xadmin
from apps.users import views
#導(dǎo)入TemplatesView
from django.views.generic import TemplateView

urlpatterns = [
    path('admin/', admin.site.urls),
    path('xadmin/',xadmin.site.urls),
    #之前的方法
    # path('',views.index),
    #新的方法
    path('',TemplateView.as_view(template_name='index.html'),name='index')
]

再次啟動(dòng)項(xiàng)目,進(jìn)入127.0.0.1:8000:



一樣的效果。

login.html

login--登錄頁面也很特殊,網(wǎng)站中必備,所以django也自帶了一些類和方法供我們使用。
上一步中的index頁面,在右上角有一個(gè)的登錄按鈕,當(dāng)我點(diǎn)擊它時(shí),會(huì)出現(xiàn):


這是由于我們還沒有在url中進(jìn)行配置它。

(1)django自帶類及方法實(shí)現(xiàn)login頁面的顯示以及驗(yàn)證

打開index.html,修改登錄按鈕的跳轉(zhuǎn)url為:

#點(diǎn)擊登錄,會(huì)重新進(jìn)入url進(jìn)行匹配
<a href = '{% url 'login'  %}'>登錄</a>
配置url

打開MXOnline/urls.py:

#必須加name = '*****'否則會(huì)報(bào)login是無效的視圖函數(shù)等等。
path('login/',LoginView.as_view(),name = 'login)

所以我們給要加上name = ‘名稱’。


views

打開apps/users/views.py:

from django.shortcuts import render

#導(dǎo)入View
from django.views.generic.base import View

#login頁面的顯示以及表單提交的處理
class LoginView(View):
    #如果使用get,#點(diǎn)擊按鈕#,跳轉(zhuǎn)到login.html
    def get(self,request,*args,**kwargs):
        return render(request,'login.html')

當(dāng)啟動(dòng)項(xiàng)目時(shí),點(diǎn)擊右上角的登錄按鈕:




那么login.html頁面的顯示就成功了。

表單驗(yàn)證處理

首先要在login.html頁面中修改form表單的提交地址,我們還是提交到/login/中,但是,寫法要寫為:

{%  url 'login'  %}

提交地址的name為login,通過name到url中進(jìn)行匹配



在url中匹配后還是進(jìn)入LoginView.as_view()中。
因?yàn)閒orm表單是post提交,所以要在LoginView類中添加一個(gè)新的方法post()。

在這之前,django中內(nèi)置了一個(gè)用于防止大量不合法的登錄user的攻擊而設(shè)置的一個(gè)模塊forms.Form,所以我們?cè)趗serapp下新建一個(gè)文件form.py,用于書寫表單限制類LoginForm:

from django import forms

#用于防止大量不合理的用戶名和密碼進(jìn)行攻擊網(wǎng)站

class LoginForm(forms.Form):
    '''
    表單限制類:
        繼承于django內(nèi)置的表單認(rèn)證模塊forms.Form,
        當(dāng)用戶輸入的內(nèi)容不符合設(shè)置的要求時(shí),django內(nèi)置的form表單認(rèn)證會(huì)自動(dòng)阻擋,
        并且報(bào)出視圖函數(shù)沒有返回HttpResponse對(duì)象的異常(該異常頁面可在view視圖函數(shù)中進(jìn)行重新編輯)
        不會(huì)再到view的提交處理函數(shù)(LoginView.post)獲取數(shù)據(jù)。
    '''
    #設(shè)置用戶名必填,并且最小長(zhǎng)度為2
    username = forms.CharField(required=True,min_length=2)
    #密碼必填,并且最小長(zhǎng)度為3
    password = forms.CharField(required=True,min_length=3)

在apps/user/view.py中編寫表單提交的處理函數(shù):

from django.shortcuts import render

# Create your views here.

from django.views.generic.base import View      #View視圖
from django.http import HttpResponse,HttpResponseRedirect
from apps.users.form import LoginForm    #表單驗(yàn)證
from django.contrib.auth import authenticate,login   #用戶名或密碼認(rèn)證
from django.urls import reverse       #重定向參數(shù)
#login.html的顯示
class LoginView(View):
    #如果使用get,#點(diǎn)擊按鈕#,跳轉(zhuǎn)到login.html
    def get(self,request,*args,**kwargs):
        return render(request,'login.html')
    #如果使用的是post,#表單提交#,那么
    def post(self,request,*args,**kwargs):
        '''
        用戶登陸處理邏輯:
        (1).實(shí)例化form.py中的表單限制類,參數(shù)為(request.POST)
        (2).用戶輸入用戶名和密碼,首先進(jìn)入django內(nèi)置的合法限制類--form.py中的LoginForm類。
            不合法:默認(rèn)會(huì)報(bào)出視圖函數(shù)沒有返回HttpResponse對(duì)象的異常,我們?cè)谥茍D函數(shù)中重寫頁面,
                   如果不合法,那么重新返回login.html頁面,并攜帶不合法的數(shù)據(jù)。不再往下進(jìn)行。
            合法,通過--- 對(duì)象.cleaned_data['username/password']進(jìn)行獲取用戶輸入的數(shù)據(jù),往下將繼續(xù)進(jìn)行
        (3).django內(nèi)置表單驗(yàn)證模塊,用于驗(yàn)證用戶名和密碼的方法,有兩個(gè)參數(shù)username和password
            驗(yàn)證成功返回驗(yàn)證對(duì)象(數(shù)據(jù)庫中的對(duì)象),失敗則是None
        (4).判斷:
                如果返回的對(duì)象不為空:那么表示數(shù)據(jù)庫中有該對(duì)象,那么
                                    通過django內(nèi)置的表單登錄方法login(request,返回的對(duì)象),
                                    進(jìn)行登錄操作,并重定向到index頁面
                如果為空:那么表示數(shù)據(jù)庫中沒有該對(duì)象,
                         直接返回login.html重新登陸,
                         并攜帶msg(用戶名或密碼錯(cuò)誤)的提示信息,以及用戶不正確的數(shù)據(jù)信息。
        :param request:
        :param args:
        :param kwargs:
        :return:
        '''
        #實(shí)例化LoginForm
        login_form = LoginForm(request.POST)

        #如果login_form表單是合法的,則獲取,不合法直接阻擋。
        if login_form.is_valid():
            user_name = login_form.cleaned_data['username']
            pass_word = login_form.cleaned_data['password']

            #django內(nèi)置用于驗(yàn)證用戶名和密碼的方法,有兩個(gè)參數(shù)username和password
            #驗(yàn)證成功返回驗(yàn)證對(duì)象(數(shù)據(jù)庫中的對(duì)象),失敗則是None
            user = authenticate(username=user_name,password=pass_word)
            if user is not None:
                #登錄模塊,接受request和成功驗(yàn)證返回的user對(duì)象
                login(request,user)
                #返回重定向到index頁面,然后到url中進(jìn)行匹配
                return HttpResponseRedirect(reverse('index'))
            else:
                #如果沒有查詢到用戶,那么要求重新登陸,仍然返回login頁面
                return render(request,'login.html',{'msg':'用戶名密碼錯(cuò)誤','login_form':login_form})
        else:
            return render(request,'login.html',{'login_form':login_form})

msg--錯(cuò)誤信息,要在html頁面上顯示,所以要對(duì)login.html進(jìn)行修改渲染數(shù)據(jù)msg:



輸入錯(cuò)誤的用戶名或者密碼時(shí):msg會(huì)被渲染出來。


當(dāng)我們填寫正確的信息后,登陸成功,返回到index頁面,發(fā)現(xiàn)index頁面并沒有發(fā)生變化,還是要進(jìn)行登錄



那么這時(shí)候我們要再index頁面中進(jìn)行判斷:
如果登陸成功,那么頁面的一些元素要發(fā)生變化,比如:



那么打開index.html:
添加if語句即可完成

總結(jié):用戶輸入username和password,點(diǎn)擊立即登錄按鈕,會(huì)通過url的name屬性進(jìn)入到view視圖的表單類中(LoginView),因?yàn)槭莗ost請(qǐng)求,所以進(jìn)入post函數(shù)中,
首先會(huì)通過django的表單合法驗(yàn)證設(shè)置的標(biāo)準(zhǔn)看是否合法(合法性標(biāo)準(zhǔn)自定義,合法反饋頁面自定義)(合法驗(yàn)證模塊定義在user/form.py中)。
如果不合法,默認(rèn)會(huì)報(bào)出沒有返回HttpResponse對(duì)象的異常,但在這里返回login.html頁面,并攜帶不合法的信息。
如果合法,通過clean_data['username/password']獲取表單信息,然后使用django內(nèi)置的表單驗(yàn)證authenticate(username=,passsword=)進(jìn)行驗(yàn)證該用戶是否注冊(cè),返回一個(gè)user對(duì)象(數(shù)據(jù)庫中)。
如果user對(duì)象不為空,表示已注冊(cè),允許登錄使用login(request,user)進(jìn)行登錄操作,返回到index頁面,并且index頁面的某些元素會(huì)被替換。
如果user對(duì)象為空,那么表示填寫的信息不正確,直接返回login頁面,并攜帶msg(錯(cuò)誤提示)和錯(cuò)誤的表單信息。

最后提交GitHub。

使用之前的方法進(jìn)行登陸驗(yàn)證

復(fù)制index和login命名為index1和login1。
首先,配置url:

    path('index1/',views.index1,name = 'index1'),
    path('login1/',views.login1,name = 'login1'),

在index1.html中修改登錄按鈕的鏈接地址,修改為'login1':



在login1.html中修改form表單提交按鈕的提交地址也為'login1':



這樣兩個(gè)按鈕的提交地址通過name屬性匹配url,進(jìn)入view視圖的login():
#之前方法實(shí)現(xiàn)登錄驗(yàn)證
def index1(request):
    return render(request,'index1.html')

from apps.users.models import UserProfile
def login1(request):
    '''
    表單驗(yàn)證;
    如果是通過get方法進(jìn)行訪問,那么直接返回login1.html.
    如果使用post方法,那么表示是表單提交:
    (1).獲取用戶輸入的表單數(shù)據(jù)
    (2).首先從數(shù)據(jù)庫中查找用戶名為用戶輸入的用戶名的queryset對(duì)象(假設(shè)注冊(cè)時(shí)用戶名唯一,不重復(fù))
    (3).如果queryset對(duì)象存在,通過迭代取出對(duì)象中的密碼,(由于用戶名唯一,密碼也一定唯一)
        判斷用戶輸入的密碼是否于取出的密碼相等,
            如果相等:允許登錄,重定向index1頁面。
            不相等,返回login1.html,并且攜帶正確的username以及錯(cuò)誤提示信息。
    (4).如果queryset對(duì)象不存在,那么返回login.html,并攜帶錯(cuò)誤提示信息。

    :param request:
    :return:
    '''
    if request.method == 'GET':
        return render(request,'login1.html')
    if request.method == 'POST':
        #獲取表單數(shù)據(jù)
        username = request.POST.get('username')
        password = request.POST.get('password')

        #從數(shù)據(jù)庫中獲取用戶名為用戶輸入用戶名的queryset對(duì)象,(假設(shè)注冊(cè)時(shí)用戶名不能重復(fù),唯一的)
        users = UserProfile.objects.filter(username=username)

        if users.exists():           #判斷queryset對(duì)象中是否有數(shù)據(jù)

            passwordlist = []
            for user in users:
                passwordlist.append(user.password)       #通過迭代取出密碼

            if password in passwordlist:         #判斷密碼是否一致
                    return HttpResponseRedirect(reverse('index1'))
            else:
                return render(request,'login1.html',{'msg':'密碼錯(cuò)誤','username':username})
        else:
            return render(request, 'login1.html', {'msg': '用戶名不存在'})

在用戶名或密碼錯(cuò)誤時(shí),要對(duì)login1.html頁面進(jìn)行數(shù)據(jù)綁定



那么現(xiàn)在開始運(yùn)行項(xiàng)目;
127.0.0.1:8000/index1;



點(diǎn)擊右上角登錄按鈕,進(jìn)入login1頁面:

輸入錯(cuò)誤的username和password;



點(diǎn)擊立即登錄,出現(xiàn)錯(cuò)誤提示信息,不攜帶任何數(shù)據(jù)

輸入正確的username和錯(cuò)誤的password:

點(diǎn)擊立即登錄,保留了正確的username,出現(xiàn)了錯(cuò)誤提示信息

輸入正確的username和password:

點(diǎn)擊立即登錄,跳轉(zhuǎn)到index1頁面


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
禁止轉(zhuǎn)載,如需轉(zhuǎn)載請(qǐng)通過簡(jiǎn)信或評(píng)論聯(lián)系作者。

友情鏈接更多精彩內(nèi)容