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学习笔记之常用函数及说明
May 23 Python
安装ElasticSearch搜索工具并配置Python驱动的方法
Dec 22 Python
numpy排序与集合运算用法示例
Dec 15 Python
[原创]python爬虫(入门教程、视频教程)
Jan 08 Python
关于Python正则表达式 findall函数问题详解
Mar 22 Python
python监测当前联网状态并连接的实例
Dec 18 Python
Python循环中else,break和continue的用法实例详解
Jul 11 Python
python使用百度文字识别功能方法详解
Jul 23 Python
pytorch实现线性拟合方式
Jan 15 Python
Python Scrapy框架第一个入门程序示例
Feb 05 Python
浅谈python 中的 type(), dtype(), astype()的区别
Apr 09 Python
python中 _、__、__xx__()区别及使用场景
Jun 30 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
网站当前的在线人数
2006/10/09 PHP
php的memcached客户端memcached
2011/06/14 PHP
php中使用preg_match_all匹配文章中的图片
2013/02/06 PHP
做了CDN获取用户真实IP的函数代码(PHP与Asp设置方式)
2013/04/13 PHP
PHP jQuery表单,带验证具体实现方法
2014/02/15 PHP
PHP获取网页所有连接的方法(附demo源码下载)
2016/03/30 PHP
thinkphp5框架前后端分离项目实现分页功能的方法分析
2019/10/08 PHP
PHP实现倒计时功能
2020/11/16 PHP
JavaScript的Cookies
2008/01/16 Javascript
javascript 二分法(数组array)
2010/04/24 Javascript
javascript相等运算符与等同运算符详细介绍
2013/11/09 Javascript
用Jquery.load载入页面实现局部刷新
2014/01/22 Javascript
JS检测输入字符是否包含非法字符的示例代码
2014/02/11 Javascript
jQuery绑定事件-多种实现方式总结
2016/05/09 Javascript
jQuery实现图片轮播效果代码(基于jquery.pack.js插件)
2016/06/02 Javascript
JS制作类似选项卡切换的年历
2016/12/03 Javascript
vue-cli webpack 开发环境跨域详解
2017/05/18 Javascript
js与jQuery实现获取table中的数据并拼成json字符串操作示例
2018/07/12 jQuery
解决angular2在双向数据绑定时[(ngModel)]无法使用的问题
2018/09/13 Javascript
详解webpack引用jquery(第三方模块)的三种办法
2019/08/21 jQuery
关于better-scroll插件的无法滑动bug(2021通过插件解决)
2021/03/01 Javascript
Python进阶学习之特殊方法实例详析
2017/12/01 Python
Python文本处理之按行处理大文件的方法
2018/04/09 Python
Python爬虫框架scrapy实现downloader_middleware设置proxy代理功能示例
2018/08/04 Python
Python 多线程C段扫描、检测 Ping扫描脚本的实现
2020/09/03 Python
python中的时区问题
2021/01/14 Python
python re模块常见用法例举
2021/03/01 Python
blueseventy官网:铁人三项和比赛泳衣
2021/02/06 全球购物
会议邀请函范文
2014/01/09 职场文书
新学期家长寄语
2014/01/19 职场文书
大学生作弊检讨书
2014/02/19 职场文书
大学本科生职业生涯规划书范文
2014/09/14 职场文书
参观邀请函范文
2015/02/02 职场文书
小组组名及励志口号
2015/12/24 职场文书
学生早退检讨书(范文)
2019/08/19 职场文书
shell进度条追踪指令执行时间的场景分析
2022/06/16 Servers