我們可以使用 Django 身份驗證系統(tǒng)為我們的項目構(gòu)建身份驗證。
先決條件:
- Python
- OOP
- Django 基礎(chǔ)知識(Django 模板拍摇、視圖亮钦、URL、設(shè)置)
這是 Django文檔中關(guān)于其身份驗證系統(tǒng)的說明:
Django 在其默認(rèn)配置中的身份驗證系統(tǒng)充活。這種配置已經(jīng)發(fā)展到滿足最常見的項目需求蜂莉,處理相當(dāng)廣泛的任務(wù),并仔細(xì)實現(xiàn)了密碼和權(quán)限混卵。對于身份驗證需求與默認(rèn)不同的項目映穗,Django 支持廣泛的身份驗證擴(kuò)展和自定義。
Django 身份驗證同時提供身份驗證和授權(quán)幕随,通常稱為身份驗證系統(tǒng)蚁滋,因為這些功能有些耦合。
我們將使用身份驗證視圖和內(nèi)置表單來創(chuàng)建這個應(yīng)用程序合陵。該應(yīng)用程序?qū)?zhí)行的操作是:
- 用戶注冊
- 登錄
- 登出
- 密碼更改
設(shè)置
讓我們開始為我們的項目創(chuàng)建一個文件夾,然后我們創(chuàng)建一個虛擬環(huán)境澄阳,并激活它:
mkdir django_authentication
cd django auth
py -m venv venv
cd venv/Scripts
activate
現(xiàn)在我們安裝 Django:
pip install django
我們創(chuàng)建一個 django 項目:
django_admin startproject django_authentication
cd django_authentication
現(xiàn)在我們創(chuàng)建我們的應(yīng)用程序:
py manage.py startapp user_auth
我們必須添加我們的應(yīng)用程序拥知,django_authentication/settings.py
并且我們的應(yīng)用程序?qū)⒃谟脩舻卿浕蜃N時重定向用戶的 URL:
LOGIN_REDIRECT_URL = '/home'
LOGOUT_REDIRECT_URL = '/home'
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'user_auth',
]
將應(yīng)用添加到 后INSTALLED_APPS
,我們在終端中使用以下命令運(yùn)行遷移:
py manage.py migrate
根據(jù)文檔:
當(dāng) django.contrib.auth 在您的 INSTALLED_APPS 設(shè)置中列出時碎赢,它將確保為您安裝的應(yīng)用程序之一中定義的每個 Django 模型創(chuàng)建四個默認(rèn)權(quán)限 - 添加低剔、更改、刪除和查看肮塞。
這些權(quán)限將在您運(yùn)行manage.py migrate 時創(chuàng)建襟齿;在將 django.contrib.auth 添加到 INSTALLED_APPS 后第一次運(yùn)行 migrate 時,將為所有以前安裝的模型以及當(dāng)時正在安裝的任何新模型創(chuàng)建默認(rèn)權(quán)限枕赵。之后猜欺,它會在每次運(yùn)行manage.py migrate 時為新模型創(chuàng)建默認(rèn)權(quán)限(創(chuàng)建權(quán)限的函數(shù)連接到 post_migrate 信號)。
我們將實現(xiàn) Authentication Views 來處理登錄拷窜、注銷和密碼管理开皿,我們需要django.contrib.auth.urls
添加django_authentication/urls.py
django_authentication/ urls.py
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('users', include('django.contrib.auth.urls')),
]
這將包括以下 URL 模式:
users/login/ [name='login']
users/logout/ [name='logout']
users/password_change/ [name='password_change']
users/password_change/done/ [name='password_change_done']
users/password_reset/ [name='password_reset']
users/password_reset/done/ [name='password_reset_done']
users/reset/<uidb64>/<token>/ [name='password_reset_confirm']
users/reset/done/ [name='password_reset_complete']
我們運(yùn)行以下命令來運(yùn)行服務(wù)器:
py manage.py runserver
在user_auth
目錄中涧黄,我們創(chuàng)建一個文件夾來存儲我們應(yīng)用的模板。
user_auth/
__init__.py
admin.py
apps.py
migrations/
models.py
templates/
user_auth/
home.html
base.html
tests.py
urls.py
views.py
Home
from django.shortcuts import render
# Create your views here.
def home_page(request):
return render (request,"user_auth/home.html")
這里我們只寫一個函數(shù)來渲染home.html
我們必須urls.py
在我們的應(yīng)用程序目錄中創(chuàng)建一個文件來添加我們將創(chuàng)建的視圖的 URL赋荆。
user_auth/ urls.py
from django.contrib import admin
from django.urls import path, include
from . import views
urlpatterns = [
path('', views.home_page, name="home"),
]
urls.py
現(xiàn)在我們必須在項目文件中包含 user_auth 應(yīng)用程序 URL 笋妥。
django_authentication/ urls.py
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('users', include('django.contrib.auth.urls')),
path('home/', include('user_auth.urls')),
]
我們創(chuàng)建了兩個模板。base.html
我們將在其中添加將被其他 HTML 文件繼承的 HTML 和 CSS 代碼窄潭。這home.html
將是主頁的模板春宣。
base.html
<!doctype html>
<html lang="en">
<div class="topnav">
<a href="{% url 'home' %}">Home</a>
{% if user.is_authenticated %}
<a href="{% url 'logout' %}">Logout</a>
{% else %}
<a href="{% url 'login' %}">Login</a>
{% endif %}
<a href="{% url 'signup' %}">SingUp</a>
</div>
<div class="container">
{% block content %}
{% endblock content %}
</div>
</body>
<html>
<style type="text/css">
.topnav {
background-color: #333;
overflow: hidden;
position: fixed;
top: 0;
width: 100%;
}
.topnav a {
float: left;
color: #f2f2f2;
text-align: center;
padding: 14px 16px;
text-decoration: none;
font-size: 17px;
font-family: sans-serif;
}
/* Change the color of links on hover */
.topnav a:hover {
background-color: #ddd;
color: black;
}
.topnav a.active {
background-color: #04AA6D;
color: white;
}
body {
background-color: #DEB887;
}
</style>
home.html
{% extends 'user_auth/base.html' %}
{% block content %}
<body>
<div class= "greeting">
<h1>Hello</h1>
<p> Welcome {{ user.username|default:'' }}, to the Our site</p>
</div>
</body>
<style>
.greeting {
color: #F0FFFF;
text-align: center;
font-family: sans-serif;
}
</style>
{% endblock content %}
在 templates/user_auth 中,我們創(chuàng)建了一個名為“registration”的文件夾嫉你。我們在其中創(chuàng)建了一個用于登錄月帝、注冊的模板和一個 form_base 模板。在 form_base 模板中均抽,我們添加了登錄和注冊模板將繼承的 HTML 和 CSS嫁赏。
form_base.html
HTML 和 CSS 是從Dennis Ivy的本教程中復(fù)制而來的。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Django Auth</title>
<link rel="preconnect" >
<link rel="preconnect" crossorigin>
<link rel="stylesheet">
<style>
body {
background-color: #DEB887;
font-family: 'Poppins', sans-serif;
padding-top: 50px;
}
h1,
h2,
h3,
h4,
h5,
h6,
{
font-family:'Raleway', sans-serif;
}
a,
p {
color: #4b5156
}
.container{
max-width: 550px;
margin: auto;
background-color: #FFEBCD;
-webkit-box-shadow: 2px 2px 13px -4px rgba(0,0,0,0.21);
box-shadow: 2px 2px 13px -4px rgba(0,0,0,0.21);
}
input {
outline: none;
border: none;
}
.header-bar {
display:flex;
justify-content:space-between;
color:#fff;
padding:10px;
border-radius:5px 5px 0 0;
background: #5F9EA0;
}
.header-bar a {
color: rgb(247,247,247);
text-decoration:none;
}
input[type=text],
input[type=password],
textarea {
border: 1px solid #757575;
border-radius: 5px;
padding: 10px;
width: 90%;
}
label {
padding-top: 10px !important;
display: block;
}
::placeholder {
font-weight: 300;
opacity: 0.5;
}
.button {
border: 1px solid #757575;
background-color: #FFF;
color: #EB796F;
padding: 10px;
font-size: 14px;
border-radius: 5px;
cursor: pointer;
text-decoration: none;
}
.card-body {
padding: 20px;
}
.topnav {
background-color: #333;
overflow: hidden;
position: fixed; /* Set the navbar to fixed position */
top: 0; /* Position the navbar at the top of the page */
width: 100%; /* Full width */
}
/* Style the links inside the navigation bar */
.topnav a {
float: left;
color: #f2f2f2;
text-align: center;
padding: 14px 16px;
text-decoration: none;
font-size: 17px;
font-family: sans-serif;
}
/* Change the color of links on hover */
.topnav a:hover {
background-color: #ddd;
color: black;
}
</style>
</head>
<body>
<div class="topnav">
<a href="{% url 'home' %}">Home</a>
{% if user.is_authenticated %}
<a href="{% url 'logout' %}">Logout</a>
{% else %}
<a href="{% url 'login' %}">Login</a>
{% endif %}
<a href="{% url 'signup' %}">SingUp</a>
</div>
<div class="container">
{% block content %}
{% endblock content %}
</div>
</body>
</html>
報名
from django.shortcuts import render
from django.urls import reverse_lazy
from django.contrib.auth.forms import UserCreationForm, AuthenticationForm
from django.views.generic.edit import CreateView
...
class SignUp(CreateView):
form_class = UserCreationForm
success_url = reverse_lazy("login")
template_name = "user_auth/registration/signup.html"
我們從CreateView
. 此類顯示用于創(chuàng)建對象的表單油挥,重新顯示帶有驗證錯誤(如果有的話)的表單潦蝇,并保存對象。對于這個類深寥,我們給UserCreationForm
一個值form_class
攘乒,這個表單根據(jù)給定的用戶名和密碼創(chuàng)建一個沒有權(quán)限的用戶。
注冊后惋鹅,用戶將被帶到登錄頁面则酝。我們template_name
給這個視圖模板的位置作為一個值。
signup.html
{% extends 'user_auth/registration/form_base.html' %}
{% block content %}
<div class="header-bar">
<h1>Sign Up</h1>
</div>
<div class="card-body">
<form method="POST">
{% csrf_token %}
<label>{{form.username.label}}</label>
{{form.username}}
<label>{{form.password1.label}}</label>
{{form.password1}}
<label>{{form.password2.label}}</label>
{{form.password2}}
<input style="margin-top:10px;" class="button" type="submit" value="Register">
</form>
<p>Already have an account?<a href="{% url 'login' %}">Login</a></p>
</div>
{% endblock %}
登錄
from django.shortcuts import render
from django.urls import reverse_lazy
from django.contrib.auth.forms import UserCreationForm, AuthenticationForm
from django.views.generic.edit import CreateView
...
class Login(LoginView):
form_class = AuthenticationForm
template_name = "user_auth/registration/login.html"
我們從LoginView
. 并使用AuthenticationForm
as a form_class
which 是用于登錄用戶的表單闰集。這里我們不定義success_url
沽讹,因為它已經(jīng)定義在settings.py
.
根據(jù)文檔,這就是LoginView
:
這是做什么的
LoginView
:如果通過 GET 調(diào)用武鲁,它會顯示一個 POST 到同一 URL 的登錄表單爽雄。稍后再詳細(xì)介紹。
如果使用用戶提交的憑據(jù)通過 POST 調(diào)用沐鼠,它會嘗試讓用戶登錄挚瘟。如果登錄成功,視圖將重定向到下一個指定的 URL饲梭。如果未提供 next乘盖,它會重定向到 settings.LOGIN_REDIRECT_URL(默認(rèn)為 /accounts/profile/)。如果登錄不成功憔涉,它會重新顯示登錄表單订框。
您有責(zé)任為登錄模板提供 HTML,默認(rèn)情況下稱為registration/login.html兜叨。這個模板被傳遞了四個模板上下文變量:
form:表示 AuthenticationForm 的 Form 對象布蔗。
next:登錄成功后重定向到的 URL藤违。這也可能包含一個查詢字符串。
site:當(dāng)前站點纵揍,根據(jù) SITE_ID 設(shè)置顿乒。如果您沒有安裝站點框架,這將被設(shè)置為 RequestSite 的一個實例泽谨,該實例從當(dāng)前的 HttpRequest 派生站點名稱和域璧榄。
site_name:site.name的別名。如果您沒有安裝站點框架吧雹,這將設(shè)置為 request.META['SERVER_NAME'] 的值骨杂。有關(guān)站點的更多信息,請參閱“站點”框架雄卷。
如果您不想調(diào)用模板registration/login.html搓蚪,您可以通過額外參數(shù)將template_name 參數(shù)傳遞給URLconf 中的as_view 方法。例如丁鹉,此 URLconf 行將使用 myapp/login.html 代替:
path('accounts/login/', auth_views.LoginView.as_view(template_name='myapp/login.html')),
login.html
{% extends 'user_auth/registration/form_base.html' %}
{% block content %}
<div class="header-bar">
<h1>Login</h1>
</div>
<div class="card-body">
<form method="POST">
{% csrf_token %}
{{form.as_p}}
<input class="button" type="submit" value="Login">
</form>
<p> Don't have an account?<a href="{% url 'signup' %}">Register</a></p>
</div>
{% endblock %}
密碼更改
from django.shortcuts import render
from django.urls import reverse_lazy
from django.contrib.auth.forms import UserCreationForm, AuthenticationForm, PasswordChangeForm
from django.views.generic.edit import CreateView
from django.contrib.auth.views import LoginView, LogoutView, PasswordChangeView
...
class PasswordChange(PasswordChangeView):
form_class = PasswordChangeForm
template_name = "user_auth/registration/password_change_form.html"
PasswordChangeView
允許用戶更改此密碼妒潭。這PasswordChangeForm
是一種允許用戶更改密碼的表單。
password_change.html
{% extends 'user_auth/registration/form_base.html' %}
{% block content %}
<div class="header-bar">
<h1>Password Change</h1>
</div>
<div class="card-body">
<form method="POST">
{% csrf_token %}
{{form.as_p}}
<input class="button" type="submit" value="Login">
</form>
</div>
{% endblock %}
home.html
{% extends 'user_auth/base.html' %}
{% block content %}
<body>
<div class= "greeting">
<h1> Welcome {{ user.username|default:'' }}, to the Django Auth site.</h1>
{% if user.is_authenticated %}
<p> Change you password<a href="{% url 'password_change' %}"> Here</a></p>
{% endif %}
</div>
</body>
<style>
.greeting {
color: #F0FFFF;
text-align: center;
font-family: sans-serif;
}
</style>
{% endblock content %}
結(jié)論
Django 允許我們使用其類基礎(chǔ)視圖非常輕松地為我們的項目創(chuàng)建身份驗證揣钦。PasswordResetView
此外雳灾,我們可以使用和使用電子郵件實現(xiàn)密碼重置PasswordResetForm
。這是一個優(yōu)勢冯凹,因為它允許我們在應(yīng)用程序的業(yè)務(wù)邏輯上投入更多時間谎亩。
感謝您花時間閱讀這篇文章。