Django自定义用户认证示例详解


Posted in Python onMarch 14, 2018

前言

Django附带的认证对于大多数常见情况来说已经足够了,但是如何在 Django 中使用自定义的数据表进行用户认证,有一种较为笨蛋的办法就是自定义好数据表后,使用OnetoOne来跟 Django 的表进行关联,类似于这样:

from django.contrib.auth.models import User
class UserProfile(models.Model):
 """
 用户账号表
 """
 user = models.OneToOneField(User)
 name = models.CharField(max_length=32)
 def __str__(self):
  return self.name
 class Meta:
  verbose_name_plural = verbose_name = "用户账号"
  ordering = ['id']

这样做虽然可以简单、快速的实现,但是有一个问题就是我们在自己的表中创建一个用户就必须再跟 admin 中的一个用户进行关联,这简直是不可以忍受的。

admin代替默认User model

写我们自定义的 models 类来创建用户数据表来代替默认的User model,而不与django admin的进行关联,相关的官方文档在这里

?戳我

from django.db import models
from django.contrib.auth.models import User
from django.contrib.auth.models import (
 BaseUserManager, AbstractBaseUser
)
class UserProfileManager(BaseUserManager):
 def create_user(self, email, name, password=None):
  """
  用户创建,需要提供 email、name、password
  """
  if not email:
   raise ValueError('Users must have an email address')
  user = self.model(
   email=self.normalize_email(email),
   name=name,
  )
  user.set_password(password)
  user.save(using=self._db)
  return user
 def create_superuser(self, email, name, password):
  """
  超级用户创建,需要提供 email、name、password
  """
  user = self.create_user(
   email,
   password=password,
   name=name,
  )
  user.is_admin = True
  user.is_active = True
  user.save(using=self._db)
  return user
class UserProfile(AbstractBaseUser):
 # 在此处可以配置更多的自定义字段
 email = models.EmailField(
  verbose_name='email address',
  max_length=255,
  unique=True,
 )
 name = models.CharField(max_length=32, verbose_name="用户名称")
 phone = models.IntegerField("电话")
 is_active = models.BooleanField(default=True)
 is_admin = models.BooleanField(default=False)
 objects = UserProfileManager()
 USERNAME_FIELD = 'email' # 将email 作为登入用户名
 REQUIRED_FIELDS = ['name', 'phone']
 def __str__(self):
  return self.email
 def get_full_name(self):
  # The user is identified by their email address
  return self.email
 def get_short_name(self):
  # The user is identified by their email address
  return self.email
 def has_perm(self, perm, obj=None):
  "Does the user have a specific permission?"
  # Simplest possible answer: Yes, always
  return True
 def has_module_perms(self, app_label):
  "Does the user have permissions to view the app `app_label`?"
  # Simplest possible answer: Yes, always
  return True
 @property
 def is_staff(self):
  "Is the user a member of staff?"
  # Simplest possible answer: All admins are staff
  return self.is_admin

admin 配置

class UserCreationForm(forms.ModelForm):
 """A form for creating new users. Includes all the required
 fields, plus a repeated password."""
 password1 = forms.CharField(label='Password', widget=forms.PasswordInput)
 password2 = forms.CharField(label='Password confirmation', widget=forms.PasswordInput)

 class Meta:
  model = models.UserProfile
  fields = ('email', 'name')

 def clean_password2(self):
  password1 = self.cleaned_data.get("password1")
  password2 = self.cleaned_data.get("password2")
  if password1 and password2 and password1 != password2:
   raise forms.ValidationError("Passwords don't match")
  return password2

 def save(self, commit=True):
  user = super(UserCreationForm, self).save(commit=False)
  user.set_password(self.cleaned_data["password1"])
  if commit:
   user.save()
  return user


class UserChangeForm(forms.ModelForm):
 """A form for updating users. Includes all the fields on
 the user, but replaces the password field with admin's
 password hash display field.
 """
 password = ReadOnlyPasswordHashField()
 class Meta:
  model = models.UserProfile
  fields = ('email', 'password', 'name', 'is_active', 'is_admin')
 def clean_password(self):
  return self.initial["password"]
class UserProfileAdmin(BaseUserAdmin):
 form = UserChangeForm
 add_form = UserCreationForm
 list_display = ('email', 'name', 'is_admin', 'is_staff')
 list_filter = ('is_admin',)
 fieldsets = (
  (None, {'fields': ('email', 'password')}),
  ('Personal info', {'fields': ('name',)}),
  ('Permissions', {'fields': ('is_admin', 'is_active', 'roles', 'user_permissions', 'groups')}),
 )
 add_fieldsets = (
  (None, {
   'classes': ('wide',),
   'fields': ('email', 'name', 'password1', 'password2')}
   ),
 )
 search_fields = ('email',)
 ordering = ('email',)
 filter_horizontal = ('groups', 'user_permissions','roles')

2.Django允许您通过AUTH_USER_MODEL配置来引用自定义的model设置来覆盖默认User模型,这个配置的配置方法为在 settings 中加入:AUTH_USER_MODEL = "APP.model_class" ,例如本例中我们需要在 setting 中加入以下配置:

AUTH_USER_MODEL = "app1.UserProfile"

3.部署

python manage.py makemigrations
python manage.py migrate

创建一个新用户,此时我们就可以用这个用户来登录 admin 后台了

python manage.py createsuperuser

效果如下:

Django自定义用户认证示例详解 

自定义认证

那如果我们需要使用我们自己的认证系统呢,假如我们有一个 login 页面和一个 home 页面:

from django.shortcuts import render, HttpResponse, redirect
from django.contrib.auth import authenticate,login,logout
from app1 import models
from django.contrib.auth.decorators import login_required

def auth_required(auth_type):
 # 认证装饰器
 def wapper(func):
  def inner(request, *args, **kwargs):
   if auth_type == 'admin':
    ck = request.COOKIES.get("login") # 获取当前登录的用户
    if request.user.is_authenticated() and ck:
     return func(request, *args, **kwargs)
    else:
     return redirect("/app1/login/")
  return inner
 return wapper

def login_auth(request):
 # 认证
 if request.method == "GET":
  return render(request, 'login.html')

 elif request.method == "POST":
  username = request.POST.get('username', None)
  password = request.POST.get('password', None)
  user = authenticate(username=username, password=password)
  if user is not None:
   if user.is_active:
    login(request, user)
    _next = request.GET.get("next",'/crm')
    return redirect('_next')
   else:
    return redirect('/app1/login/')
  else:
   return redirect('/app1/login/')
 else:
  pass
def my_logout(request):
 # 注销
 if request.method == 'GET':
  logout(request)
  return redirect('/app1/login/')

@login_required
def home(request):
 # home page
 path1, path2 = "Home", '主页'
 if request.method == "GET":
  return render(request, 'home.html', locals())
 elif request.method == "POST":
  pass

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对三水点靠木的支持。

Python 相关文章推荐
Python通过select实现异步IO的方法
Jun 04 Python
python简单线程和协程学习心得(分享)
Jun 14 Python
浅谈python中统计计数的几种方法和Counter详解
Nov 07 Python
python绘制BA无标度网络示例代码
Nov 21 Python
django在保存图像的同时压缩图像示例代码详解
Feb 11 Python
python词云库wordCloud使用方法详解(解决中文乱码)
Feb 17 Python
Python 读取xml数据,cv2裁剪图片实例
Mar 10 Python
基于python SMTP实现自动发送邮件教程解析
Jun 02 Python
详解python polyscope库的安装和例程
Nov 13 Python
Python爬取你好李焕英豆瓣短评生成词云的示例代码
Feb 24 Python
Flask搭建一个API服务器的步骤
May 28 Python
详解Python描述符的工作原理
Jun 11 Python
python如何压缩新文件到已有ZIP文件
Mar 14 #Python
python中format()函数的简单使用教程
Mar 14 #Python
Python批量提取PDF文件中文本的脚本
Mar 14 #Python
深入理解Django的中间件middleware
Mar 14 #Python
python批量设置多个Excel文件页眉页脚的脚本
Mar 14 #Python
浅谈python正则的常用方法 覆盖范围70%以上
Mar 14 #Python
Python使用matplotlib绘制多个图形单独显示的方法示例
Mar 14 #Python
You might like
php中get_object_vars()方法用法实例
2015/02/08 PHP
php文件上传 你真的掌握了吗
2016/11/28 PHP
jQuery下实现等待指定元素加载完毕(可改成纯js版)
2013/07/11 Javascript
JavaScript设计模式之建造者模式介绍
2014/12/28 Javascript
JavaScript简单修改窗口大小的方法
2015/08/03 Javascript
基于JavaScript实现Json数据根据某个字段进行排序
2015/11/24 Javascript
AngularJS基于provider实现全局变量的读取和赋值方法
2017/06/28 Javascript
vue 项目如何引入微信sdk接口的方法
2017/12/18 Javascript
vue单文件组件lint error自动fix与styleLint报错自动fix详解
2019/01/08 Javascript
vue踩坑记-在项目中安装依赖模块npm install报错
2019/04/02 Javascript
[05:40]DOTA2荣耀之路6:Wings最后进攻
2018/05/30 DOTA
python 字符串split的用法分享
2013/03/23 Python
Python单例模式实例分析
2015/01/14 Python
关于pip的安装,更新,卸载模块以及使用方法(详解)
2017/05/19 Python
Python通过Django实现用户注册和邮箱验证功能代码
2017/12/11 Python
python中的colorlog库使用详解
2019/07/05 Python
python 中值滤波,椒盐去噪,图片增强实例
2019/12/18 Python
详解利用python识别图片中的条码(pyzbar)及条码图片矫正和增强
2020/11/17 Python
python中复数的共轭复数知识点总结
2020/12/06 Python
Python3中的tuple函数知识点讲解
2021/01/03 Python
python Scrapy爬虫框架的使用
2021/01/21 Python
购买限量版收藏品、珠宝和礼品:Bradford Exchange
2016/09/23 全球购物
美国排名第一的泳池用品直接来源:In The Swim
2019/09/23 全球购物
.NET面试题:什么是反射
2016/09/30 面试题
大学生自荐信
2013/12/11 职场文书
餐饮业会计岗位职责
2013/12/19 职场文书
放飞蜻蜓反思
2014/02/05 职场文书
公司总经理岗位职责
2014/03/15 职场文书
全国文明单位申报材料
2014/05/31 职场文书
植树节标语
2014/06/27 职场文书
学校运动会报道稿
2014/09/23 职场文书
教师个人查摆剖析材料
2014/10/14 职场文书
校运会加油稿大全
2015/07/22 职场文书
运动会宣传稿50字
2015/07/23 职场文书
2015年语言文字工作总结
2015/07/23 职场文书
win10键盘驱动怎么修复?Win10键盘驱动修复小技巧
2022/04/06 数码科技