1. 概述

Django 中的 django.contrib.auth 应用提供了完整的用户及认证授权功能。

Django 官方推荐基于内置 User 数据模型创建新的自定义用户模型,方便添加 birthday 等新的用户字段和功能。

本文包含的内容有:

  • 介绍在 Django 中如何自定义用户模型,并集成到系统。
  • 定制 django.contrib.auth 应用使用的模板文件。
  • 在系统中集成认证与授权功能。

以下所有示例在 Python 3.8.2 + Django 2.1 中实现。

2. 自定义用户模型

2.1. 创建认证与授权相关的单独应用 accounts

  1. $ python manage.py startapp accounts

将应用添加到项目中:

  1. # project_dir/settings.py
  2. INSTALLED_APPS = [
  3. # Local
  4. 'accounts.apps.AccountsConfig',
  5. #...
  6. ]

2.2. 创建自定义用户模型 CustomUser

Django 官方文档中推荐基于 AbstractBaseUser 创建自定义用户模型,但是一般基于 AbstractUser 创建再方便。

本命中的自定义 CustomUser 中新增了字段 birthday。

  1. # accounts/models.py
  2. from django.db import models
  3. from django.contrib.auth.models import AbstractUser
  4. class CustomUser(AbstractUser):
  5. birthday = models.DateField(null=True, blank=True)

2.3. 集成自定义用户模型

通过 AUTH_USER_MODEL 告诉系统新的用户模型:

  1. # project_dir/settings.py
  2. AUTH_USER_MODEL = 'accounts.CustomUser'

之后可通过 get_user_model() 获取该自定义用户模型:

  1. # in view or model files
  2. from django.contrib.auth import get_user_model
  3. CustomUser = get_user_model()

django.contrib.auth 应用已实现了完整的 login, logout 功能,并已在 django.contrib.auth.urls 中定义了 login, logout, password_change, password_change_done, password_reset, password_reset_done, password_reset_confirm, password_reset_complete 等 URL。

django.contrib.auth.urls 集成到项目中:

  1. # project_dir/urls.py
  2. from django.urls import path, include
  3. urlpatterns = [
  4. path('accounts/', include('django.contrib.auth.urls'),
  5. #...
  6. ]

集成后,即可访问 /accounts/login/, /accounts/logout/, /accounts/password_change/ 等功能,同时时视图和模板中也可访问这个 URL 定义:

  1. <!-- in template files -->
  2. <a href="{% url 'login' %}">Login URL</a>
  1. # in view files
  2. from django.urls import reverse, reverse_lazy
  3. login_url = reverse('login')
  4. #in Class Based View:
  5. login_url = reverse_lazy('login')

2.4. 集成自定义用户模型到后台管理界面

后台管理界面中,添加新用户时呈现的表单由 django.contrib.auth.forms.UserCreationForm 提供,而更新用户时呈现的表单由 django.contrib.auth.forms.UserChangeForm 提供。

为自定义用户模型定制这两个表单:

  1. # accounts/forms.py
  2. from django.contrib.auth.forms import UserCreationForm, UserChangeForm
  3. from .models import CustomUser
  4. class CustomUserCreationForm(UserCreationForm):
  5. class Meta(UserCreationForm.Meta):
  6. model = CustomUser
  7. fields = ('username', 'email', 'birthday', )
  8. class CustomUserChangeForm(UserChangeForm):
  9. class Meta(UserChangeForm.Meta):
  10. model = CustomUser
  11. fields = UserChangeForm.Meta.fields + ( 'birthday', )

注册到 admin 中:

  1. # accounts/admin.py
  2. from django.contrib import admin
  3. from django.contrib.auth.admin import UserAdmin
  4. from .models import CustomUser
  5. from .forms import CustomUserCreationForm, CustomUserChangeForm
  6. class CustomUserAdmin(UserAdmin):
  7. model = CustomUser
  8. add_form = CustomUserCreationForm
  9. form = CustomUserChangeForm
  10. list_display = ['email', 'username', 'birthday', 'is_staff']
  11. admin.site.register(CustomUser, CustomUserAdmin)

3. 定制 django.contrib.auth 应用使用的模板文件

3.1. 定义模板文件

django.contrib.auth 中 login, logout, password_change, password_change_done, password_reset, password_reset_done, password_reset_confirm, password_reset_complete 等视图,访问的相应模板需保存在registration/ 目录下,模板文件有: login.html, password_change_done.html, password_change_form.html, password_reset_complete.html, password_reset_confirm.html, password_reset_done.html, password_reset_form.html 等。

默认配置下,模板文件需保存在 <app-name>/templates/<app-name>/registration/ 目录下,如 accounts/templates/accounts/registration/login.html

对于小项目,可以将模板目录设置为扁平化:

  1. # project_dir/settings.py
  2. TEMPLATES = [
  3. {
  4. 'BACKEND': 'django.template.backends.django.DjangoTemplates',
  5. 'DIRS': [os.path.join(BASE_DIR, 'templates')], # new
  6. #...
  7. }
  8. ]

从而模板可以保存在 templates/ 目录中,如 templates/registration/login.html

模板中可使用 form 变量,例如:

  1. <!-- templates/registration/login.html -->
  2. {% extends 'base.html' %}
  3. {% block title %}Login{% endblock title %}
  4. {% block content %}
  5. <h2>Login</h2>
  6. <form method="post">
  7. {% csrf_token %}
  8. {{ form.as_p }}
  9. <button class="btn btn-success ml-2" type="submit">Login</button>
  10. </form>
  11. {% endblock content %}

3.2. 创建注册功能

django.contrib.auth 没有实现 sign up 功能。

基于 CreateView 创建 SignUpView 视图:

  1. # accounts/views.py
  2. from django.views.generic.edit import CreateView
  3. from django.urls import reverse_lazy
  4. from .models import CustomUser
  5. from .forms import CustomUserCreationForm
  6. class SignupView(CreateView):
  7. #model = CustomUser
  8. form_class = CustomUserCreationForm
  9. template_name = 'signup.html'
  10. success_url = reverse_lazy('login')

添加模板文件:

  1. <!-- templates/signup.html -->
  2. {% extends 'base.html' %}
  3. {% load crispy_forms_tags %}
  4. {% block title %}Signup{% endblock title %}
  5. {% block content %}
  6. <h2>Signup</h2>
  7. <form method="post">
  8. {% csrf_token %}
  9. {{ form|crispy }}
  10. <button class="btn btn-success" type="submit">Signup</button>
  11. </form>
  12. {% endblock content %}

添加应用级别的 URL 配置:

  1. # accounts/urls.py
  2. from django.urls import path
  3. from .views import SignUpView
  4. urlpatterns = [
  5. path('signup/', SignUpView.as_view(), name='signup'),
  6. ]

集成到项目级别的 URL 配置中:

  1. # project_dir/urls.py
  2. urlpatterns = [
  3. path('admin/', admin.site.urls),
  4. path('accounts/', include('accounts.urls')),
  5. path('accounts/', include('django.contrib.auth.urls')),
  6. #...
  7. ]

4. 在系统中集成认证与授权功能

4.1. 认证:要求登录后才能访问

视图应继承加入 LoginRequiredMixin,属性值 login_url 设置当没有登录时,将转向的登录页面地址或 URL name:

  1. # in view files
  2. from django.views.generic.edit import DeleteView
  3. from django.urls import reverse_lazy
  4. from django.contrib.auth.mixins import LoginRequiredMixin
  5. from django.core.exceptions import PermissionDenied
  6. from .models import Article
  7. class ArticleDeleteView(LoginRequiredMixin, DeleteView):
  8. model = Article
  9. template_name = 'article_delete.html'
  10. success_url = reverse_lazy('article_list')
  11. login_url = 'login'

4.2. 授权:只有特定的用户或权限才能访问

CBV 中,代码调用入口是 dispatch() 方法,可以在该方法中实现权限验证,当权限不够时抛出异常:

  1. # in view files
  2. from django.views.generic.edit import DeleteView
  3. from django.urls import reverse_lazy
  4. from django.contrib.auth.mixins import LoginRequiredMixin
  5. from django.core.exceptions import PermissionDenied
  6. from .models import Article
  7. class ArticleDeleteView(LoginRequiredMixin, DeleteView):
  8. model = Article
  9. template_name = 'article_delete.html'
  10. success_url = reverse_lazy('article_list')
  11. login_url = 'login'
  12. def dispatch(self, request, *args, **kwargs):
  13. obj = self.get_object()
  14. if obj.author != request.user:
  15. raise PermissionDenied()
  16. return super().dispatch(request, *args, **kwargs)

资源

Django 中自定义用户模型及集成认证授权功能总结的更多相关文章

  1. 阶段5 3.微服务项目【学成在线】_day18 用户授权_10-前端集成认证授权-需求分析

    4 前端集成认证授权 4.1 需求分析 截至目前认证授权服务端的功能已基本完成,本章实现前端集成认证授权功能. 前端集成认证授权功能需要作如下工作: 1.前端页面校验用户的身份,如果用户没有登录则跳转 ...

  2. Django自定义用户认证系统之自定义用户模型

    参考文档:http://python.usyiyi.cn/django/topics/auth/customizing.html Django 自带的认证系统足够应付大多数情况,但你或许不打算使用现成 ...

  3. 5 项目---自定义用户模型以及轮播图图片url返回格式

    创建自定义的用户模型类  1. 用命令创建users 应用 2. 将users 注册到settings.py INSTALLED_APPS = [ 'django.contrib.admin', 'd ...

  4. Django之重写用户模型

    django——重写用户模型 Django内建的User模型可能不适合某些类型的项目.例如,在某些网站上使用邮件地址而不是用户名作为身份的标识可能更合理. 1.修改配置文件,覆盖默认的User模型 D ...

  5. Django1.5 自定义用户模型(总结)

    Django系统有自带的超级棒的认证机制,但是默认的用户模型有一点捉急,为了自定义用户模型,看了很多相关的文章,这里做一个总结: 你可以先看一下这篇,对Django的用户模型有一个比较全的了解: 来自 ...

  6. django中添加用户

    在django中添加用户,直接在auth_user表中添加会有问题,因为这里密码是加密的,可以通过manage.py shell加入 创建User: 1 >>> from djang ...

  7. 解决在django中应用keras模型时出现的ValueError("Tensor %s is not an element of this graph." % obj)问题

    用keras训练好模型,再在django初始化加载模型,这个过程没有问题,但是在调用到模型执行model.predict()的时候就报错: raise ValueError("Tensor ...

  8. .net core gRPC与IdentityServer4集成认证授权

    前言 随着.net core3.0的正式发布,gRPC服务被集成到了VS2019.本文主要演示如何对gRPC的服务进行认证授权. 分析 目前.net core使用最广的认证授权组件是基于OAuth2. ...

  9. YII2中自定义用户认证模型,完成登陆和注册

    有些时候我们需要自已定义用户类,操作自已建的用户表,来完成登陆和注册功能. 用户表结构如下,当然可以根据自已的需要添加或删除: CREATE TABLE `tb_user` ( `id` int(11 ...

随机推荐

  1. LeetCode Day 6

    LeetCode0006 将一个给定字符串根据给定的行数,以从上往下.从左到右进行 Z 字形排列. 比如输入字符串为 "LEETCODEISHIRING" ,指定行数为 3 时,排 ...

  2. inventor安装未完成,某些产品无法安装的解决方法

    inventor提示安装未完成,某些产品无法安装该怎样解决呢?,一些朋友在win7或者win10系统下安装inventor失败提示inventor安装未完成,某些产品无法安装,也有时候想重新安装inv ...

  3. 用css3实现图片的放大缩小

    记录一个公用的css实现图片的放大缩小 @keyframes scaleDraw { /*定义关键帧.scaleDrew是需要绑定到选择器的关键帧名称*/ 0%{ transform: scale(1 ...

  4. unittest(13)- 从配置文件中读取测试数据

    case.config # 1. http_request.py import requests class HttpRequest: def http_request(self, url, meth ...

  5. The Monster(Codeforce-C-思维题)

    C. The Monster time limit per test 1 second memory limit per test 256 megabytes   As Will is stuck i ...

  6. Docker Linux下安装

    下载脚本并运行安装: sudo wget -qO- https://get.docker.com/ | sh wget:下载文件工具, -q:不显示指令执行过程, -O-:-O-以'-'作为file参 ...

  7. ant:如何用ant将web project打包成war包

    说明:src中的文件将不会呈现出来,诸位可以自己写一个简单的web项目,然后依照我所提供的ant脚本配置来设置. 文件结构如图所示:               配置为下: build.xml < ...

  8. angular知识点(2)

    angular知识点(2) 1.为了代码规范,对于需要自动加载的依赖,需要在前面加上注释,注释为://@ngInject 或者是/*@ngInject*/ 2.ngSwitch的应用 在需要用到选择出 ...

  9. 微软手机 能靠Surface Phone卷土重来吗?

    能靠Surface Phone卷土重来吗?" title="微软手机 能靠Surface Phone卷土重来吗?"> 就算整体大环境再好,就算是站在风口之上,也总是 ...

  10. Ueditor富文本编辑器--Ctrl V 粘贴后原有图片显示错误

    最近负责将公司官网从静态网站改版成动态网站,方便公司推广营销人员修改增加文案,避免官网文案维护过于依赖技术人员.在做后台管理系统时用到了富文本编辑器Ueditor,因为公司有一个阿里云文件资源服务器, ...