赞
踩
在开发过程中,模型User的字段可能满足不了复杂的开发需求。现在大多数网站的用户信息都有用户的手机号码、QQ号码和微信号们等一系列个人信息。为了满足各种需求,Django提供了三种模型扩展的方法:
1、代理模型:这是一种模型继承,这种模型在数据库中无须创建新数据表。一般用于改变现有模型的行为方式,如增加新方法函数等,并且不影响现有数据库的结构。当不需要在数据库中存储额外的信息,而需要增加操作方式或更改模型的查询管理方式,适合使用代理模型来扩展现有User模型。
2、Profile扩展模型User:当存储的信息与模型User相关,而且并不改变模型User原有的认证方法时,可定义新的模型MyUser,并设置某个字段为OneToOneField,这样能与模型User形成一对一关联,该方法称为用户配置(User Profile)。
3、AbstractUser扩展模型User:如果模型User内置的方法符合开发需求,在不改变这些函数方法的情况下,添加模型User的额外字段,可通过AbstractUser方式实现。使用AbstractUser定义的模型会替换原有模型User。
上述三种方法各有优缺点,一般情况下,建议使用AbstractUser扩展模型User,因为该方式对原有模型User影响较少而且无须额外创建数据表。下面以MyDjango项目为例讲解如何使用AbstractUser扩展模型User。首先在MySQL中找到项目所使用的数据库,并清除数据库中全部的数据表,注意了删除数据库一定要小心,我这边之前删除了数据库之后怎么也创建不了了花费了我半天才搞定,因为我app之前设置了很多关联的东西所以要把之前那些关联的东西都注销掉再创建,这里我就把我之前那个index的models.py以及关联的文件都注销掉在user的models.py文件中定义模型MyUser,代码如下:
#user/models.py
from django.contrib.auth.models import AbstractUser
class MyUser(AbstractUser):
qq = models.CharField('QQ号码', max_length=16)
weChat = models.CharField('微信账号', max_length=100)
mobile = models.CharField('手机号码', max_length=11)
#设置返回值
def __str__(self):
return self.username
模型MyUser继承自AbstractUser类,AbstractUser类已有内置模型User的字段属性,因此模型MyUser具有模型User的全部属性。在执行数据迁移(创建数据表)之前,必须要在项目的settings.py中配置相关信息,配置信息如下:
#settings.py
AUTH_USER_MODEL = 'user.MyUser'
配置信息是将内置模型User替换成user定义的模型MyUser,若没有设置配置信息,在创建数据表的时候,会分别创建数据表auth_user和user_myuser。在PyCharm的Terminal下执行数据迁移:
python manage.py makemigrations
python manage.py migrate
打开数据库查看数据表信息,可以发现内置模型User的数据表auth_user改为数据表user_myuser,并且数据表user_myuser的字段除了具有内置模型User的字段之外,还额外增加了自定义的字段。
上述例子使用AbstractUser扩展模型User,实现过程可分为两个步骤:
1、定义新的模型MyUser,该模型必须继承AbstractUser类,在模型MyUser下定义的字段为扩展字段。
2、在项目的配置文件settings.py中配置AUTH_USER_MODEL信息,在数据迁移时,将内置模型User替换成user定义的模型MyUser。
完成模型User的扩展后,接着探讨模型MyUser与内置模型User在实际开发过程中是否存在使用上的差异。首先是要python manage.py createsuperuser创建超级用户并登录Admin后台管理系统:
认证与授权没有用户信息表,因为模型MyUser是在user的models.py中定义的。若将模型MyUser展示在后台系统,则可以在user的admin.py中定义相关数据对象:
在user的admin里面添加代码:
from django.contrib import admin
from .models import MyUser
from django.contrib.auth.admin import UserAdmin
from django.utils.translation import gettext_lazy as _
# Register your models here.
@admin.register(MyUser)
class MyUserAdmin(UserAdmin):
list_display = ['username', 'email', 'mobile', 'qq', 'weChat']
# 修改用户时,在个人信息里添加'mobile'、'qq'、'weChat'的信息录入
# 将源码的UserAdmin.fieldsets转换成列表格式
fieldsets = list(UserAdmin.fieldsets)
# 重写UserAdmin的fieldsets,添加'mobile'、'qq'、'weChat'的信息录入
fieldsets[1] = (_('Personal info'), {'fields': ('first_name', 'last_name', 'email', 'mobile', 'qq', 'weChat')})
user下的_init_.py添加代码:
#设置App(user)的中文名 from django.apps import AppConfig import os #修改app在admin后台显示名称 #default_app_config的值来自apps.py的类名 default_app_config = 'user.IndexConfig' #获取当前app的命名 def get_current_app_name(_file): return os.path.split(os.path.dirname(_file))[-1] #重写类IndexConfig class IndexConfig(AppConfig): name = get_current_app_name(__file__) verbose_name = '用户管理'
刷新浏览器看看效果
上面例子中,admin.py定义的MyUserAdmin继承自UserAdmin,UserAdmin是内置模型User的Admin数据对象,源码可在Python安装目录Lib\site-packages\django\contrib\auth\admin.py中查看。因此,在定义MyUserAdmin时,直接继承UserAdmin,并通过重写某些属性,可以快速开发扩展模型MyUser的Admin后台数据对象。
除了继承UserAdmin的Admin数据对象之外,还可以在表单中继承内置模型User所定义的表单类。内置表单类可以在Python安装目录Lib\site-packages\django\contrib\auth\forms.py下查看源码。从源码中发现,forms.py定义了多个内置表单类,如图表:
从上述内置的表单类可以发现,这些表单类都涉及模型User的字段,说明这些表单都是在内置模型User的基础上实现的。因此,我们为扩展模型MyUser定义相关的表单类可以继承上述的表单类。以UserCreationForm为例,使用表单类UserCreationForm实现用户注册功能。在user中创建form.py文件来重写表单类:
from django.contrib.auth.forms import UserCreationForm
from .models import MyUser
class MyUserCreationForm(UserCreationForm):
class Meta(UserCreationForm.Meta):
model = MyUser
#在注册界面添加邮箱、手机号码、微信号码和QQ号码
fields = UserCreationForm.Meta.fields + ('email', 'mobile', 'weChat', 'qq')
自定义表单类MyUserCreationForm继承自表单类UserCreationForm,并且重写类Meta的属性model和属性fields,分别重新设置表单类所绑定的模型和字段。然后在模板user.html和视图函数regusterView中编写一下代码:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <link rel="stylesheet" href="https://unpkg.com/mobi.css/dist/mobi.min.css"> </head> <body> <div class="flex-center"> <div class="container"> <div class="flex-center"> <div class="unit-1-2 unit-1-on-mobile"> <h1>MyDjango Auth</h1> {% if tips %} <div>{{ tips }}</div> {% endif %} <form class="form" action="" method="post"> {% csrf_token %} <div>用户名:{{ user.username }}</div> <div>邮 箱:{{ user.email }}</div> <div>手机号:{{ user.mobile }}</div> <div>Q Q 号:{{ user.qq }}</div> <div>微信号:{{ user.weChat }}</div> <div>密 码:{{ user.password1 }}</div> <div>密码确认:{{ user.password2 }}</div> <button type="submit" class="btn btn-primary btn-block">注 册</button> </form> </div> </div> </div> </div> </body> </html>
#使用表单实现用户注册
def registerView(request):
if request.method == 'POST':
user = MyUserCreationForm(request.POST)
if user.is_valid():
user.save()
tips = '注册成功'
user = MyUserCreationForm()
else:
user = MyUserCreationForm()
return render(request, 'user.html', locals())
从上述代码可以看到,视图函数registerView使用表单类MyUserCreationForm实现用户注册功能,功能说明如下:
1、当用户在浏览器上访问http://127.0.0.1:8000/user/register.html时,视图函数首先将表单类MyUserCreationForm实例化后传给模板,在网页上生成用户注册的表单界面。
2、输入用户信息并单击"注册"按钮,程序将表单数据交给表单类MyUserCreationForm处理并生成user对象。
3、最后验证user对象的数据格式,若验证成功通过,则将数据保存到数据表user_myuser中
本文参考:Auth认证系统
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。