03 用戶登陸的常見模塊和使用
next在登陸頁面的妙用
在用戶的登陸頁面判斷url中是否含有next參數,如果有則跳轉到,登陸前的url:
常用的是在登陸的LoginView處理函數中,把以下的代碼添加和修改局部的登陸函數:
# 判斷頁面url中是否有next參數, next = request.GET.get("next") # 如果有,則跳轉到next的url if next: return redirect(next) else: # 如果沒有,跳轉到主頁 return redirect(reverse("goods:index"))
完整代碼:
classView CodeLoginView(View): """登錄""" def get(self, request): """提供登錄頁面""" return render(request, "login.html") def post(self, request): """處理登錄的數據""" # 獲取參數 user_name = request.POST.get("username") password = request.POST.get("pwd") remembered= request.POST.get("remembered") # 記住用戶名的參數 # 參數校驗 if not all([user_name, password]): # 參數不完整 return render(request, "login.html") # 登錄業務邏輯處理 # try: # password = sha256(password) # User.objects.get(username=user_name, password=password)# except User.DoesNotExist: # return HttpResponse("用戶名或密碼錯誤") # 使用django的認證系統進行用戶密碼的校驗 user = authenticate(username=user_name, password=password) if user is None: # 用戶的登錄信息有誤 return render(request, "login.html", {"errmsg": "用戶名或密碼錯誤!"}) # 判斷用戶的激活狀態 if user.is_active is False: return render(request, "login.html", {"errmsg": "用戶尚未激活!"}) # 保存用戶的登錄狀態 # 使用django的login函數保存用戶的session數據 login(request, user) # 根據用戶勾選的記住用戶名選項,設置session數據的有效期(django幫助我們完成cookie有效期的設置) if remembered != "on": # 表示用戶沒有勾選 request.session.set_expiry(0) # 設置為臨時會話 else: # 表示用戶勾選 request.session.set_expiry(None) # 采用django的默認設置有效期 # 登錄成功, # 判斷頁面url中是否有next參數, next = request.GET.get("next") # 如果有,則跳轉到next的url if next: return redirect(next) else: # 如果沒有,跳轉到主頁 return redirect(reverse("goods:index"))
在下面的頁面中的url改為:
http://127.0.0.1:8000/users/login
用戶就跳轉到了登陸的頁面:
在用戶輸入完,用戶和密碼後會跳轉到原來的網頁:
====================================================================================================================
如何退出一個用戶
若要退出一個已經通過django.contrib.auth.login()登入的用戶,可以在你的視圖中使用django.contrib.auth.logout()。 它接收一個HttpRequest對象且沒有返回值
定義退出是請求的處理函數:
from django.contrib.auth import authenticate, login, logout class LogoutView(View): """退出""" def get(self, request): # 使用django的認證系統提供的logout函數,清除session數據 logout(request) # 跳轉到主頁 return redirect(reverse("goods:index"))
定義退出的請求路徑:
url(r‘^logout$‘, views.LogoutView.as_view(), name="logout"),
在任一個登陸過的頁面都有登陸過的session信息,如下圖:
在上面途中的地址欄中填寫退出登陸的url:
http://127.0.0.1:8000/users/logout
session清除掉了,並且重定向到了指定的網頁
=============================================================================================================
只允許登錄的用戶訪問
login_required 裝飾器,login_required([redirect_field_name=REDIRECT_FIELD_NAME, login_url=None])
作為一個快捷方式,你可以使用便捷的login_required()裝飾器:
from django.contrib.auth.decorators import login_required
@login_required(redirect_field_name=‘my_redirect_field‘)
def my_view(request):
...
login_required()完成下面的事情:
- 如果用戶沒有登入,則重定向到settings.LOGIN_URL,並將當前訪問的絕對路徑傳遞到查詢字符串中。例如:/accounts/login/?next=/polls/3/。
- 如果用戶已經登入,則正常執行視圖。視圖的代碼可以安全地假設用戶已經登入。
默認情況下,在成功認證後用戶應該被重定向的路徑存儲在查詢字符串的一個叫做"next"的參數中。如果對該參數你傾向使用一個不同的名字,login_required()帶有一個可選的redirect_field_name參數:
Django認證系統文檔:http://python.usyiyi.cn/documents/django_182/topics/auth/default.html
自定義一個給所有只允許登陸過的用戶訪問的基類,在utils包中創建文件views.py
因為我用的到時類視圖,所以我重構了as_view方法,用login_required裝飾as_view編寫如下的代碼:,
from django.contrib.auth.decorators import login_required class LoginRequiredMixin(object): """要求用戶登錄的功能補充邏輯""" @classmethod def as_view(cls, **initkwargs): view = super(LoginRequiredMixin, cls).as_view(**initkwargs) # 實際上就是調用的django提供的類視圖基類的as_view return login_required(view)
定義地址信息的請求處理函數,並且只有登陸過的用戶才可以訪問,導入自定義的限制訪問的基類 from utils.views import LoginRequiredMixin
from utils.views import LoginRequiredMixin class AddressView(LoginRequiredMixin, View): """用戶地址""" return render(request, "user_center_site.html", context)
在應用users中添加地址信息的url
url(r‘^address$‘, views.AddressView.as_view(), name="address"),
在配置文件中,用戶沒有登陸重定向的頁面:
LOGIN_URL = ‘/users/login‘
沒登陸的用來直接訪問返回到登陸的頁面
http://127.0.0.1:8000/users/address
用戶登陸後在地址欄中輸入:
http://127.0.0.1:8000/users/address
顯示的頁面如下:
在Address中get 方法中給傳用戶的地址信息進行渲染,request請求中包含了用戶的信息,我們可以直接調用request.user獲取當前的對象user
通過當前的user表查到最新的地址信息表user.address_set.latest("create_time")
class AddressView(LoginRequiredMixin, View): """用戶地址""" def get(self, request): """提供用戶地址頁面""" user = request.user #登錄的用戶對象 # 獲取用戶的地址信息,按照創建時間選擇最新的一條 try: address = user.address_set.latest("create_time") except Address.DoesNotExist: address = None context = { # "user": user, # 這個數據可以不用傳,在的django中可以直接使用 "address": address } # 渲染模板 return render(request, "user_center_site.html", context)
在Address中post方法中讓用戶修改最新的地址信息進行渲染:
def post(self, request): """維護地址信息""" user = request.user recv_name = request.POST.get("recv_name") addr = request.POST.get("addr") zip_code = request.POST.get("zip_code") recv_mobile = request.POST.get("recv_mobile") if all([recv_name, addr, zip_code, recv_mobile]): # address = Address( # user=user, # receiver_name=recv_name, # detail_addr=addr, # zip_code=zip_code, # receiver_mobile=recv_mobile # ) # address.save() Address.objects.create( user=user, receiver_name=recv_name, detail_addr=addr, zip_code=zip_code, receiver_mobile=recv_mobile ) return redirect(reverse("users:address"))
隨便填寫提交的返回頁面如下:
03 用戶登陸的常見模塊和使用