Django自带用户认证系统,这个系统支持访问控制、注册用户、关联创建者和内容等;在开发用户认证功能时的时候,可以使用django中的django.contrib.auth 中封裝了注册、认证,登录登出方法,可以直接使用;
相关表
在使用"python manage.py makemigrations“和”python manage.py migrate"迁移完成数据库之后根据配置文件settings.py中的数据库段生成的数据表中已经包含了6张进行认证的数据表,分别是:
auth_user
auth_group
auth_group_permissions
auth_permission
auth_user_groups
auth_user_user_permissions
自带用户认证系统,进行用户认证的数据表为auth_user(用户的数据保存在这个表里)。
一、登陆功能:
authenticate():提供了用户认证,即验证用户名以及密码是否正确,一般需要username和password两个关键字参数
如果通过认证,authenticate()函数会返回一个User对象。当我们试图登陆一个从数据库中直接取出来不经过authenticate()的User对象时会报错。
1.登陆 auth.authenticate(username=name值, password=password值)
2.验证用户名和密码 auth.login(request, user) 这个函数使用Django的session框架给某个已认证的用户附加上session_id信息。
from django.shortcuts import render,redirect,HttpResponse
from django.contrib.auth import authenticate,login
def auth_view(request):
username=request.POST.GET("usernmae") # 获取用户名
password=request.POST.GET("password") # 获取用户的密码
user=authenticate(username=username,password=password) # 验证用户名和密码,返回用户对象
if user: # 如果用户对象存在
login(request,user) # 用户登陆
return redirect("/index/")
else:
return HttpResponse("用户名或密码错误")
当用户登陆成功时,会生成一个sessionid保存在cookies中,可以在数据库django_session中查看,当用户访问其他页面时,可以通过sessionid判断用户是否已经登陆。
二、注册功能
django自带User模型,导入方法:from django.contrib.auth.models import User
User是auth模块中维护用户信息的关系模式,在数据库中被命名为auth_user,使用migrate会自动生成.
1.user对象
User对象属性:username,password为必填项
password用哈希算法保存到数据库中
is_staff:判断用户是否拥有网站的管理权限
is_active:判断是否允许用户登陆,设置为“False”时可以不用删除用户来禁止用户登陆
用create_user辅助函数创建用户
create_user是django封装好的用于创建用户的方法(注意使用该方法注册的用户才能处理密码明文存密文到数据库的问题),
创建方法:User.objects.create_user(username=name, password=password)此处的User是django中自带的User模型from django.contrib.auth.models import User
def regist(request):
name = request.POST.get('name')
password = request.POST.get('password')
User.objects.create_user(username=name, password=password)
...
三、退出登陆auth.logout(request)
这个函数接受一个HttpResponse对象,无返回值。当调用该函数时,当前请求的session信息全部被清除。即使当前用户没有登陆,调用该函数也不会报错。
def logout(request):
if request.method == 'GET':
auth.logout(request)
四、登陆态验证
login_required() 若在访问某页面时,需要确认用户登陆成功才能访问,可以在url中用login_required方法进行验证,如果登陆成功就执行,如果用户未登陆,自动跳转登陆页面。
a. login_requierd() 装饰器
配置跳转路径,,当用户未登陆访问其他页面时,自动跳转到指定的url
url(r'^index/', login_required(views.index)),
url(r'^addstu/', login_required(views.addStu), name='astu'),
url(r'^stupage/', login_required(views.stuPage)),
值得注意的是,一旦加上login_required方法,在用户未登陆时访问页面会出现如下的404错误,所需还需要在setting.py进行配置LOGIN_URL。
配置跳转路径,当用户未登陆访问其他页面时,自动跳转到登陆页面LOGIN_URL = '/login/'
装饰器也可以加到view方法前
from django.contrib.auth.decorators import login_required
@login_required
def views(request):
pass
五、修改存储自定义认证中的User表
用户也可以不使用自带用户认证系统默认的数据表auth_user,通过以下方式可以将用户数据保存到自己定义的表中
from django.contrib.auth.models import User
class UserProfile(models.Model):
user = models.OneToOneField(User,on_delete=models.CASCADE) # django自带用户表User模块和自定义的用户关联
name = models.CharField(max_length=32)
def __str__(self):
return self.name
六、自定义用户认证系统
Django 自带的用户认证系统已经可以满足大部分的情况,但是有时候我们需要某些特定的需求。Django 支持使用其他认证系统、也可以扩展Django的User模块,完全自定义新的认证模块。
参考:https://docs.djangoproject.com/en/2.0/topics/auth/customizing/
a、拷贝以下代码到model文件中:
from django.db import models
from django.contrib.auth.models import (
BaseUserManager, AbstractBaseUser
)
class MyUserManager(BaseUserManager):
def create_user(self, email, name, password=None):
"""
Creates and saves a User with the given email, date of
birth and 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):
"""
Creates and saves a superuser with the given email, date of
birth and password.
"""
user = self.create_user(
email,
password=password,
name=name,
)
user.is_admin = 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)
is_active = models.BooleanField(default=True)
is_admin = models.BooleanField(default=False)
objects = MyUserManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['name']
def __str__(self):
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
email, name等字段都是可以自定义的
b、在admin.py中添加如下代码:
from django import forms
from django.contrib import admin
from django.contrib.auth.models import Group
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
from django.contrib.auth.forms import ReadOnlyPasswordHashField
from customauth.models import MyUser
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 = MyUser
fields = ('email', 'date_of_birth')
def clean_password2(self):
# Check that the two password entries match
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):
# Save the provided password in hashed format
user = super().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 = MyUser
fields = ('email', 'password', 'date_of_birth', 'is_active', 'is_admin')
def clean_password(self):
# Regardless of what the user provides, return the initial value.
# This is done here, rather than on the field, because the
# field does not have access to the initial value
return self.initial["password"]
class UserAdmin(BaseUserAdmin):
# The forms to add and change user instances
form = UserChangeForm
add_form = UserCreationForm
# The fields to be used in displaying the User model.
# These override the definitions on the base UserAdmin
# that reference specific fields on auth.User.
list_display = ('email', 'date_of_birth', 'is_admin')
list_filter = ('is_admin',)
fieldsets = (
(None, {'fields': ('email', 'password')}),
('Personal info', {'fields': ('date_of_birth',)}),
('Permissions', {'fields': ('is_admin',)}),
)
# add_fieldsets is not a standard ModelAdmin attribute. UserAdmin
# overrides get_fieldsets to use this attribute when creating a user.
add_fieldsets = (
(None, {
'classes': ('wide',),
'fields': ('email', 'date_of_birth', 'password1', 'password2')}
),
)
search_fields = ('email',)
ordering = ('email',)
filter_horizontal = ()
# Now register the new UserAdmin...
admin.site.register(MyUser, UserAdmin)
# ... and, since we're not using Django's built-in permissions,
# unregister the Group model from admin.
admin.site.unregister(Group)
C、 在settings.py中添加配置:
AUTH_USER_MODEL = 'customauth.MyUser' #customauth指APP name, MyUser指自定义的用户表model类
(这个时候仍然可以使用django.contrib.auth import authenticate,login,logout 等认证方法,只是保存数据的表不一样)
D、创建超级用户
首先我们要新建一个用户名,用来登陆管理网站,可以使用如下命令:
python manage.py createsuperuser
输入想要使用的用户名:
Username (leave blank to use ‘administrator’): user01
输入email:
Email address: (在这里输入你的自己的邮箱帐号)
输入密码,需要输入两次,并且输入密码时不会显示出来:
Password:
Password (again):
当两次密码都相同的时候,就会提示超级帐号创建成功。
Superuser created successfully.
xadmin常用样式功能
参考博客:https://blog.csdn.net/weixin_42042680/article/details/84799260
Xadmin站点的详细配置
import xadmin
from xadmin import viewsclass BaseSetting(object):
"""xadmin的基本配置"""
enable_themes = True # 开启主题切换功能
use_bootswatch = True # 支持切换主题
xadmin.site.register(views.BaseAdminView, BaseSetting)
class GlobalSettings(object):
"""xadmin的全局配置"""
site_title = "xxx后台管理系统" # 设置站点标题
site_footer = "xxxxxxx" # 设置站点的页脚
menu_style = "accordion" # 设置菜单折叠,在左侧,默认的
# 设置models的全局图标, UserProfile, Sports 为表名
global_search_models = [UserProfile, Sports]
global_models_icon = {
UserProfile: "glyphicon glyphicon-user", Sports: "fa fa-cloud"
xadmin.site.register(views.CommAdminView, GlobalSettings)
xadmin 详细配置
xadmin 可以使用的页面样式控制基本与Django原生的admin一直。
按日期、月份筛选
date_hierarchy = "date"
list_display 列表展示的字段
preserve_filters 默认情况下,当你对目标进行创建、编辑或删除操作后,页面会依然保持原来的过滤状态。将preserve_filters设为False后,则会返回未过滤状态。
prepopulated_fields 设置预填充字段。不接收DateTimeField、ForeignKey和ManyToManyField类型的字段。
view_on_site 这个属性可以控制是否在admin页面显示“View site”的链接。这个链接主要用于跳转到你指定的URL页面。
free_query_filter 属性: 默认为 True , 指定是否可以自由搜索. 如果开启自由搜索, 用户可以通过 url 参数来进行特定的搜索,
search_fields 可以通过搜索框搜索的字段名称,xadmin使用的是 模糊查询,存在外键 同 list_filter 一样 注意:只能包括 字符类型,不能有 非字符类型 如:SBBH-20180515-0002
list_filter 可以进行过滤操作的列,例如:存在外键字段class --->student__class 获取值
ordering 默认排序的字段
readonly_fields 在编辑页面的只读字段
exclude 在编辑页面隐藏的字段
list_editable 在列表页可以快速直接编辑的字段
show_detail_fileds 在列表页显示详情信息
refresh_times 指定列表页的数据定时刷新 例如:refresh_times=(3,5)
list_export 控制列表页导出数据的类型
show_bookmarks 控制是否显示书签功能
data_charts 控制显示图标的样式
model_icon 配置表的图标,可以在 awesome 上下载最新的font-awesome.css 替换,并寻找相应的icon书写
Fieldsets 详细页面时,使用fieldsets标签对数据进行分割显示
empty_value_display = "列数据为空时,显示默认值"
列聚合,可用的值:"count","min","max","avg", "sum"
aggregate_fields = {"expire": "max"}
显示还原按钮,删除修改的信息可以还原
reversion_enable = True
添加数据时候,一步一步提供数据
> wizard_form_list = [
> ("基础信息", ("name", "contact", "telphone", "address")),
> ("其它信息", ("customer_id", "expire", "description")), ]
fields 表单显示内容, 不包含在内的字段不能编辑
filter_horizontal 从‘多选框’的形式改变为‘过滤器’的方式,水平排列过滤器,必须是一个 ManyToManyField类型,且不能用于 ForeignKey字段,默认地,管理工具使用下拉框 来展现外键 字段
raw_id_fields 将ForeignKey字段从‘下拉框’改变为‘文本框’显示
relfield_style 后台自定义不是下拉选择框,而是搜索框(解决了为什么用户不是下拉框的问题。。) relfield_style = 'fk-ajax'
exclude 在编辑和查看列表时指定不显示的字段
list_editable 列表显示的时候,指定的字段可以直接页面一键编辑
list_display_links 设置默认可编辑字段
list_per_page = 20 每页显示20个
actions = ('ocr_action', 'excel_action', 'auto_excel_action') 在类中自定义的函数方法
auto_excel_action.short_description='自动化导入数据文件' 函数名描述
object_list_template = "test.html" 自定义页面
data_charts 图表,该属性为dict类型,key为图表的标示名称,value为图表的具体设置属性
data_charts = {
"user_count": {'title': u"约运动",
"x-field": "sport_time",
"y-field": ("people_nums",),
},
}
图表属性:
title : 图表的显示名称
x-field : 图表的 X 轴数据列, 一般是日期, 时间等
y-field : 图表的 Y 轴数据列, 该项是一个 list, 可以同时设定多个列, 这样多个列的数据会在同一个图表中显示
order : 排序信息, 如果不写则使用数据列表的排序
# 导出类型
list_export = ('xls', 'xml', 'json') list_export设置为None来禁用数据导出功能
#导出字段
list_export_fields = ('start_people', 'sport', 'sport_time')