Django auth組件

Django auth

   Django中的auth組件非常適合高效開發,它會用自帶的auth_user表來記錄用戶相關的數據。

   並且提供了一整套服務,包括判斷用戶是否登錄,session限制頁面訪問,創建用戶,註銷用戶等等。

   通過以下程式碼即可導入auth組件。

from django.contrib import auth

   使用auth組件前,一定要切記生成物理表。

python manage.py migrate

   此外,注意一點:auth表中的數據和admin後台管理是相通的。

   我們可以看一下這張表中的欄位資訊。

id 				主鍵
username		用戶名
password 		密碼(sha256加密)
last_login		上次登錄時間
is_superuser	是否是管理員
first_name		姓
last_name		名
email			郵箱地址
is_staff		是否是工作人員
is_activ		是否激活
date_joined		加入日期

登錄相關

authenticate

   驗證用戶名及密碼是否正確,最少兩個參數,即usernamepassword

   返回值是一條記錄對象,並且該對象上會設置一個屬性來標識該用戶已經通過認證。

user_obj = auth.authenticate(request,username=username,password=password) # request選填

login

   該方法能夠將authenticate()返回的用戶對象存入至request對象中,通過request.user即可調用出當前對象。

   並且該方法還會自動生成一個session保存至session表中。

   只要使用login(request, user_obj)之後,request.user就能拿到當前登錄的用戶對象。

   否則request.user得到的是一個匿名用戶對象(AnonymousUser Object)。

class Login(View):
    def get(self, request):
        return render(request, "login.html")

    def post(self, request):
        username = request.POST.get("username")
        password = request.POST.get("password")
        user_obj = auth.authenticate(
            username=username, password=password)  # 拿到用戶記錄對象
        if user_obj:
            auth.login(request, user_obj)  # 封裝對象至request中,並且添加session
            return redirect("/index/")
        else:
            return redirect("/register/")  # 跳轉到註冊頁面

logout

   該方法接受一個HttpRequest對象,無返回值。

   當調用該函數時,當前請求的session資訊會全部清除。該用戶即使沒有登錄,使用該函數也不會報錯。

class Logout(View):
    def get(self, request):
        auth.logout(request) # 清除session
        return HttpResponse("清除成功")

is_authenticated

   該方法判斷用戶是否進行登錄,返回布爾值。

    {% if request.user.is_authenticated %}  <!-- 前端不需要加括弧 -->
      <a class="btn btn-default" href="{% url 'edit_password' %}'" role="button">修改{{request.user.username}}密碼</a>
    {% endif %}

login_requierd

   auth組件給我們提供的一個裝飾器工具,用來快捷的給某個視圖添加登錄校驗。

   需要先導入該裝飾器:

from django.contrib.auth.decorators import login_required

   使用方法:單獨指定跳轉的視圖函數

@method_decorator(login_required(login_url='/login/'),name="dispatch")
class Logout(View):
    def get(self, request):
        auth.logout(request) # 清除session
        return HttpResponse("清除成功")

   或者你也可以使用全局配置,讓他自動跳轉到某一功能下。

   局部裝飾器跳轉比全局跳轉優先順序要高

LOGIN_URL = '/login/'  # 這裡配置成你項目登錄頁面的路由

註冊相關

create_user

   創建一個普通用戶。需要提供必要參數(username、password)等

   注意:我們要先導入auth_user表才行,此外,所有創建用戶等密碼都是密文。

from django.contrib.auth.models import User

class Register(View):

    def get(self, request):
        return render(request, "register.html")

    def post(self, request):
        username = request.POST.get("username")
        password = request.POST.get("password")
        repeat_password = request.POST.get("repeat-password")
        if repeat_password == password:
            if User.objects.filter(username="username").exists():  # 如果表中不存在該數據時
                User.objects.create_user(
                    username = username,
                    password = password,
                )
                return redirect("/index/")

            else:
                return HttpResponse("用戶已存在")
        else:
            return HttpResponse("密碼不一致,請重新輸入")

create_superuser

   創建一個超級用戶。需要提供必要參數(username、password、email)等

   注意:創建超級用戶一般會使用命令行創建,不要使用程式碼進行創建。

from django.contrib.auth.models import User
user_obj = User.objects.create_superuser(username='用戶名',password='密碼',email='郵箱',...)

修改密碼

check_password

   需要一個參數,即老密碼。判斷老密碼是否輸入正確

set_password

   設置密碼,接收要設置的新密碼作為參數。

   注意:設置完一定要調用用戶對象的save()方法!!!

@method_decorator(login_required(login_url='/login/'),name="dispatch")
class edit_password(View):
    def get(self, request):
        return render(request, "edit_password.html",locals())

    def post(self, request):
        username = request.POST.get("username")
        old_password = request.POST.get("old_password")
        new_password = request.POST.get("new_password")
        user_obj = request.user
        if user_obj.check_password(old_password): # 驗證老密碼是否正確
            user_obj.set_password(new_password) # 設置密碼
            user_obj.save()
            auth.login(request, user_obj)  # 重新封裝對象至request中,並且添加session
            return redirect("/index/")
        else:
            return HttpResponse("密碼錯誤")

其他屬性

屬性 描述
user_obj.is_staff 用戶是否擁有網站的管理許可權.
user_obj.active 是否允許用戶登錄, 設置為 False,可以在不刪除用戶的前提下禁止用戶登錄。

擴展auth_user

   我們可以通過繼承內置的 AbstractUser類,來定義一個自己的Model類。

   這樣就可以擴展auth_user表中的欄位了。

   注意:這必須是在沒執行python manage.py migrate之前

from django.contrib.auth.models import AbstractUser
class UserInfo(AbstractUser):
    """
    用戶資訊表
    """
    nid = models.AutoField(primary_key=True)
    phone = models.CharField(max_length=11, null=True, unique=True)
    
    def __str__(self):
        return self.username

   按上面的方式擴展了內置的auth_user表之後,一定要在settings.py中告訴Django,我現在使用我新定義的UserInfo表來做用戶認證。寫法如下:

# 引用Django自帶的User表,繼承使用時需要設置
AUTH_USER_MODEL = "app名.UserInfo(表名)"

   自定義認證系統默認使用的數據表之後,我們就可以像使用默認的auth_user表那樣使用我們的UserInfo表了

   創建普通用戶:

UserInfo.objects.create_user(username='用戶名', password='密碼')

   創建超級用戶:

UserInfo.objects.create_superuser(username='用戶名', password='密碼')

   一旦我們指定了新的認證系統所使用的表,我們就需要重新在資料庫中創建該表,而不能繼續使用原來默認的auth_user表了。

全套程式碼

最終效果

   auth

路由層

from django.conf.urls import url
from django.contrib import admin
from app01 import views

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^index/', views.Index.as_view(), name='index'),
    url(r'^login/', views.Login.as_view(), name='login'),
    url(r'^logout/', views.Logout.as_view(), name='logout'),
    url(r'^register/', views.Register.as_view(), name='register'),
    url(r'^edit_password/', views.edit_password.as_view(), name='edit_password'),
    url(r'^other/', views.Other.as_view(), name='other'),
]

視圖函數

from django.shortcuts import render
from django.shortcuts import redirect
from django.shortcuts import HttpResponse
from django.views import View
from django.views.decorators.csrf import csrf_exempt, csrf_protect
from django.utils.decorators import method_decorator
from django.contrib import auth
from django.contrib.auth.decorators import login_required
from django.contrib.auth.models import User

# Create your views here.


class Index(View):

    def get(self, request):
        return render(request, "index.html",locals())


class Login(View):
    def get(self, request):
        return render(request, "login.html")

    def post(self, request):
        username = request.POST.get("username")
        password = request.POST.get("password")
        user_obj = auth.authenticate(
            username=username, password=password)  # 拿到用戶記錄對象
        if user_obj:
            auth.login(request, user_obj)  # 封裝對象至request中,並且添加session
            return redirect("/index/")
        else:
            return redirect("/register/")  # 跳轉到註冊頁面

@method_decorator(login_required(login_url='/login/'),name="dispatch")
class Logout(View):
    def get(self, request):
        auth.logout(request) # 清除session
        return HttpResponse("清除成功")


class Register(View):
    def get(self, request):
        return render(request, "register.html")

    def post(self, request):
        username = request.POST.get("username")
        password = request.POST.get("password")
        repeat_password = request.POST.get("repeat-password")
        if repeat_password == password:

            if not User.objects.filter(username=username):  # 如果表中不存在該數據時

                User.objects.create_user(
                    username = username,
                    password = password,
                )

                return redirect("/index/")

            else:
                return HttpResponse("用戶已存在")
        else:
            return HttpResponse("密碼不一致,請重新輸入")


@method_decorator(login_required(login_url='/login/'),name="dispatch")
class edit_password(View):
    def get(self, request):
        return render(request, "edit_password.html",locals())

    def post(self, request):
        username = request.POST.get("username")
        old_password = request.POST.get("old_password")
        new_password = request.POST.get("new_password")
        user_obj = request.user
        if user_obj.check_password(old_password): # 驗證老密碼是否正確
            user_obj.set_password(new_password) # 設置密碼
            user_obj.save()
            auth.login(request, user_obj)  # 重新封裝對象至request中,並且添加session
            return redirect("/index/")
        else:
            return HttpResponse("密碼錯誤")
        

@method_decorator(login_required(login_url='/login/'),name="dispatch")
class Other(View):
    def get(self, request):
        if not request.user.is_authenticated():
            return redirect("/login/")
        else:
            return HttpResponse("歡迎來到其他頁面")

模板層

   index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <link href='//cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css' rel='stylesheet'>
    <script src='//cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js'></script>
    <script src='//cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js'></script>
</head>
<body>
    <h1>歡迎來到主頁</h1>
    
    <a class="btn btn-primary" href="{% url 'login' %}" role="button">登錄</a>
    
    <a class="btn btn-warning" href="{% url 'register' %}" role="button">註冊</a>
    

    {% if request.user.is_authenticated %}
      <a class="btn btn-default" href="{% url 'edit_password' %}'" role="button">修改{{request.user.username}}密碼</a>
      <a class="btn btn-danger" href="{% url 'logout' %}" role="button">註銷</a>
    {% endif %}

</body>
</html>

   edit_password.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <link href='//cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css' rel='stylesheet'>
    <script src='//cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js'></script>
    <script src='//cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js'></script>
</head>
<body>
    <form action="" method="POST" role="form">
        {% csrf_token %}
        <legend>修改密碼</legend>
    
        <div class="form-group">
            <label for="username">用戶名</label>
            <input type="text" class="form-control" id="username" name="username" placeholder="用戶名" value="{{request.user.username}}" readonly>
        </div>

        <div class="form-group">
            <label for="old_password">舊密碼</label>
            <input type="password" class="form-control" id="old_password" name="old_password" placeholder="密碼">
        </div>

        <div class="form-group">
            <label for="new_password">新密碼</label>
            <input type="password" class="form-control" id="new_password" name="new_password" placeholder="密碼">
        </div>
    
        <button type="submit" class="btn btn-primary">提交</button>
    </form>
    
</body>
</html>

   login.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <link href='//cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css' rel='stylesheet'>
    <script src='//cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js'></script>
    <script src='//cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js'></script>
</head>
<body>
    
    <form action="" method="POST" role="form">
        {% csrf_token %}
        <legend>登錄用戶</legend>
    
        <div class="form-group">
            <label for="username">用戶名</label>
            <input type="text" class="form-control" id="username" name="username" placeholder="用戶名">
        </div>

        <div class="form-group">
            <label for="password">密碼</label>
            <input type="text" class="form-control" id="password" name="password" placeholder="密碼">
        </div>
    
        <button type="submit" class="btn btn-primary">登錄</button>
    </form>
    
</body>
</html>

   register.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <link href='//cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css' rel='stylesheet'>
    <script src='//cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js'></script>
    <script src='//cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js'></script>
</head>
<body>
    
    <form action="" method="POST" role="form">
        {% csrf_token %}
        <legend>註冊用戶</legend>
    
        <div class="form-group">
            <label for="username">用戶名</label>
            <input type="text" class="form-control" id="username" name="username" placeholder="用戶名">
        </div>

        <div class="form-group">
            <label for="password">密碼</label>
            <input type="text" class="form-control" id="password" name="password" placeholder="密碼">
        </div>

        <div class="form-group">
            <label for="repeat-password">確認</label>
            <input type="text" class="form-control" id="repeat-password" name="repeat-password" placeholder="重複輸入密碼">
        </div>
    
        <button type="submit" class="btn btn-primary">註冊</button>
    </form>
    
</body>
</html>
Tags: