前言
这几年一直在it行业里摸爬滚打,一路走来,不少总结了一些python行业里的高频面试,看到大部分初入行的新鲜血液,还在为各样的面试题答案或收录有各种困难问题
于是乎,我自己开发了一款面试宝典,希望能帮到大家,也希望有更多的Python新人真正加入从事到这个行业里,让python火不只是停留在广告上。
微信小程序搜索:Python面试宝典
或可关注原创个人博客:https://lienze.tech
也可关注微信公众号,不定时发送各类有趣猎奇的技术文章:Python编程学习
重载admin用户系统
django
自带的admin
模块下的用户系统主要负责用户账户,组,权限和基于cookie
的会话等业务
认证系统由以下部分组成:
-
用户:包含用户数据字段,是实现业务功能逻辑的基础
-
权限:控制用户进否可以执行某项任务的二进制(是/否)标志。
-
组:一种为多个用户加上标签和权限的常用方式。
-
消息:一种为指定用户生成简单消息队列的方式
默认方法
在项目中,我们将使用email作为用户的用户名,那么可以在自带用户表中写明
USERNAME_FIELD = 'email'
# 该属性设置当前表的登陆字段
描述我们自定义用户模型上作唯一标识符字段名称的字符串,字段必须是唯一的,在定义中设置
unique=True
设置某个字段为必填项
REQUIRED_FIELDS = ['username']
is_authenticated()
判断用户是否已通过身份验证的方法,不意味任何权限,而且不检查用户的活动状态
get_username()
返回由USERNAME_FIELD制定的字段的值
get_full_name()
返回
first_name
加上last_name
中间加上一个空格,由于我们重新设置了表字段,那么这个默认函数需要我们重新给定返回值
get_short_name()
一个短的且非正式用户的标识符,返回
first_name
当你的项目重写该字段或直接去掉了first_name
,所以我们必须重新给定这个函数的返回值
set_password()
将用户的密码设置为给定的字符串
has_perm(perm, obj=None)
用户是否具有某个权限,如果给定
obj
,则需要根据特定对象实例检查权限
has_module_perms(app_label)
如果用户有权访问给定应用中的模型,则返回
True
这里我们这两个字段都设置为True
,可以让用户访问任一APP
is_staff()@property
如果用户允许访问管理网站,则返回
True
这里我们返回is_admin
的字段属性即可
关于字段属性,如果需要进行高度扩展,可以使用继承AbstractBaseUser
这个类
这个类中只含有password
,last_login
,以及is_active
三个字段属性
重载管理器
由于已经覆盖了默认的
admin
用户表,现在需要将其对应的管理器函数进行编写编写时主要关注一下两个父类函数的重写
create_user(username_field,password_filed=None,**other_fields)
normalize_email()将邮件地址规范化的类方法
user.save(using=self._db)
create_superuser(username, email, password)
#用户创建,is_admin设置为True即可
user.save(using=self._db)
from django.contrib.auth.models import BaseUserManager
class MyUserManager(BaseUserManager):
def create_user(self, username, email, password=None):
if not email :
raise ValueError('Users must have an email address')
if not username:
raise ValueError('Users must have an username')
#判断邮件和用户名是否具有
now = timezone.now()
#获取当前django的时间
user = self.model(
username=username,
email=self.normalize_email(email),
date_joined=now,
last_login=now,
)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, username, email, password):
user = self.create_user(username,
email,
password=password,
)
user.is_admin = True
user.save(using=self._db)
return user
重新定义新用户表的管理器之后,想要生效,还需要在对应的模型类表中覆盖
objects
属性
objects = MyUserManager()
重载表
下面是一个真实的重载自带用户表的模型类
from django.contrib.auth.models import AbstractBaseUser
class Member(AbstractBaseUser):
#AbstractBaseUser中只含有3个field: password, last_login和is_active.
email = models.EmailField(verbose_name='邮箱',max_length=255,unique=True,)
username = models.CharField(verbose_name="用户名", max_length=16, unique=True)
weibo_id = models.CharField(verbose_name="新浪微博", max_length=30, blank=True)
blog = models.CharField(verbose_name="个人网站", max_length=200, blank=True)
location = models.CharField(verbose_name="城市", max_length=10, blank=True)
profile = models.CharField(verbose_name="个人简介", max_length=140, blank=True)
avatar = models.CharField(verbose_name="头像", max_length=128, blank=True)
au = models.IntegerField(verbose_name="用户活跃度", default=0)
last_ip = models.IPAddressField(verbose_name="上次访问IP", default="0.0.0.0")
email_verified = models.BooleanField(verbose_name="邮箱是否验证", default=False)
date_joined = models.DateTimeField(verbose_name="用户注册时间", default=timezone.now)
topic_num = models.IntegerField(verbose_name="帖子数", default=0)
comment_num = models.IntegerField(verbose_name="评论数", default=0)
is_active = models.BooleanField(default=True)
is_admin = models.BooleanField(default=False)
objects = MyUserManager()
#objects就是我们之前一直使用的管理器
#管理器用来维护我们的增删改查
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['username']
def __str__(self):
return self.username
#标签中的数据实例
def is_email_verified(self):
return self.email_verified
#我们可以在模板中,通过实例出来的对象数据进行这个函数的调取,获取他是否验证过
def get_weibo(self):
return self.weibo_id
def get_username(self):
return self.username
#方法的圆括号在templates标签中必需省略!!
def get_email(self):
return self.email
#方法的圆括号在templates标签中必需省略!!
def get_full_name(self):
# The user is identified by their email address
return self.email
#get_full_name本来是获取first_name和last_name的
#但是由于我们重新设置了表结构,那么这个函数必须自定义
#方法的圆括号在templates标签中必需省略!!
def get_short_name(self):
# The user is identified by their email address
return self.username
def has_perm(self, perm, obj=None):
"Does the user have a specific permission?"
return True
def has_module_perms(self, app_label):
"Does the user have permissions to view the app `app_label`?"
return True
def calculate_au(self):
"""
计算活跃度
公式:Topic * 5 + Comment * 1
"""
self.au = self.topic_num * 5 + self.comment_num * 1
return self.au
@property
#类中函数可以直接做为属性使用
def is_staff(self):
"Is the user a member of staff?"
# Simplest possible answer: All admins are staff
return self.is_admin
重载Admin表单
由于修改了默认的
django
表结构,此时在admin
界面修改密码或添加用户数据已经不能再按照之前的表单系统啦需要在
app
的admin.py
中重写UserCreationForm
和UserChangeForm
# 用户创建表单
from django import forms
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.forms import ReadOnlyPasswordHashField
from people.models import Member, Follower
class UserCreationForm(forms.ModelForm):
"""A form for creating new users. Includes all the required
fields, plus a repeated password."""
password1 = forms.CharField(label='密码', widget=forms.PasswordInput)
password2 = forms.CharField(label='确认密码', widget=forms.PasswordInput)
class Meta:
model = Member
fields = ('email', 'username')
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("两次输入验证失败")
return password2
#在form中的clean__field函数会在is_valid()函数验证时自动调用
def save(self, commit=True):
user = super(UserCreationForm, self).save(commit=False)
user.set_password(self.cleaned_data["password1"])
#set_password将会采用django的加密算法将密码设置到对应的模型实例中
#在内存中创建的好的对象只有通过commit=True才被真正执行到数据库上
if commit:
user.save()
return user
# 密码改变时的展示表单
class UserChangeForm(forms.ModelForm):
password = ReadOnlyPasswordHashField()
class Meta:
model = Member
fields = ('email', 'password', 'username', 'is_active', 'is_admin',)
def clean_password(self):
return self.initial["password"]
#使用默认的save函数即可
# 真正的用户admin界面管理方式
class MyUserAdmin(UserAdmin):
form = UserChangeForm
add_form = UserCreationForm
list_display = ('id', 'email', 'username', 'email_verified', 'last_login','is_active','is_admin','last_ip')
list_display_links = ('id', 'email', 'username')
list_filter = ('email', 'email_verified',)
fieldsets = (
(None, {'fields': ('username', 'email', 'date_joined', 'password','is_active','is_admin','avatar')}),
('状态', {'fields': ('email_verified', 'last_ip', 'au', 'topic_num', 'comment_num')}),
('社交网络', {'fields': ('weibo_id', 'blog')}),
)
add_fieldsets = (
(None, {
'classes': ('wide',),
#admin样式设置
#Fieldsets 使用 wide 样式将会有额外的水平空格.
'fields': ('email', 'username', 'password1', 'password2','is_active','is_admin')}
),
)
search_fields = ('id', 'email', 'username')
ordering = ('id', 'email', 'email_verified')
filter_horizontal = ()
#这个字段为了设置与groups关联的多选框
admin.site.register(Member, MyUserAdmin)
admin.site.register(Follower)
最终
还需要在
settings.py
文件下进行设置,覆盖默认的User
模型
AUTH_USER_MODEL = 'people.Member'