一、🛡? Django 鑒權 & 登錄控制?
Django 自帶的鑒權系統(用戶身份管理小管家)
?
鑒權系統能干啥?
Django 自帶的鑒權系統,就像一個?“用戶身份管家”?,幫你管好這些事兒:
功能 | 類比 |
---|---|
加密存儲用戶密碼 | 把用戶的 “秘密”(密碼)鎖進保險箱,存的時候自動加密~ |
登錄表單 | 提供 “登錄頁面模板”(雖然需要自己改改樣式,但基礎功能有了)~ |
驗證賬號密碼 | 檢查用戶輸入的賬號密碼對不對,像 “門衛查身份證”~ |
驗證是否登錄 | 判斷用戶 “有沒有帶身份憑證”,沒登錄就不讓進某些頁面~ |
針對單用戶的權限設置 | 給不同用戶發 “權限卡片”(比如管理員能刪數據,普通用戶只能看)~ |
?
啟用鑒權系統的條件(配置檢查)
要讓鑒權系統工作,項目里得有這兩個 “開關”(在?settings.py
?):
①?INSTALLED_APPS
?里要有這倆
INSTALLED_APPS = [..."django.contrib.auth", # 鑒權核心功能"django.contrib.contenttypes", # 輔助管理權限...
]
- 類比:給 “身份管家” 開通 “系統權限”,讓它能在項目里工作~
?
②?MIDDLEWARE
?里要有這倆中間件
MIDDLEWARE = [..."django.contrib.sessions.middleware.SessionMiddleware", # 管理用戶會話(登錄狀態)"django.contrib.auth.middleware.AuthenticationMiddleware", # 管理用戶身份驗證...
]
SessionMiddleware
:給用戶發 “會話餅干”(記錄登錄狀態)~AuthenticationMiddleware
:檢查用戶的 “身份餅干”,確認是否登錄~- 類比:給 “身份管家” 配兩個小助手,一個發餅干、一個查餅干~
?
禁止匿名訪問(攔住沒登錄的人!)
場景
有些頁面 / 功能(比如 “發布評論”),必須?登錄后才能用?!如果匿名用戶(沒登錄的人)訪問,就 “攔住他”,讓他先登錄~
?
方法 1:手動判斷(一步步攔)
from django.http import HttpResponse
from django.views.decorators.csrf import csrf_exempt # 演示用,實際要開CSRFdef submit(request):# request.user 是鑒權系統給的“用戶身份對象”if not request.user.is_authenticated: # is_authenticated 是“檢查是否登錄”的小開關return HttpResponse("請登錄后再發布", status=401)# 登錄了就繼續處理發布邏輯...
流程:
request.user
:鑒權系統把 “當前用戶身份” 放到?request
?里,你可以直接用~request.user.is_authenticated
:判斷用戶?是否登錄?(登錄了返回?True
?,沒登錄返回?False
?)~- 如果沒登錄,返回 “請登錄” 的提示(
status=401
?表示 “未授權” )~
類比:
你:“小管家!看看這個用戶有沒有登錄,沒登錄就攔住他!”
小管家:檢查?request.user
?的 “身份憑證”,沒登錄就說 “請先登錄~”
?
方法 2:@login_required 裝飾器(一鍵攔)
from django.contrib.auth.decorators import login_required@login_required
def submit(request):# 只有登錄用戶能進這個視圖!...
流程:
@login_required
?是 Django 提供的 “快捷攔人裝飾器”~- 如果用戶沒登錄,自動?跳轉到登錄頁面?(需要在?
settings.py
?配置?LOGIN_URL
?)~
類比:
你給 “發布評論” 的門掛了一個 “登錄才能進” 的魔法門牌(@login_required
?)~
沒登錄的人想進門,直接被傳送到 “登錄頁面”~
?
方法 2 的配置(讓跳轉生效)
在?settings.py
?里加一行:
LOGIN_URL = '/login/' # 登錄頁面的 URL
- 這樣,匿名用戶訪問被?
@login_required
?裝飾的視圖時,會自動跳轉到?/login/
?~
?Django 為了方便開發者處理用戶的認證(登錄、登出等)相關操作,內置了一套鑒權系統。
當你在項目的 URL 配置里,使用?include("django.contrib.auth.urls")
?后,就相當于給項目 “接入” 了鑒權系統的一系列 URL (添加一個路由),其中就有?/accounts/login/
?。
它的工作方式
?
視圖函數:
當用戶訪問?/accounts/login/
?時,Django 會找到鑒權系統里對應的視圖函數(?LoginView
?,它是一個基于類的視圖)。這個視圖函數就像一個 “登錄小助手”,負責處理用戶登錄的邏輯,比如驗證用戶輸入的用戶名和密碼是否正確。
?
表單處理:
?LoginView
?會自動生成一個登錄表單 ,包含用戶名和密碼的輸入框。就好比小助手準備了一張 “登錄申請表”,讓用戶填寫信息。而且它還會對用戶提交的表單數據進行校驗,看看用戶名和密碼是不是匹配數據庫里存儲的用戶信息。
?
登錄狀態管理:
如果用戶輸入的信息正確,LoginView
?會通過 Django 的會話機制,給用戶設置登錄狀態。這就像給用戶發了一張 “小鎮通行證”,用戶后續訪問需要登錄才能查看的頁面時,Django 就能通過這張 “通行證” 確認用戶已經登錄啦。
?
可定制性
雖然?/accounts/login/
?是 Django 提供的,但它也是可以定制的哦。默認情況下它會去尋找?registration/login.html
?這個模板文件來展示登錄頁面
總結(小劇場)
鑒權系統小劇場
你:“小管家!我需要管理用戶登錄、權限,你能幫我嗎?”
小管家:“當然!我有加密密碼、驗證登錄、管理權限的本事~ 不過你得在?settings.py
?里開一下我的權限!”
?
禁止匿名訪問小劇場
方法 1 場景:
用戶(沒登錄)想訪問 “發布評論” 頁面~
小管家檢查?request.user
?,發現沒登錄 → 攔住:“請登錄后再發布!”
方法 2 場景:
用戶(沒登錄)想訪問 “發布評論” 頁面~
小管家看到門上掛了?@login_required
?→ 直接把用戶傳送到登錄頁面:“先登錄才能進!”
二、🚪 Django 登錄頁面實現?
實現登錄頁面的流程(創建視圖 + 路由)
?
1. 核心思路
Django 自帶的鑒權系統,已經幫我們寫好了?登錄邏輯?(驗證賬號密碼、設置登錄狀態),但?登錄頁面的模板需要自己提供?!
實現步驟就兩步:
- 配路由(讓?
/accounts/login/
?能找到 Django 自帶的登錄視圖) - 寫登錄頁面模板(告訴 Django 登錄頁面長啥樣)
?
2. 配置路由(讓請求找到 Django 登錄視圖)
from django.urls import path, includeurlpatterns = [# 包含 Django 自帶的 auth 路由path("accounts/", include("django.contrib.auth.urls")),
]
include("django.contrib.auth.urls")
:這是 Django 提供的 “快捷路由”,里面包含了?/accounts/login/
、/accounts/logout/
?等常用登錄、登出路由~- 類比:你給 “登錄功能” 的請求,設置了一個 “自動導航”,讓 Django 自帶的登錄視圖處理請求~
訪問效果
當你訪問?http://127.0.0.1:8000/accounts/login/
?時,Django 會找到自帶的?LoginView
?處理請求~
?
報錯分析:TemplateDoesNotExist(模板找不到)
錯誤信息解讀
TemplateDoesNotExist at /accounts/login/
registration/login.html
- Django 想找?
registration/login.html
?這個模板文件,但沒找到~
為什么會找這個模板?
Django 自帶的?LoginView
?默認會去?templates/registration/login.html
?找登錄頁面模板~
如果你的項目里沒有這個文件,就會報錯!
?
解決方法(給 Django 一個登錄頁面)
?
方法 1:自己寫?login.html
?模板
步驟 1:創建模板文件
在你的 App(比如?beifan
?)目錄下,創建這樣的路徑:
beifan/
└── templates/└── registration/└── login.html
template、registration是目錄
- 路徑必須是?
templates/registration/login.html
?,因為 Django 默認找這個位置~
?
步驟 2:寫模板內容
在?login.html
?里寫登錄頁面的 HTML ,比如:
<!DOCTYPE html>
<html>
<head><title>登錄</title>
</head>
<body><h1>歡迎登錄</h1><form method="post">{% csrf_token %} <!-- 必須加,防止跨站攻擊 -->{{ form.as_p }} <!-- 自動渲染登錄表單 --><button type="submit">登錄</button></form>
</body>
</html>
{{ form.as_p }}
:Django 會自動生成用戶名、密碼的輸入框~
?
方法 2:復用 Django admin 的登錄模板(偷懶版)
錯誤信息里的提示
{# beifan/templates/registration/login.html #}
{% extends "admin/login.html" %}
- 這行代碼的意思是:“讓登錄頁面繼承 Django admin 的登錄模板”,這樣不用自己寫樣式~
?
步驟 1:創建模板文件
同樣在?beifan/templates/registration/login.html
?里寫:
{% extends "admin/login.html" %}
{% extends "admin/login.html" %}
:表示 “我的登錄頁面,用 Django admin 的登錄頁面樣式”~
?
步驟 2:確保 Django 能找到模板
在?settings.py
?里,確保你的 App(beifan
?)在?INSTALLED_APPS
?里,并且模板配置正確:
INSTALLED_APPS = [...'beifan',...
]TEMPLATES = [{...'APP_DIRS': True, # 允許 Django 在 App 的 templates 目錄找模板...},
]
?
步驟 3:檢查模板路徑
確保你的模板文件路徑是:
beifan/
└── templates/└── registration/└── login.html
- 這樣 Django 就能找到?
registration/login.html
?,繼承?admin/login.html
?的樣式~
?
總結(小劇場)
實現登錄頁小劇場
你:“Django 呀,我要做個登錄頁面,用戶訪問?/accounts/login/
?時能登錄~”
Django:“好呀!你配好路由(include('django.contrib.auth.urls')
?),再給我一個?registration/login.html
?模板,我就能顯示登錄頁面啦!”
報錯解決小劇場
你訪問?/accounts/login/
?,Django 大喊:“找不到?registration/login.html
?模板!”
你:“哦~ 原來要自己創建這個文件!”
于是你在?beifan/templates/registration/
?里創建?login.html
?,要么自己寫內容,要么繼承?admin/login.html
?,問題解決!
三、🎨 什么是Django 模板?
模板就是?“HTML 半成品 + Django 魔法標記”?,讓你能把 Python 數據(比如模型數據、變量)動態渲染到網頁里~?
模板是干啥的?
想象你要做 100 個 “用戶訂單詳情頁”,每個頁面的結構一樣(比如標題、表格),但數據不同(訂單號、商品、價格)。
- 如果純手寫 HTML ,得復制 100 個文件,改數據 → 超麻煩!
- 用 Django 模板 → 寫一個 “模板文件”(HTML 框架 + 動態標記),然后傳不同數據進去,自動生成 100 個頁面!
?
模板長啥樣?(結構拆解)
1. 普通 HTML 部分(靜態內容)
<!DOCTYPE html>
<html>
<head><title>我的頁面</title>
</head>
<body><h1>歡迎來到我的網站!</h1><p>這是一段固定不變的文字~</p>
</body>
</html>
- 這部分和普通 HTML 一樣,是靜態內容(所有用戶看到的都一樣)~
?
2. Django 魔法標記(動態內容)
<!DOCTYPE html>
<html>
<head><title>{{ page_title }}</title> <!-- 動態標題 -->
</head>
<body><h1>歡迎 {{ user_name }} 來到我的網站!</h1> <!-- 動態用戶名 --><p>你的訂單號是:{{ order.id }}</p> <!-- 動態訂單號 -->{% if user.is_vip %} <!-- 條件判斷 --><p>你是 VIP 用戶,享受專屬優惠~</p>{% endif %}{% for product in products %} <!-- 循環遍歷 --><li>{{ product.name }} - 價格:{{ product.price }}</li>{% endfor %}
</body>
</html>
{{ 變量 }}
:插入 Python 變量(比如?page_title
、user_name
?),把后端數據動態渲染到 HTML 里~
類比:在 HTML 里 “挖個坑”,讓后端傳數據填進來~{% 標簽 %}
:控制邏輯(比如?if
?判斷、for
?循環 ),讓 HTML 能根據后端數據 “動態變化”~
類比:給 HTML 加 “魔法指令”,讓它能判斷、循環,變聰明~
?
模板的作用(為啥需要它?)
1. 分離前后端
- 后端(Python)負責 “處理數據、業務邏輯”,前端(HTML)負責 “頁面展示”~
- 模板就是 “橋梁”:讓后端把數據傳給前端,前端用 HTML + 魔法標記展示數據~
2. 復用代碼
- 一個模板可以渲染?N 個頁面(傳不同數據就行),不用重復寫 HTML 結構~
3. 動態交互
- 結合?
{{ }}
?和?{% %}
?,讓頁面能根據用戶、數據的不同,展示不同內容~
?
模板的使用流程(小劇場)
1. 后端準備數據
from django.shortcuts import renderdef my_view(request):# 準備要傳給模板的數據(字典形式)context = {'page_title': '我的動態頁面','user_name': '北凡','order': {'id': 123},'user': {'is_vip': True},'products': [{'name': '魔法棒', 'price': 99},{'name': '仙女裙', 'price': 199},]}# 渲染模板,把 data 傳給模板return render(request, 'my_template.html', context)
?
2. 前端模板?my_template.html
?接收數據
<!DOCTYPE html>
<html>
<head><title>{{ page_title }}</title>
</head>
<body><h1>歡迎 {{ user_name }} 來到我的網站!</h1><p>你的訂單號是:{{ order.id }}</p>{% if user.is_vip %}<p>你是 VIP 用戶,享受專屬優惠~</p>{% endif %}<h3>你的商品:</h3><ul>{% for product in products %}<li>{{ product.name }} - 價格:{{ product.price }}</li>{% endfor %}</ul>
</body>
</html>
?
3. 最終渲染的 HTML(用戶看到的)
<!DOCTYPE html>
<html>
<head><title>我的動態頁面</title>
</head>
<body><h1>歡迎 北凡 來到我的網站!</h1><p>你的訂單號是:123</p><p>你是 VIP 用戶,享受專屬優惠~</p><h3>你的商品:</h3><ul><li>魔法棒 - 價格:99</li><li>仙女裙 - 價格:199</li></ul>
</body>
</html>
?
模板的存放位置
Django 會在這些地方找模板:
- 項目根目錄的?
templates
?文件夾(適合全局模板) - 每個 App 目錄下的?
templates
?文件夾(適合 App 專屬模板)
比如你的 App 叫?beifan
?,模板可以放在:
beifan/
└── templates/└── beifan/└── my_template.html
?
總結
模板就是?“會魔法的 HTML”?,通過?{{ }}
?插變量、{% %}
?寫邏輯,讓后端數據能動態渲染到前端頁面里~
它讓前后端分離更清晰、代碼復用更方便、頁面交互更靈活~ 掌握模板,就能做出 “千人千面” 的動態網頁啦! 🎉
?