测试平台——用户模块开发

这里写目录标题

  • 一、创建子应用
  • 二、用户注册设计
    • 1、用户注册模型类设计
      • a、Django认证系统提供了用户模型类User,为什么还要定义User模型类?
      • b、AbstractUser
      • c、自定义用户模型类的字段有
      • d、User模型类编写好了就可以了吗?
    • 2、用户注册序列化器类设计
      • a、注意
      • b、单字段进行校验
      • c、用户认证的时候为什么不用create,而用create_user呢?
      • d、代码展示
    • 3、用户注册视图类设计
      • a.注意
      • b.APIView子类
    • 4.路由配置
      • a.特别注意:
  • 三、用户验证
    • 1、需要配置如下内容
      • a、指定认证方式
      • b、自定义JWT认证成功之后返回的响应格式
      • c、截图所示
    • 2、验证

一、创建子应用

一个项目往往会包含多个子应用,直接放在项目根目录不便于管理。

在当前目录的apps目录下创建子应用

python manage.py startapp users

测试平台——用户模块开发_第1张图片
优化导入路径

sys.path.insert(0, os.path.join(BASE_DIR, 'apps'))

测试平台——用户模块开发_第2张图片
注册子应用
测试平台——用户模块开发_第3张图片

二、用户注册设计

1、用户注册模型类设计

a、Django认证系统提供了用户模型类User,为什么还要定义User模型类?

Django认证系统提供了用户模型类User,具体位置:django.contrib.auth.models.User;
因为Django认证系统提供的用户模型类User中缺少我本次项目中需要的字段,需要重写定义User模型类,最好不要和User重名,我以UserModel命令

b、AbstractUser

自定义的User需要继承AbstractUser,同时还需要继承BaseModel
AbstractUser源码如下:

class AbstractUser(AbstractBaseUser, PermissionsMixin):
    username_validator = UnicodeUsernameValidator()
    .....

class User(AbstractUser):
    class Meta(AbstractUser.Meta):
        swappable = 'AUTH_USER_MODEL'

c、自定义用户模型类的字段有

mobile
代码如下

import re

from django.db import models
from django.contrib.auth.models import AbstractUser


# Create your models here.

class User(AbstractUser):
    mobile = models.CharField('电话号码',
                              max_length=20,
                              help_text='电话号码',
                              null=True, blank=True,
                              )

    class Meta:
        db_table = 't_user'
        verbose_name = '用户表'
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.username

    REQUIRED_FIELDS = ['mobile']  # 再通过createsuperuser管理命令创建用户时,将提示输入mobile字段

d、User模型类编写好了就可以了吗?

当然不是了,Django不会识别到你自己定义的User模型类,此时Django还是识别系统自带的User模型类,那需要怎么做
需要在settings.py配置文件中配置

特别注意:添加自定义用户模型类(应用名字.模型类名)

AUTH_USER_MODEL='users.User'

2、用户注册序列化器类设计

a、注意

1、extra_kwargs:当对模型类中定义的字段进行细微的调整时,在序列化器类中使用extra_kwargs进行调整
2、模型类中字段如果有设置为unique=True时,当校验不通过,在序列化输出时,并不是我想要的校验结果,可以通过
"validators": [UniqueValidator(queryset=UserModel.objects.all(), message='用户名已注册,请重新输入')],进行自定义.

3、一定要记住password字段,一定不能输出,要设置为’write_only’: True,

b、单字段进行校验

当在extra_kwargs={}中没法进行细微的调整时,需要进行单字段校验
采用validate_属性名称
例如当对手机号进行校验时,

用validate_phone(attr)

必须返回attr
拓展:

多字段校验:validate(attrs)

c、用户认证的时候为什么不用create,而用create_user呢?

UserModel.objects.create(**validated_data):
create:只会将反序列化输入校验通过的字段,原样插入到数据库中,因为密码是不能直接插入到数据中的
所以必须要重写create方法.

代码如下:

def create(self,validated_data):
    '''必须重写create函数,因为用户密码是不能直接插入到数据库的'''
    user=UserModel.objects.create_user(**validated_data)
    return user

d、代码展示

import re

from rest_framework.validators import UniqueValidator, ValidationError
from rest_framework import serializers

from .models import User


class RegisterSerializer(serializers.ModelSerializer):
    password_confirm = serializers.CharField(write_only=True,
                                             label='确认密码',
                                             help_text='确认密码',
                                             min_length=6,
                                             max_length=20,
                                             error_messages={
                                                 'min_length': '仅允许6-20个字符的密码',
                                                 'max_length': '仅允许6-20个字符的密码'
                                             })

    class Meta:
        model = User
        fields = ['id', 'username', 'password', 'mobile', 'email', 'password_confirm']

        extra_kwargs = {
            'username': {
                'label': '用户名',
                'help_text': '用户名',
                'min_length': 2,
                'max_length': 20,
                'error_messages': {
                    'min_length': '仅允许2-20个字符的密码',
                    'max_length': '仅允许2-20个字符的密码'
                }
            },
            'password': {
                'label': '密码',
                'help_text': '密码',
                'write_only': True,
                'min_length': 6,
                'max_length': 20,
                'error_messages': {
                    'min_length': '仅允许6-20个字符的密码',
                    'max_length': '仅允许6-20个字符的密码'
                }
            },
            'email': {
                'label': '邮箱',
                'help_text': '邮箱',
                'required': True,
                'allow_blank': True,
                'validators': [
                    UniqueValidator(queryset=User.objects.all(), message='此邮箱已注册')
                ]
            }
        }

    def validate_mobile(self, value):
        if not re.match(r'1[3-9]\d{9}', value):
            raise ValidationError("手机号码格式不正确")
        return value

    def validate(self, attrs):
        password = attrs.get('password')
        password_confirm = attrs.get('password_confirm')
        if not password == password_confirm:
            raise serializers.ValidationError('您2次输入的密码不一致')
        return attrs

    def create(self, validated_data):
        validated_data.pop('password_confirm')
        # 调用create_user方法,处理密码加密的问题
        return User.objects.create_user(**validated_data)

3、用户注册视图类设计

a.注意

当视图类中需要用的接口包括增删改查查时,不用想直接继承ModelViewSet即可
当视图类中只实现某1个功能,只需要继承特定的视图类即可,不能继承ModelViewSet.
因为会有漏洞,不法分子会恶意访问接口进行修改数据.

b.APIView子类

ListAPIView
CreateAPIView
UpdateAPIView
RetrieveAPIView
DestroyAPIView
ListCreateAPIView
RetrieveUpdateAPIView
RetrieveDestroyAPIView
RetrieveUpdateDestroyAPIView

from django.shortcuts import render

# Create your views here.
from rest_framework.viewsets import ModelViewSet
from rest_framework.permissions import IsAuthenticated
from rest_framework import generics

from .models import User

from .serializers import RegisterSerializer


class UserRegisterView(generics.CreateAPIView):
    queryset = User.objects.all()
    serializer_class = RegisterSerializer

4.路由配置

from django.urls import path,include
from . import views
from rest_framework import routers
from rest_framework_jwt.views import obtain_jwt_token

urlpatterns=[
    path('users/login/',obtain_jwt_token),
    path('register/',views.UserRegisterView.as_view())

a.特别注意:

当数据库脚本生成和迁移操作时,如果数据库中没有生成对应的表,
首先需要检查模型类设计是否正确;
接着将迁移脚本都删除,同时将数据库中的表也删除
重新执行迁移脚本(init.py文件不要删)

测试平台——用户模块开发_第4张图片

三、用户验证

1、需要配置如下内容

a、指定认证方式

REST_FRAMEWORK = {

    # 指定使用的认证类
    # a、在全局指定默认的认证类(认证方式)
    'DEFAULT_AUTHENTICATION_CLASSES': [
        # 1、指定jwt token认证
        'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
    ],
    # 'DEFAULT_PERMISSION_CLASSES':(
    #     'erp_project.utils.rbac_permissions.RbacPermission'
    # )
# 过滤
    'DEFAULT_FILTER_BACKENDS': ['django_filters.rest_framework.DjangoFilterBackend'],
}


# JWT配置
JWT_AUTH = {
    # 指定token失效时间为1天
    'JWT_EXPIRATION_DELTA': datetime.timedelta(days=1),
    # 使用自己的jwt_response_payload_handler,目的是响应结果中可以返回用户名和id
    'JWT_RESPONSE_PAYLOAD_HANDLER': 'utils.jwt_handler.jwt_response_payload_handler',

}

b、自定义JWT认证成功之后返回的响应格式

def jwt_response_payload_handler(token, user=None, response=None):
    '''自定义JWT认证成功之后返回的响应格式'''
    return {
        'id': user.id,  # 返回登录用户的id
        'username': user.username,  # 用户名
        'token': token
    }

c、截图所示

测试平台——用户模块开发_第5张图片
测试平台——用户模块开发_第6张图片

2、验证

测试平台——用户模块开发_第7张图片

测试平台——用户模块开发_第8张图片

你可能感兴趣的:(#,测试效能平台(二),sqlite,数据库,android,django,python)