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 的列表遍历删除实现代码
Apr 12 Python
python对配置文件.ini进行增删改查操作的方法示例
Jul 28 Python
Python编程django实现同一个ip十分钟内只能注册一次
Nov 03 Python
Python实现桶排序与快速排序算法结合应用示例
Nov 22 Python
Python中那些 Pythonic的写法详解
Jul 02 Python
Python实现线性判别分析(LDA)的MATLAB方式
Dec 09 Python
使用python3 实现插入数据到mysql
Mar 02 Python
Spring Boot中使用IntelliJ IDEA插件EasyCode一键生成代码详细方法
Mar 20 Python
Windows下Anaconda安装、换源与更新的方法
Apr 17 Python
卸载tensorflow-cpu重装tensorflow-gpu操作
Jun 23 Python
python 自动化偷懒的四个实用操作
Apr 11 Python
python使用BeautifulSoup 解析HTML
Apr 24 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中数据的批量导入(csv文件)
2006/10/09 PHP
MySQL的FIND_IN_SET函数使用方法分享
2012/03/27 PHP
fetchAll()与mysql_fetch_array()的区别详解
2013/06/05 PHP
php连接函数implode与分割explode的深入解析
2013/06/26 PHP
PHP URL路由类实例
2013/11/12 PHP
使用PHP生成二维码的方法汇总
2015/07/22 PHP
PHP+Mysql+jQuery文件下载次数统计实例讲解
2015/10/10 PHP
Zend Framework实现Zend_View集成Smarty模板系统的方法
2016/03/05 PHP
PHP实现简单的计算器
2020/08/28 PHP
javascript对象的property和prototype是这样一种关系
2007/03/24 Javascript
建立良好体验度的Web注册系统ajax
2007/07/09 Javascript
JavaScript和ActionScript的交互实现代码
2010/08/01 Javascript
Js动态添加复选框Checkbox的实例方法
2013/04/08 Javascript
js控制分页打印、打印分页示例
2014/02/08 Javascript
jquery增加和删除元素的方法
2015/01/14 Javascript
详解addEventListener的三个参数之useCapture
2015/03/16 Javascript
JS实现仿新浪黄色经典滑动门效果代码
2015/09/27 Javascript
JS实现的页面自定义滚动条效果
2015/10/26 Javascript
BootStrap中的表单大全
2016/09/07 Javascript
jQuery实现背景滑动菜单
2016/12/02 Javascript
jQuery实现的背景颜色渐变动画效果示例
2017/03/24 jQuery
js实现华丽的九九乘法表效果
2017/03/29 Javascript
JavaScript引用类型之基本包装类型实例分析【Boolean、Number和String】
2018/08/09 Javascript
微信小程序新手教程之启动页的重要性
2019/03/03 Javascript
在vue中实现某一些路由页面隐藏导航栏的功能操作
2020/09/21 Javascript
使用Python实现下载网易云音乐的高清MV
2015/03/16 Python
Python编程中实现迭代器的一些技巧小结
2016/06/21 Python
Python简单定义与使用字典dict的方法示例
2017/07/25 Python
Python用Jira库来操作Jira
2020/12/28 Python
女装和独特珠宝:Sundance Catalog
2018/09/19 全球购物
乌克兰机票、铁路和巴士票、酒店搜索、保险:Tickets.ua
2020/01/11 全球购物
荷兰睡眠专家:Beter Bed
2020/11/23 全球购物
英语系毕业生自荐信
2013/10/31 职场文书
开工典礼策划方案
2014/05/23 职场文书
行政处罚告知书
2015/07/01 职场文书
解决Laravel使用验证时跳转到首页的问题
2021/11/17 PHP