Django深入研究4(后台系统的二次开发、Auth认证系统)

一、后台系统的二次开发

  前面的章节讲述了Admin的基本设置,但实际上每个网站的功能和需求都是各不相同的,这也导致了Admin后台功能有所差异。因此,通过重写ModelAdmin的方法可以实现Admin的二次开发,满足多方面的开发需求。

1、get_readonly_fields函数

  函数get_readonly_fields和属性readonly_fields的功能相似,不过前者比后者更为强大。比如使用函数get_readonly_felds实现不同的用户角色来决定字段的可读属性,实现代码如下:

#重写 get_readonly_fields函数,设置超级用户和普通用户的权限
def get_readonly_fields(self, request, obj=None):
	if request.user.is_superuser:
		self.readonly_fields=[]
	return self.readonly_fields

  函数get_readonly_fields首先判断当前发送请求的用户是否为超级用户,如果符合判断条件,将重新设置readonly_fields属性,使当前用户具有全部字段的编辑权限。其中,函数参数request是当前用户的请求对象,参数obj是模型对象,默认值为None。
  在浏览器上通过切换不同的用户登录,可以发现在新增或者修改数据的时候,不同的用户身份对字段name的操作权限有所不。

2、设置字段格式

  在Admin 预览模型Performer的数据信息时,数据表的表头是由属性list_display所定义的,每个表头的数据都来自于数据库,并且数据以固定的字体格式显示在网页上。若要对某些字段的数据进行特殊处理,如设置数据的字体颜色,以模型Performer的name字段为例,将该字段的数据设置为不同的颜色,实现代码如下:

#models.py的模型Performer
from django.db import models
from django.utils.html import format_html

#一对一关系(姓名信息表和出生年月表)
class Performer(models.Model):

    id = models.IntegerField('编号', primary_key=True)
    name = models.CharField('姓名', max_length=20)
    nationality = models.CharField('国籍', max_length=20)
    masterpiece = models. CharField('节目', max_length=50)

    # 设置返回值
    def str(self):
        return self.name

    class Meta:

        # 如只设置 verbose_name,在Admin会显示为”产品信息s"
        # verbose_name ='演员信息'
        verbose_name_plural = '演员信息'

    # 自定义字体颜色
    def color_type(self):
        if "张三" in self.name:
            color_code = 'red'
        elif "李四" in self.name:
            color_code = 'blue'
        else:
            color_code = 'pink'
        return format_html(
            '<span style="color: {};">{}</span>',
            color_code,
            self.name,
        )
    color_type.short_description="带颜色的姓名"

#在admin.py的ProductAdmin中添加自定义字段
#添加自定义字段,在属性list display中添加自定义字段color_type
list_display.append('color_type')

  从上述代码可以看到,设置字段的数据格式主要由文件models.py和admin.py实现,说明如下:

  • 在models.py的模型Performer中定义函数color_type,函数名可以自行命名,该函数通过判断模型字段的数据内容,从而返回不同的字体颜色。
  • 然后在admin.py的类ProductAdmin的属性list_display中添加模型Performer的函数color_type,使该函数以表头的形式显示在Admin后台的数据信息页面上。运行结果如下。
    在这里插入图片描述

3、函数get_queryset

  函数get_queryset根据不同用户角色设置数据的访问权限,该函数可以将一些重要的数据进行过滤。以模型Performer为例,在admin.py的类ProductAdmin中重写函数get_queryset,代码如下:

# 重写get_queryset
def get_queryset(self, request):
     qs = super(ProductAdmin, self).get_queryset(request)
     if request.user.is_superuser:
         return qs
     else:
         return qs.filter(id_lt=6)

  分析上述代码可知,自定义函数get_queryset的代码说明如下:

  • 首先通过super方法来获取父类ModelAdmin的函数get_queryset所生成的查询对象,该对象用于查询模型Performer的全部数据。
  • 然后判断当前用户的用户身份,如果为超级用户,函数返回模型Performer的全部数据,否则只返回模型Performer的前5条数据。

4、函数save_model

  函数save_model是在新增或修改数据的时候,点击保存按钮所触发的功能,该函数主要对输入的数据进行入库和更新处理。若想在这功能中加入一些特殊的功能需求,可以对函数save_model进行重写。比如对数据的修改实现一个日志记录,那么函数save_model的实现代码如下:

# 修改保存方法
    def save_model(self, request, obj, form, change):
        if change:
            # 获取当前用户名
            user = request.user
            # 使用模型获取数据,pk代表具有主键属性的字段
            name = self.model.objects.get(pk=obj.pk).name
            # 使用表单获取数据
            weight = form.cleaned_data['weight']
            # 写入日志文件
            f = open('e://MyDjango_log.txt', 'a')
            f.write('产品:'+str(name)+',被用户:'+str(user)+'修改'+'\r\n')
            f.close()
        else:
            pass
        # 使用super可使自定义save mode1既保留父类已有的功能又添加自定义功能
        super(ProductAdmin,self).save_model(request, obj, form, change)

  上述代码中,函数save_model的功能说明如下:

  • 首先判断参数change是否为True,若为True,则说明当前操作为数据修改,反之为新增数据。
  • 分别从三个函数参数中获取相关的数据内容。参数request代表当前用户的请求对象,参数obj代表当前数据所对应的模型对象,参数form代表Admin的数据修改页面所对应的数据表单。
  • 然后将所获取的数据写入文本文件,实现简单的日志记录功能。
  • 最后使用super 方法使重写函数save_model执行原有函数save_model的功能,对数据进行入库和变更处理。若将此代码注释,当触发重写函数时,程序只执行日志记录功能,并不执行数据入库和变更处理。

二、Auth认证系统

  Django除了有强大的Admin管理系统之外,还提供了完善的用户管理系统。整个用户管理系统可分为三大部分:用户信息、用户权限和用户组,在数据库中分别对应数据表auth_user、auth_permision和auth_group。

1、内置user实现用户管理

  用户管理功能已经是一个网站必备的功能之一,而Django内置了强大的用户管理系统,并且具有灵活的扩展性,可以满足多方面的开发需求。在创建Django项目时,Django已默认使用内置用户管理系统,在settings.py的INSTALLED_APPS、MIDDLEWARE和AUTH_PASSWORD_VALIDATORS中可以看到相关的配置信息。
  这里使用内置的用户管理系统实现用户的注册、登录、修改密码和注销功能。以MyDjango为例,在项目中创建新的App,命名为user,并且在项目的settings.py和urls.py中配置App的信息,代码如下:

# setting中的INSTALLED_APPS添加
'user',

# urls的urlpatterns中
path('user/', include('user.urls'))

  完成后再在user文件夹下添加urls.py 和在templates中添加user.html。App中的urls.py主要用于接收和处理根目录的urls.py的请求信息。user.html用于显示网页。在App的urls.py中设定了4个不同的URL地址,分别代表用户登录、注册、修改密码和用户注销,代码如下:

#urls.py文件#设置URL地址信息
from django.urls import path
from.import views
urlpatterns=[
    path('login.html', views.loginView, name='login'),
    path('register.html', views.registerView, name='register'),
    path('setpassword.html', views.setpasswordView, name='setpassword'),
    path('logout.html', views.logoutView, name='logout'),
]

  上述URL地址分别对应视图函数loginView、registerView、setpasswordView和logoutView;参数name用于设置URL的命名,可直接在HTML模板上使用并生成相应的URL地址。在讲解视图函数之前,首先了解HTML模板的代码结构,代码如下:


<!DOCTYPE html>
<html lang="zh-cn">
<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>用户名:<input type="text" name='username'></div>
            <div>密码:<input type="password" name='password'></div>
            {%if new_password %}
                <div>新密码:<input type="password" name='new_password'></div>
            {%endif%}
            <button type="submit" class="btn btn-primary btn-block">确定</button>
        </form>
        <div class="flex-left top-gap text-small">
            <div class="unit-2-3">
                <a href="{{ unit_2}}">{{ unit_2_name }}</a>
            </div>
            <div class="unit-1-3 flex-right">
                <a href="{{ unit_1 }}">{{ unit_1_name }}</a>
            </div>
        </div>
    </div>
    </div>
    </div>
</div>
</body>
</html>

  编辑完页面之后就是构建网址和页面的连接视图模块,首先在视图模块添加如下代码,用于实现登录功能:

from django.shortcuts import render,redirect
from django.contrib.auth.models import User
from django.contrib.auth import login, logout, authenticate
#Create your views here.
def loginView(request):
    #设置标题和另外两个URL链接
    title = '登录'
    unit_2 = '/user/register.html'
    unit_2_name = '立即注册'
    unit_1 = '/user/setpassword.html'

    unit_1_name = '修改密码'
    if request.method == 'POST':
        username = request.POST.get('username', '')
        password = request.POST.get('password', '')
        if User.objects.filter(username=username):
            user = authenticate(username=username, password=password)
            if user:
                if user.is_active:
                    login(request, user)
                return redirect('/')
            else:
                tips = '账号密码错误, 请重新输入'
        else:
            tips = '用户不存在, 请注册'
    return render(request, 'user.html', locals())


def registerView(request):
    pass


def setpasswordView(request):
    pass


def logoutView(request):
    pass

  上述代码结合模板文件user.html的变量进行分析,分析如下:

  • 首先设置模板变量title和unit2等变量值,在模板中生成相关的URL地址,可以从登录界面跳到注册界面或修改密码界面。
  • 由于提交表单是由当前的URL执行处理的,因此函数loginView需要处理不同的请求方式,视图函数首先判断当前请求方式。如果是POST请求,则获取表单中两个文本框的数据内容,分别为username和password,然后对模型User中的数据进行判断和验证,只有验证成功之后,网页才会跳转到首页,否则在登录界面上提示错误信息。
  • 如果是GET请求,当完成模板变量赋值之后就不再做任何处理,直接将模板user.html生成HTML网页返回到浏览器上。
  • 当函数loginView收到POST请求并获取表单的数据后,根据表单的数据判断用户是否存在。当用户存在时,对用户的账号和密码进行验证处理,由内置函数authenticate完成验证功能,如果验证成功,函数authenticate返回模型Uesr的数据对象user,否则返回None。
  • 然后从对象user的is active字段来判断当前用户的状态是否被激活,如果为1,说明当前用户处于激活状态,可执行用户登录。
  • 最后执行用户登录,由内置函数login完成登录过程。函数login接收两个参数,第一个是request对象,来自视图函数的参数request;第二个是user对象,来自函数authenticate返回的对象user。
       为了更好地演运行结果,在index中分别对模板index.html的<header>标签和视图函数index进行修改,代码如下:
# index 模板增加如下代码
<header id="top">
    <!--内容显示区域:width:1211px-->
    <div id="top_box">
        <ul class="rt">
            {%if username%}
                <li>用户名:{{username}}</li>
                <li><a href="{%url 'logout' %}">退出登录</a></li>
            {%else%}
                <li><a href="{%url 'login' %}">登录</a></li>
                <li><a href="{%url 'register' %}">注册</a></li>
            {%endif%}
        </ul>
    </div>
</header>
# index的视图模块中增加如下代码

# 获取当前请求的用户名
username = request.user.username

  在浏览器上访问http://127.0.0.1:8000/user/login.html,在用户登录界面输入用户的账号和密码,然后单击“确定”按钮,将输入的用户信息提交到视图函数loginView中完成登录过程,运行结果如图。
在这里插入图片描述
   上面的例子中只编写了登录代码,其他的都是pass代替,下面一个个编写所有模板代码,先是注册代码:

def registerView(request):
    # 设置标题和另外两个URL链接
    title ='注册'
    unit_2 = '/user/login.htm1'
    unit_2_name ='立即登录'
    unit_1 = '/user/setpassword.html'
    unit_1_name ='修改密码'
    if request.method == 'POST':
        username=request.POST.get('username','')
        password=request.POST.get('password','')
        if User.objects.filter(username=username):
            tips='用户已存在'
        else :
            user=User.objects.create_user(username=username,password=password)
            user.save()
            tips ='注册成功,请登录!'
    return render(request,'user.html',locals())

   从上述代码得知,用户注册与用户登录的流程大致相同,具体说明如下:

  • 当用户输入账号和密码并单击“确定”按钮后,程序将表单数据提交到函数registerView中进行处理。
  • 函数registerView首先获取表单的数据内容,根据获取的数据来判断模型User是否存在相关的用户信息。
  • 如果用户存在,直接返回到注册界面并提示用户已存在。
  • 如果用户不存在,程序使用内置函数create user对模型User进行用户创建,函数create_user是模型User特有的函数,该函数创建并保存一个is active=True的User对象。其中,函数参数username不能为空,否则抛出ValueError异常;而模型User的其他字段可作为函数createuser的可选参数,如email、first name和password等。如果使用过程中没有设置函数参数password,则User对象的set_unusable password)函数将会被调用,为当前用户创建一个随机密码。

接着是修改密码函数

def setpasswordView(request):
    #设置标题和另外两个URL链接
    title="修改密码"
    unit_2 = '/user/login.html'
    unit_2_name ='立即登录'
    unit_1 = '/user/register.html'
    unit_1_name ='立即注册'
    new_password = True
    if request.method == 'POST':
        username = request.POST.get('username','')
        old_password = request.POST.get('password','')
        new_password = request.POST.get('new_password','')
        if User.objects.filter(username=username):
            user=authenticate(username=username,password=old_password)
            user.set_password(new_password)
            user.save()
            tips ='密码修改成功'
        else :
            tips ='用户不存在!'
    return render(request,'user.html',locals())

函数setpasswordView的处理逻辑与上述例子也是相似的,函数处理逻辑说明如下:

  • 当函数setpasswordView收到表单提交的请求后,程序会获取表单的数据内容,然后根据表单数据查找模型User相应的数据。
  • 如果用户存在,由内置函数authenticate验证用户的账号和密码是否正确,若验证成功,则返回user对象,再使用内置函数set password修改对象user的密码,最后保存修改后的user对象,从而实现密码修改。
  • 如果用户不存在,直接返回到界面并提示用户不存在。
    最后就是登出/注销代码了,这个代码相对简单,调用内置函数logout就可实现
def logoutView(request):
    # 用户注销,退出登录
    logout(request)
    return redirect('/')

2、发送邮件实现密码找回

  在前面内容中,密码修改是在用户知道密码的情况下实现的,而在日常应用中,还有一种是在用户忘记密码的情况下实现密码修改,也称为密码找回。密码找回首先需要对用户账号进行验证,确认该账号是当前用户所拥有的,验证成功后才能给用户重置密码。用户验证方式主要有手机验证码验证和邮箱验证码验证两种,因此这里使用Django内置的邮件功能实现邮箱验证,从而实现密码找回功能。
  在实现邮件发送功能之前,我们需要对邮箱进行相关配置,以QQ邮箱为例,在QQ邮箱的设置中找到账户设置,在账户设置中找到POP3/IMAP/SMTP/Exchange/CardDAV/CalDAV服务,然后开启POP3/SMTP服务
在这里插入图片描述
  值得注意的是,开启服务时,QQ邮箱会返回一个客户端授权密码,该密码是用于登录第三方邮件客户端的专用密码,切记保存授权密码,该密码在开发过程中需要使用。
  本例中,我们使用QQ邮箱给用户发送验证邮件,因此在Django的settings.py中添加QQ邮箱的相关配置,配置信息如下:

#邮件配置信息
EMAIL_USE_SSL=True
#邮件服务器,如果是163就改成smtp.163.com
EMAILHOST='smtp.qq.com'
#邮件服务器端口
EMAIL_PORT = 465
#发送邮件的账号
EMAIL_HOST_USER = '1217082113@qq.com'
#SMTP服务密码
EMAIL_HOST_PASSWORD = 'xjibpiecqxxxxx'
DEFAULT_FROM_EMAIL = EMAIL_HOST_USER

上述配置是邮件发送方的邮件服务器信息,各个配置信息说明如下。

  • EMAIL_USE_SSL:设置Django与邮件服务器的连接方式为SSL。
  • EMAIL HOST:设置服务器的地址,该配置使用SMTP服务器。
  • EMAILPORT:设置服务器端口信息,若使用SMTP服务器,则端口应为465或587。
  • EMAILHOST_USER:发送邮件的账号,该账号必须开启POP3/SMTP服务。
  • EMAIL_HOST_PASSWORD :客户端授权密码,及开启POP3时发送的授权密码。
  • DEFAULT_FROM_EMAIL:设置默认发送邮件的账号。
    完成邮箱相关配置后,我们在user的urls.py、模板user.html和views.py中编写功能实现代码,代码如下:
# 在user的urls.py中加入以下路径
path('findPassword.html', views.findPassword, name='findPassword'),
# 模板findPassword.html

<!DOCTYPE html>
<html lang="zh-cn">
<head>
    <meta charset="utf-8">
    <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>用户名:<input type="text" name='username' values="{{username}}"></div>
            <div>验证码:<input type="text" name='VerificationCode'></div>
            {%if new_password %}
                <div>新密码:<input type="password" name='new_password'></div>
            {%endif%}
            <button type="submit" class="btn btn-primary btn-block">{{button}}</button>
        </form>

    </div>
    </div>
    </div>
</div>
</body>
</html>


# views.py中定义功能
#找回密码
def findPassword(request):

    button = '获取验证码'
    new_password = False
    if request.method == 'POST':
        username = request.POST.get('username', 'root')
        VerificationCode = request.POST.get('VerificationCode', '')
        password = request.POST.get('password', '')
        user = User.objects.filter(username=username)
        # 用户不存在
        if not user:
            tips = '用户' + username + '不存在'
        else:
            #判断验证码是否已发送
            if not request.session.get('VerificationCode', ''):
                # 发送验证码并将验证码写入session
                button = '重置密码'
                tips = '验证码已发送'
                new_password = True
                VerificationCode = str(random.randint(1000, 9999))
                request.session['VerificationCode'] = VerificationCode
                user[0].email_user('找回密码', VerificationCode)
            # 匹配输入的验证码是否正确
            elif VerificationCode == request.session.get('VerificationCode'):

                # 密码加密处理并保存到数据库
                dj_ps = make_password(password, None, 'pbkdf2_sha256')
                user[0].password = dj_ps
                user[0].save()
                del request.session['VerificationCode']
                tips = '密码已重置'
            # 输入验证码错误
            else:
                tips = '验证码错误,请重新获取'
                new_password = False
                del request.session['VerificationCode']
    return render(request, 'findPassword.html', locals())


  用户第一次访问http://127.0.0.1:8000/user/findPassword.html的时候,触发了GET请求,视图函数findPassword 直接将模板 user.html返回,如图1所示。
  当输入用户名并单击“获取验证码”按钮的时候,触发了POST请求,视图函数findPassword 首先根据用户输入的用户名和模型User里的数据进行查找,判断用户名是否存在,若不存在,则会生成提示信息,如图2所示。
图1图2
  如果用户存在,接着判断会话session的VerificationCode是否存在。若不存在,则视图函数findPassword通过发送邮件的方式将验证码发到该用户的邮箱,验证码是使用random模块随机生成的4位数,然后将验证码写入会话session的VerificationCode,其作用是与用户输入的验证码进行匹配。邮件发送是由内置函数email_user实现的,该方法是模型User特有的方法之一,只适用于模型User。需要注意的是,用户的邮箱来自于模型User的字段email,如果当前用户的邮箱信息为空,邮件是无法发送出去的。
  用户接收到验证码之后,可在网页上输入验证码,然后单击“重置密码”按钮,这时会触发POST请求,函数findPassword获取用户输入的验证码并与会话session的VerificationCode进行对比,如果两者不符合,说明用户输入的验证码与邮件中的验证码不一样,系统提示验证码错误。
  若用户输入的验证码与会话session的VerificationCode相符合,那么程序会执行密码修改。首先会获取用户输入的密码,然后使用函数make_password对密码加密处理并保存在模型User中,最后删除会话session的VerificationCode,否则会话 session一直存在,在下次获取验证码时,程序不会执行邮件发送功能。

这里需要大佬的指点,我测试的时候出现没法收到邮件的问题,ConnectionRefusedError: [WinError 10061] 由于目标计算机积极拒绝,无法连接。

3、扩展user模型

  在开发过程中,模型User的字段可能满足不了复杂的开发需求。现在大多数网站的用户信息都有用户的手机号码、QQ号码和微信号码等一系列个人信息。为了满足各种需求,Django提供了4种模型扩展的方法。

  • 代理模型:这是一种模型继承,这种模型在数据库中无须创建新数据表。一般用于改变现有模型的行为方式,如增加新方法函数等,并且不影响现有数据库的结构。当不需要在数据库中存储额外的信息,而需要增加操作方法或更改模型的查询管理方式时,适合使用代理模型来扩展现有User模型。
  • Profile扩展模型User:当存储的信息与模型User相关,而且并不改变模型User原有的认证方法时,可定义新的模型MyUser,并设置某个字段为One ToOneField,这样能与模型User形成一对一关联,该方法称为用户配置(User Profile)。
  • AbstractBaseUser扩展模型User:当模型User的内置方法并不符合开发需求时,可使用该方法对模型User重新自定义设计,该方法对模型User和数据库架构影响很大。
  • AbstractUser扩展模型User:如果模型User内置的方法符合开发需求,在不改变这些函数方法的情况下,添加模型User的额外字段,可通过AbstractUser方式实现。使用AbstractUser定义的模型会替换原有模型User。
      上述4种方法各有优缺点,一般情况下,建议使用AbstractUser 扩展模型User,因为该方式对原有模型User影响较少而且无须额外创建数据表。下面以MyDjango项目为例讲解如何使用AbstractUser 扩展模型User。首先在MySQL中找到项目所使用的数据库,并清除该数据库中全部的数据表,在user的models.py文件中定义模型MyUser,代码如下:
from django.db import models

# Create your models here.
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中配置相关信息,配置信息如下:

# 配置信息是将内置模型User 替换成user定义的模型MyUser
AUTH_USER_MODEL = 'user.MyUser'

之后就可以在Pycharm中进行数据迁移了,指令如下:

python manage.py makemigrations

python manage.py migrate

  完成数据迁移后,打开数据库查看数据表信息,可以发现内置模型User的数据表auth_user 改为数据表user_myuser,并且数据表user_myuser的字段除了具有内置模型User的字段之外,还额外增加了自定义的字段,如下图。
在这里插入图片描述
  上述例子使用AbstractUser扩展模型User,实现过程可分为两个步骤:

  • 定义新的模型MyUser,该模型必须继承AbstractUser类,在模型MyUser 下定义的字段为扩展字段。
  • 在项目的配置文件settings.py中配置AUTH_USER_MODEL信息,在数据迁移时,将内置模型User替换成user定义的模型MyUser。

   完成模型User的扩展后,接着探讨模型MyUser与内置模型User 在实际开发过程中是否存在使用上的差异。首先使用python manage.py createsuperuser创建超级用户并登录Admin后台管理系统。
在这里插入图片描述

   从上图发现,认证与授权没有用户信息表,因为模型MyUser是在user的models.py中定义的。若将模型MyUser展示在后台系统,则可以在user的admin.py中和__init__.py定义相关数据对象,代码如下:

# admin.py
from django.contrib import admin

# Register your models here.
from .models import MyUser
from django.contrib.auth.admin import UserAdmin
from django.utils.translation import gettext_lazy as _
@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")})
                    
# __init__.py
# 设置app的中文名称
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 = '用户管理'


效果如下:
在这里插入图片描述
   除了继承UserAdmin的Admin数据对象之外,还可以在表单中继承内置模型User所定义的表单类。以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和视图函数registerView中编写以下代码,代码如下:


<!DOCTYPE html>
<html lang="zh-cn">
<head>
    <meta charset="utf-8">
    <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>QQ号码:{{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>

# view.py 
from django.shortcuts import render
from .form import MyUserCreationForm


# 使用表单实现用户注册
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())

效果如下:
在这里插入图片描述
在这里插入图片描述

4、设置用户权限

   用户权限主要是对不同的用户设置不同的功能使用权限,而每个功能主要以模型来划分。以上面的MyDjango项目为例,在Admin后台管理系统可以查看并设置用户权限。
在这里插入图片描述
上图左边列表框中列出了整个项目的用户权限,以user|用户|Can add user为例:

  • user代表项目的App。
  • 用户代表App所定义的模型MyUser。
  • Can add user代表该权限可对模型MyUser执行新增操作。

   设置用户权限实质上是对数据表user_myuser和auth permission之间的数据设置多对多关系。

  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值