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中我們想要開 ...
  • 歡迎ReaLTaiizor是一個用戶友好的、以設計為中心的.NET WinForms項目控制項庫,包含廣泛的組件。您可以使用不同的主題選項對項目進行個性化設置,並自定義用戶控制項,以使您的應用程式更加專業。 項目地址:https://github.com/Taiizor/ReaLTaiizor 步驟1: ...
  • EDP是一套集組織架構,許可權框架【功能許可權,操作許可權,數據訪問許可權,WebApi許可權】,自動化日誌,動態Interface,WebApi管理等基礎功能於一體的,基於.net的企業應用開發框架。通過友好的編碼方式實現數據行、列許可權的管控。 ...
  • Channel 是乾什麼的 The System.Threading.Channels namespace provides a set of synchronization data structures for passing data between producers and consume ...
  • efcore如何優雅的實現按年分庫按月分表 介紹 本文ShardinfCore版本 本期主角: ShardingCore 一款ef-core下高性能、輕量級針對分表分庫讀寫分離的解決方案,具有零依賴、零學習成本、零業務代碼入侵適配 距離上次發文.net相關的已經有很久了,期間一直在從事java相關的 ...
  • 前言 Spacesniffer 是一個免費的文件掃描工具,通過使用樹狀圖可視化佈局,可以立即瞭解大文件夾的位置,幫助用戶處理找到這些文件夾 當前系統C盤空間 清理後系統C盤空間 下載 Spacesniffer 下載地址:https://spacesniffer.en.softonic.com/dow ...
  • EDP是一套集組織架構,許可權框架【功能許可權,操作許可權,數據訪問許可權,WebApi許可權】,自動化日誌,動態Interface,WebApi管理等基礎功能於一體的,基於.net的企業應用開發框架。通過友好的編碼方式實現數據行、列許可權的管控。 ...
  • 一、ReZero簡介 ReZero是一款.NET中間件 : 全網唯一開源界面操作就能生成API , 可以集成到任何.NET6+ API項目,無破壞性,也可讓非.NET用戶使用exe文件 免費開源:MIT最寬鬆協議 , 一直從事開源事業十年,一直堅持開源 1.1 純ReZero開發 適合.Net Co ...
  • 一:背景 1. 講故事 停了一個月沒有更新文章了,主要是忙於寫 C#內功修煉系列的PPT,現在基本上接近尾聲,可以回頭繼續更新這段時間分析dump的一些事故報告,有朋友微信上找到我,說他們的系統出現了大量的http超時,程式不響應處理了,讓我幫忙看下怎麼回事,dump也抓到了。 二:WinDbg分析 ...
  • 開始做項目管理了(本人3年java,來到這邊之後真沒想到...),天天開會溝通整理需求,他們講話的時候忙裡偷閑整理一下常用的方法,其實語言還是有共通性的,基本上看到方法名就大概能猜出來用法。出去打水的時候看到外面太陽好好,真想在外面坐著曬太陽,回來的時候好兄弟三年前送給我的鍵盤D鍵不靈了,在打"等待 ...