Django 之Auth模塊

来源:https://www.cnblogs.com/huaxiayuyi/archive/2022/10/04/16754258.html
-Advertisement-
Play Games

一、Auth 模塊是什麼 Auth 模塊是Django中自帶的用戶認證模塊。 一個網站系統需要實現用戶註冊、用戶登錄、用戶認證、註銷、修改密碼等功能,Django中內置了強大的認證系統-auth,預設使用 auth_user 表來存儲用戶的數據。 同時Django有一個後臺管理系統(127.0.0. ...


一、Auth 模塊是什麼


Auth 模塊是Django中自帶的用戶認證模塊。

一個網站系統需要實現用戶註冊、用戶登錄、用戶認證、註銷、修改密碼等功能,Django中內置了強大的認證系統-auth,預設使用 auth_user 表來存儲用戶的數據。

同時Django有一個後臺管理系統(127.0.0.1:8000/admin),使用的用戶名和密碼也是這張數據表中的數據。

預設後臺管理的用戶名和密碼是沒有的,需要我們創建一個出來,而且只有超級管理員才能登錄這個頁面,那我們現在就來創建這樣一個超級用戶。

 

二、擴展預設的 auth_user 表


在一個新的項目中,先設計項目的資料庫,表關係,Django 系統內置的認證系統(auth_user表)很好用,但是表欄位都是固定的幾個,無法進行對它擴展。

比如,預設欄位不夠我們使用,我們可以對其進行拓展,存儲用戶手機號、時間等欄位,設置表和表之間關係,怎麼辦?

現在就來設計擴展一下這個表,需要兩步

1 配置settings

在 settings.py 配置文件中增加一句話,告訴Django 使用新定義的 UserInfo 表來做用戶認證的表。

# settings.py
# 聲明使用自定義表作為用戶驗證,聲明格式為: 應用名.表名,繼承使用時需要設置
AUTH_USER_MODEL = 'app.UserInfo'

2 配置models

創建一個自定義類並繼承AbstractUser類,然後編寫 AbstractUser 類中沒有的欄位並且'不能衝突'。

# app/models.py
from django.db import models
# 導入AbstractBaseUser類,繼承AbstractBaseUser類,基本欄位
from django.contrib.auth.models import AbstractUser

class UserInfo(AbstractUser):
    '''
    擴展用戶信息表
    繼承原有的auth_user表欄位
    '''
    nid = models.AutoField(primary_key = True)
    phone = models.CharField(max_length = 11, blank = True, null = True, unique = True, verbose_name = "手機號")
    avatar = models.FileField(upload_to = "avatar", default = "avatar/default.png")
    create_time = models.DateField(auto_now_add = True)
    blog = models.OneToOneField(to = 'Blog', null = True, to_field = 'bid', on_delete = models.CASCADE)
    
    class Meta:
        verbose_name_plural = '用戶表'
    def __str__(self):
        return self.username
    
class Blog(models.Model):
    bid = models.AutoField(primary_key = True)
    site_name = models.CharField(verbose_name = "站點名稱", max_length = 32)
    site_title = models.CharField(verbose_name = "站點標題", max_length = 32)
    site_theme = models.CharField(verbose_name = "站點樣式", max_length = 255)
    def __str__(self):
        return self.site_name

最後,執行兩條資料庫遷移命令。

python manage.py makemigrations
python manage.py migrate

 註意:所在的庫必須是第一次執行遷移命令才可以,若是原本有殘留會 引起異常。

 

三、創建超級用戶


預設後臺管理的用戶名和密碼是沒有的,需要我們創建一個出來,而且只有超級管理員才能登錄這個頁面,那我們現在就來創建這樣一個超級用戶

python manage.py createsuperuser

 

四、Auth 模塊常用方法


1 auth模塊常用方法

from django.contrib import auth

 

2 authenticate()

校驗用戶名和密碼是否正確,可以用來判斷當前是否登錄,也就是否有session數據。

from django.shortcuts import render, HttpResponse, redirect
from django.contrib import auth
def login(request):
    if request.method == 'POST':
        username = request.POST.get('username')
        password = request.POST.get('password')
        user_obj = auth.authenticate(request, username=username, password=password)
        print(user_obj)
        if user_obj:
            # 保存用戶狀態
            auth.login(request, user_obj)
            return HttpResponse('OK')
    return render(request, 'login.html')

authenticate方法如果認證成功(用戶名和密碼正確有效,就是去 UserInfo 表中查詢一下是否存在這條記錄),便會返回一個 User 對象,查詢認證失敗返回None。

templates/login.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Login</title>
</head>
<body>
    <form action="" method="post">
        {% csrf_token %}
        <p>username:<input type="text" name="username"></p>
        <p>password:<input type="text" name="password"></p>
        <input type="submit">
    </form>
</body>
</html>

 

3 login(HttpRequest, user)

該函數接受一個 HttpRequest 對象,以及一個經過認證的 User 對象。

可以在驗證成功後進行登錄,它本質上會在後端為該用戶生成相關session數據。

# 保存用戶狀態,相當於設置 session 值。
# 只要執行了此操作,後面的視圖函數只要能夠拿到request就可以通過 request.user 獲取到當前的用戶對象。
auth.login(request, user_obj)

 

4 logout(request)

該函數接受一個HttpRequest對象,無返回值。註銷。

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

def logout(request):
    # 類似於request.session.flush()
    auth.logout(request)
    return redirect('/login/')

 

5 is_authenticated()

用來判斷當前請求是否通過了認證。

def home(request):
    print(request.user)  # 用戶對象     AnonymousUser匿名用戶
    print(request.user.is_authenticated())
    if not request.user.is_authenticated():
        return redirect('/home/')
    return redirect('/register/')

 

6 login_requierd()

校驗用戶是否登錄的裝飾器。

判斷當前用戶是否登錄那種方式很複雜,需要再每個功能函數中寫上這麼一段,那麼auth模塊也幫我們提供了一個現成的登錄認證裝飾器。

from django.contrib.auth.decorators import login_required
# auth 模塊提供的登錄裝飾器提供兩個配置: 局部配置和全局配置

# 局部配置
@login_required(login_url='/login/') # 用戶沒有登錄會跳到login頁面
def home(request):
    # if not request.user.is_authenticated:
    #     return redirect('/login/')
    return HttpResponse('歡迎來到home頁面')

# 全局配置:
# settings.py配置文件中配置
LOGIN_URL = '/login/'

# 如果全局配置和局部配置都設置了,那麼會以局部配置優先。

 

7 create_superuser()

auth 提供的一個創建新普通用戶/超級管理員用戶的方法,需要提供必要參數(username、password)等。

from app import models

# 操作auth_user表寫入數據
def register(request):
    if request.method == 'POST':
        username = request.POST.get('username')
        password = request.POST.get('password')
        
        # 寫入數據不能用create密碼沒有加密處理
        # models.UserInfo.objects.create(username=username, password=password)  
        
        # 創建普通用戶
        # models.UserInfo.objects.create_user(username=username, password=password)

        # 創建超級用戶(瞭解):使用代碼創建超級用戶 郵箱是必填的 而用命令創建則可以不填
        models.UserInfo.objects.create_superuser(username=username, password=password, email='[email protected]')
    return render(request, 'register.html')

templates/register.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Register</title>
</head>
<body>
    <form action="" method="post">
        {% csrf_token %}
        <p>username:<input type="text" name="username"></p>
        <p>password:<input type="text" name="password"></p>
        <input type="submit">
    </form>
</body>
</html>

 

8 check_password()

auth 提供的一個檢查密碼是否正確的方法,需要提供當前請求用戶的密碼。

密碼正確返回True,否則返回False。

 

9 set_password

auth 提供的一個修改密碼的方法,接收新密碼作為參數,校驗原密碼並修改密碼。

def set_password(request):
    if request.method == 'POST':
        old_password = request.POST.get('old_password')
        new_password = request.POST.get('new_password')
        confirm_password = request.POST.get('confirm_password')
        # 先校驗兩次密碼是否一致
        if new_password == confirm_password:
            # 校驗老密碼對不對
            is_right = request.user.check_password(old_password)
            if is_right:
                # 修改密碼
                request.user.set_password(new_password)  # 僅僅是在修改對象的屬性
                request.user.save()  # 將修改操作保存到資料庫
        return redirect('/login/')
    return render(request, 'set_password.html', locals())

templates/set_password.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>密碼修改</title>
</head>
<body>
    <form action="" method="post">
        {% csrf_token %}
        <p>username:<input type="text" name="username" disabled value="{{ request.user.username }}"></p>
        <p>old_password:<input type="text" name="old_password"></p>
        <p>new_password:<input type="text" name="new_password"></p>
        <p>confirm_password:<input type="text" name="confirm_password"></p>
        <input type="submit">
    </form>
</body>
</html>

 

五、後臺管理系統配置


1 在該表對應的models類裡面添加一個Meta類

class Meta:
    verbose_name_plural = '用戶表' #指定該表在admin後臺的名字為:用戶表 

 

2 null=True,blank=True的區別

# null=True:  是告訴資料庫該欄位可以為空,admin後臺預設還是不允許為空
# blank=True: admin 後臺該欄位可以為空
phone = models.CharField(max_length = 11, blank = True, null = True, unique = True, verbose_name = "手機號")

 

3 settings.py配置,使django的後臺管理頁面變成中文、設置時區

# Internationalization
# https://docs.djangoproject.com/en/3.2/topics/i18n/

LANGUAGE_CODE = 'zh-hans'

TIME_ZONE = 'Asia/Shanghai'

USE_I18N = True

USE_L10N = True

USE_TZ = False

 

六、ModelAdmin的常用屬性


1 註冊表

admin.py中只需要 Mode 中的某個類註冊,即可在 Admin 中實現增刪改查的功能。

from django.contrib import admin
from app import models
# Register your models here.

admin.site.register(models.UserInfo)
admin.site.register(models.Blog)

註冊完的結果如下圖所示,點擊表名即可修改表內容。

 

2 list_display欄位展示

  • list_display:列表時,定製顯示的列。
  • 在預設的情況下,Model 在 admin 列表修改頁(Admin ChangeList)只會顯示一列,內容是實例對象的__str__的返回值,如果想要多現實一些列的數據,就可以通過 list_display 屬性來實現。
  • 它除了可以配置 Model 的欄位名之外,還可以接收函數,且這個函數將一個 Model 實例對象作為參數,這個函數也需定義在 ModeAdmin 中。語法格式如下:list_display=[]
  • 在使用 list_display 時需要特別註意它的兩個特性
  • 對於 Foreignkey 類型的欄位,顯示的是 obj.__str__() 返回的值。
  • 不支持 ManyToManyField 類型的欄位,如果需要展示,可以用自定義方法實現。
# 方式一
class UserInfoAdmin(admin.ModelAdmin):
    list_display = ('username', 'email',)
admin.site.register(models.UserInfo, UserInfoAdmin) # 第一個參數可以是列表

# 方式二
@admin.register(models.UserInfo)                    # 第一個參數可以是列表
class UserInfoAdmin(admin.ModelAdmin):
    list_display = ('username', 'email',)

 

3 list_display_links,列表時,定製列可以點擊跳轉。

 

4 list_filter

  • 配置 list_filter 屬性,可以在 Admin 後臺的列表修改頁的右側添加過濾器,且各個過濾條件是 and 的關係。
  • list_filter 是列表或者元組類型,通常使用它會傳遞兩類元素:一個是 Model 的欄位名,另一個是繼承自以下的類(並不常用):django.contrib.admin.SimpleListFilter
  • 對於 Model 的欄位名,欄位類型必須屬於 BooleanField、CharField、DateField、DateTimeField、IntegerField、ForeignKey 或 ManyToManyField 中的一種。同樣也可以使用雙下畫線實現跨表關聯。示例如下所示:list_filter= ['title', 'pub__pubname']

5 list_editable,列表時,可以編輯的列 。

 

cclass UserInfoAdmin(admin.ModelAdmin):
    list_display = ('email', 'create_time', 'phone',)
    list_display_links = ( 'create_time',)
    list_filter = ('email', 'phone',)
    list_editable = ('email', )
admin.site.register(models.UserInfo, UserInfoAdmin)

 

 

5 list_select_related,列表時,連表查詢是否自動 select_related

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 就像在學習之前先要識字,我想在介紹優化 JavaScript 代碼之前,先介紹一下自己對編程語言的理解。故事要從一隻叫做 Theseus 的機械鼠和其發明人克勞德-香農(Claude Shannon)說起。在傳記《A Mind at Play:How Claude Shannon Invented ... ...
  • 在 《基於 vite 創建 vue3 全家桶》一文整合了 *Element Plus*,並將 *Element Plus* 中提供的圖標進行全局註冊,這樣可以很方便的延續 *Element UI* 的風格 —— 通過 *el-icon-xxx* 的方式使用圖標(如果有問題的朋友可以先閱讀前面的文章:... ...
  • 一:創建一個新的工程,項目初始化 npm init -y 二:搭建項目框架 三:編寫main.js文件內容,在index.js中引入,在把index.js引入到index.html中 例: export default()=>{ function computer(){ let h2=documen ...
  • 一、使用webpack優化前端性能方法 ⽤webpack優化前端性能是指優化webpack的輸出結果,讓打包的最終結果在瀏覽器運⾏快速⾼效。 可通過webpack優化前端的手段: 代碼壓縮(刪除多餘的代碼、註釋、簡化代碼的寫法等等⽅式) HTML文件代碼壓縮 使用HTMLWebpackPlugin插 ...
  • 內部類的基本使用 內部類概念 在一個類中定義一個類。舉例:在一個類A的內部定義一個類B,類B就被稱為內部類 我們把一個類放在另一個類的內部定義,稱為內部類(inner class)。 內部類的兩個要點: 內部類提供了更好的封裝。只能讓外部類直接訪問,不允許同一個包中的其他類直接訪問。 內部類可以直接 ...
  • 一、遞歸與迴圈的對比 遞歸會帶來大量的函數調用。這是不好的 在計算環節特別大的前提下,遞歸就是不好的,因為遞歸是先調用,再計算。 在大量計算的前提下可能會造成棧溢出(StackOverFlow) 如下圖: 迴圈是先計算再調用,計算完後會調用的方法會從棧中抹去,最後將結果輸出 能不用遞歸就不用遞歸 小 ...
  • 項目地址: GitHub - apache/skywalking-swck: Apache SkyWalking Cloud on Kubernetes 項目簡介: A bridge project between Apache SkyWalking and Kubernetes. SWCK is ...
  • 變數: 什麼是變數?一個可以存儲數據(存儲的地方在記憶體中),並可以在代碼的運行中,給與數據的改變 註意:變數的聲明必須在最前面 語法:數據類型 變數名稱 = 值; 案例: %d - 輸出一個整數 %.2f - 輸出一個小數(2代表的是小數位,可以改變) %c - 輸出一個字元 %s - 輸出一個字元 ...
一周排行
    -Advertisement-
    Play Games
  • 一個自定義WPF窗體的解決方案,借鑒了呂毅老師的WPF製作高性能的透明背景的異形視窗一文,併在此基礎上增加了滑鼠穿透的功能。可以使得透明窗體的滑鼠事件穿透到下層,在下層窗體中響應。 ...
  • 在C#中使用RabbitMQ做個簡單的發送郵件小項目 前言 好久沒有做項目了,這次做一個發送郵件的小項目。發郵件是一個比較耗時的操作,之前在我的個人博客裡面回覆評論和友鏈申請是會通過發送郵件來通知對方的,不過當時只是簡單的進行了非同步操作。 那麼這次來使用RabbitMQ去統一發送郵件,我的想法是通過 ...
  • 當你使用Edge等瀏覽器或系統軟體播放媒體時,Windows控制中心就會出現相應的媒體信息以及控制播放的功能,如圖。 SMTC (SystemMediaTransportControls) 是一個Windows App SDK (舊為UWP) 中提供的一個API,用於與系統媒體交互。接入SMTC的好 ...
  • 最近在微軟商店,官方上架了新款Win11風格的WPF版UI框架【WPF Gallery Preview 1.0.0.0】,這款應用引入了前沿的Fluent Design UI設計,為用戶帶來全新的視覺體驗。 ...
  • 1.簡單使用實例 1.1 添加log4net.dll的引用。 在NuGet程式包中搜索log4net並添加,此次我所用版本為2.0.17。如下圖: 1.2 添加配置文件 右鍵項目,添加新建項,搜索選擇應用程式配置文件,命名為log4net.config,步驟如下圖: 1.2.1 log4net.co ...
  • 之前也分享過 Swashbuckle.AspNetCore 的使用,不過版本比較老了,本次演示用的示例版本為 .net core 8.0,從安裝使用開始,到根據命名空間分組顯示,十分的有用 ...
  • 在 Visual Studio 中,至少可以創建三種不同類型的類庫: 類庫(.NET Framework) 類庫(.NET 標準) 類庫 (.NET Core) 雖然第一種是我們多年來一直在使用的,但一直感到困惑的一個主要問題是何時使用 .NET Standard 和 .NET Core 類庫類型。 ...
  • WPF的按鈕提供了Template模板,可以通過修改Template模板中的內容對按鈕的樣式進行自定義。結合資源字典,可以將自定義資源在xaml視窗、自定義控制項或者整個App當中調用 ...
  • 實現了一個支持長短按得按鈕組件,單擊可以觸發Click事件,長按可以觸發LongPressed事件,長按鬆開時觸發LongClick事件。還可以和自定義外觀相結合,實現自定義的按鈕外形。 ...
  • 一、WTM是什麼 WalkingTec.Mvvm框架(簡稱WTM)最早開發與2013年,基於Asp.net MVC3 和 最早的Entity Framework, 當初主要是為瞭解決公司內部開發效率低,代碼風格不統一的問題。2017年9月,將代碼移植到了.Net Core上,併進行了深度優化和重構, ...