我们可以使用 Django 身份验证系统为我们的项目构建身份验证。
先决条件:
- Python
- OOP
- Django 基础知识(Django 模板、视图、URL、设置)
这是 Django文档中关于其身份验证系统的说明:
Django 在其默认配置中的身份验证系统。这种配置已经发展到满足最常见的项目需求,处理相当广泛的任务,并仔细实现了密码和权限。对于身份验证需求与默认不同的项目,Django 支持广泛的身份验证扩展和自定义。
Django 身份验证同时提供身份验证和授权,通常称为身份验证系统,因为这些功能有些耦合。
我们将使用身份验证视图和内置表单来创建这个应用程序。该应用程序将执行的操作是:
- 用户注册
- 登录
- 登出
- 密码更改
设置
让我们开始为我们的项目创建一个文件夹,然后我们创建一个虚拟环境,并激活它:
mkdir django_authentication
cd django auth
py -m venv venv
cd venv/Scripts
activate
现在我们安装 Django:
pip install django
我们创建一个 django 项目:
django_admin startproject django_authentication
cd django_authentication
现在我们创建我们的应用程序:
py manage.py startapp user_auth
我们必须添加我们的应用程序,django_authentication/settings.py
并且我们的应用程序将在用户登录或注销时重定向用户的 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',
]
将应用添加到 后INSTALLED_APPS
,我们在终端中使用以下命令运行迁移:
py manage.py migrate
根据文档:
当 django.contrib.auth 在您的 INSTALLED_APPS 设置中列出时,它将确保为您安装的应用程序之一中定义的每个 Django 模型创建四个默认权限 - 添加、更改、删除和查看。
这些权限将在您运行manage.py migrate 时创建;在将 django.contrib.auth 添加到 INSTALLED_APPS 后第一次运行 migrate 时,将为所有以前安装的模型以及当时正在安装的任何新模型创建默认权限。之后,它会在每次运行manage.py migrate 时为新模型创建默认权限(创建权限的函数连接到 post_migrate 信号)。
我们将实现 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']
我们运行以下命令来运行服务器:
py manage.py runserver
在user_auth
目录中,我们创建一个文件夹来存储我们应用的模板。
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")
这里我们只写一个函数来渲染home.html
我们必须urls.py
在我们的应用程序目录中创建一个文件来添加我们将创建的视图的 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
现在我们必须在项目文件中包含 user_auth 应用程序 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')),
]
我们创建了两个模板。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 中,我们创建了一个名为“registration”的文件夹。我们在其中创建了一个用于登录、注册的模板和一个 form_base 模板。在 form_base 模板中,我们添加了登录和注册模板将继承的 HTML 和 CSS。
form_base.html
HTML 和 CSS 是从Dennis Ivy的本教程中复制而来的。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Django Auth</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Poppins:wght@300&display=swap" 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
. 此类显示用于创建对象的表单,重新显示带有验证错误(如果有的话)的表单,并保存对象。对于这个类,我们给UserCreationForm
一个值form_class
,这个表单根据给定的用户名和密码创建一个没有权限的用户。
注册后,用户将被带到登录页面。我们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
,因为它已经定义在settings.py
.
根据文档,这就是LoginView
:
这是做什么的
LoginView
:如果通过 GET 调用,它会显示一个 POST 到同一 URL 的登录表单。稍后再详细介绍。
如果使用用户提交的凭据通过 POST 调用,它会尝试让用户登录。如果登录成功,视图将重定向到下一个指定的 URL。如果未提供 next,它会重定向到 settings.LOGIN_REDIRECT_URL(默认为 /accounts/profile/)。如果登录不成功,它会重新显示登录表单。
您有责任为登录模板提供 HTML,默认情况下称为registration/login.html。这个模板被传递了四个模板上下文变量:
form:表示 AuthenticationForm 的 Form 对象。
next:登录成功后重定向到的 URL。这也可能包含一个查询字符串。
site:当前站点,根据 SITE_ID 设置。如果您没有安装站点框架,这将被设置为 RequestSite 的一个实例,该实例从当前的 HttpRequest 派生站点名称和域。
site_name:site.name的别名。如果您没有安装站点框架,这将设置为 request.META['SERVER_NAME'] 的值。有关站点的更多信息,请参阅“站点”框架。
如果您不想调用模板registration/login.html,您可以通过额外参数将template_name 参数传递给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 %}
结论
Django 允许我们使用其类基础视图非常轻松地为我们的项目创建身份验证。PasswordResetView
此外,我们可以使用和使用电子邮件实现密码重置PasswordResetForm
。这是一个优势,因为它允许我们在应用程序的业务逻辑上投入更多时间。
感谢您花时间阅读这篇文章。