Python:使用 Django 身份验证系统构建身份验证应用程序

我们可以使用 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:

settings.py

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

views.py

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>

报名

Views.py

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. 并使用AuthenticationFormas a form_classwhich 是用于登录用户的表单。这里我们不定义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 %}

密码更改

views.py

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。这是一个优势,因为它允许我们在应用程序的业务逻辑上投入更多时间。

感谢您花时间阅读这篇文章。

文章来源:https://carlosmv.hashnode.dev/building-an-authentication-app-with-django-authentication-system-python

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,036评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,046评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,411评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,622评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,661评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,521评论 1 304
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,288评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,200评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,644评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,837评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,953评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,673评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,281评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,889评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,011评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,119评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,901评论 2 355

推荐阅读更多精彩内容