美文网首页
Django之使用自定义用户表(AbstractUser)/自定

Django之使用自定义用户表(AbstractUser)/自定

作者: 车陂IT仔 | 来源:发表于2022-10-26 11:41 被阅读0次

    基本步骤:

    一、自定义用户表:

    1、自定义的用户表继承AbstractUser;
    2、settings.py添加配置,指向用户表:AUTH_USER_MODEL = 'myUser.Account'(子项目名称.用户表models名称);
    3、python manage.py makemigrations
    4、python manage.py migrate

    二、自定义登录验证:
    # 签发:
    jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
    # 生成token:
    jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
    
    三、获取当前登录用户:
    # 通过headers获取token:
    token = request.META.get('HTTP_AUTHORIZATION')
    # 情况一:token的传参格式为JWT xxxx
    token = request.META.get('HTTP_AUTHORIZATION')[4:]
    # 情况二:token的传参格式为TOKEN xxxx
    token = request.META.get('HTTP_AUTHORIZATION')[7:]
    # 然后解析出user_id和username:
    jwt_decode_handler = api_settings.JWT_DECODE_HANDLER
    
    • 基本目录结构


      基本目录结构

    话不多说,直接上代码

    • models:
    from django.db import models
    from django.contrib.auth.models import AbstractUser
    
    
    """
    基类:可以把通用的字段定义这里,其他地方继承基类即可拥有
    """
    class BaseModel(models.Model):
        updated_tm = models.DateTimeField(auto_now=True)
        created_tm = models.DateTimeField(auto_now_add=True)
    
        class Meta:
            abstract = True
    
    """
    用户表:自定义的用户表
    想要使用自定义的用户表进行登录验证,需要满足下面的条件:
    1、需要继承AbstractUser;
    2、settings.py添加配置:AUTH_USER_MODEL = 'myUser.Account'(子项目名称.用户表models名称)
    """
    class Account(AbstractUser, BaseModel):
        user_id = models.AutoField(help_text="用户id", primary_key=True)
        username = models.SlugField(max_length=128, help_text="用户名", unique=True)
        password = models.CharField(max_length=128, help_text="用户密码")
        nickname = models.CharField(max_length=128, help_text="用户昵称")
    
        # 指定数据库表信息
        class Meta:
            db_table = 'user'
            verbose_name = '用户基础信息'
            verbose_name_plural = verbose_name
    
    """
    项目表:重点关注editor字段
    """
    class ProjectList(BaseModel):
        """项目基本信息"""
        project_id = models.AutoField(help_text="项目id", primary_key=True)
        project_name = models.SlugField(max_length=128, help_text="项目名", unique=True)
        editor = models.CharField(max_length=128, default='admin', help_text="编辑者")
    
        class Meta:
            db_table = 'project'
            verbose_name = '项目基本信息'
            verbose_name_plural = verbose_name
    
    • 自定义用户数据库表
    自定义用户数据库表
    • serializers
    from rest_framework import serializers
    from myUser.models import BaseModel, Account
    from myProject.models import ProjectList
    import time
    
    
    class BaseSerializer(serializers.ModelSerializer):
        """基类序列化器"""
        create_tm_format = serializers.DateTimeField(source="created_tm",
                                                     format="%Y-%m-%d %H:%M:%S",
                                                     required=False,
                                                     read_only=True,
                                                     help_text='创建时间(北京时间)')
    
        update_tm_format = serializers.DateTimeField(source="updated_tm",
                                                     format="%Y-%m-%d %H:%M:%S",
                                                     required=False,
                                                     read_only=True,
                                                     help_text='更新时间(北京时间)')
    
        created_tm = serializers.DateTimeField(required=False,
                                               read_only=True,
                                               help_text='创建时间(时间戳)')
    
        updated_tm = serializers.DateTimeField(required=False,
                                               read_only=True,
                                               help_text='更新时间(时间戳)')
    
        class Meta:
            model = BaseModel
            fields = ("created_tm", "updated_tm",
                      "create_tm_format", "update_tm_format")
    
    
    class UserSerializer(BaseSerializer):
        """用户基本信息"""
        user_id = serializers.IntegerField(read_only=True)
    
        class Meta:
            model = Account
    
            fields = ('username', 'password', 'user_id')
    
    
    class ProjectListSerializer(BaseSerializer):
        """项目基本信息"""
        class Meta:
            model = ProjectList
    
            fields = ('project_id', 'project_name', 'editor',
                      'created_start_tm', 'created_end_tm',
                      "created_tm", "updated_tm")
    
    • filter
    import django_filters
    from myUser.models import Account
    from myProject.models import ProjectList
    
    
    class UserFilter(django_filters.rest_framework.FilterSet):
        """用户基本信息"""
        user_id = django_filters.NumberFilter(field_name='user_id', lookup_expr='exact')
        username = django_filters.CharFilter(field_name='username', lookup_expr='icontains')
        nickname = django_filters.CharFilter(field_name='nickname', lookup_expr='icontains')
        created_start_tm = django_filters.DateTimeFromToRangeFilter(field_name='创建开始时间')
        created_end_tm = django_filters.DateTimeFromToRangeFilter(field_name='创建结束时间')
    
        class Meta:
            model = Account
            fields = ('user_id', 'username', 'created_start_tm', 'created_end_tm')
    
    
    class ProjectListFilter(django_filters.rest_framework.FilterSet):
        """项目基本信息"""
        project_id = django_filters.NumberFilter(field_name='project_id', lookup_expr='exact')
        project_name = django_filters.CharFilter(field_name='project_name', lookup_expr='icontains')
        editor = django_filters.CharFilter(field_name='editor', lookup_expr='exact')
        created_start_tm = django_filters.DateTimeFromToRangeFilter(field_name='创建开始时间')
        created_end_tm = django_filters.DateTimeFromToRangeFilter(field_name='创建结束时间')
    
        class Meta:
            model = ProjectList
            fields = ('project_id', 'project_name', 'created_start_tm', 'created_end_tm')
    
    • 用户登录views
    from drf_yasg.utils import swagger_auto_schema
    from myUser.models import Account
    from rest_framework import mixins
    from rest_framework.generics import GenericAPIView
    from serializers import UserSerializer
    from render_response import APIResponse
    from rest_framework_jwt.settings import api_settings
    
    # 签发
    jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
    # 生成token
    jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
    
    
    # Create your views here.
    class LoginView(mixins.UpdateModelMixin, GenericAPIView):
        authentication_classes = ()
        permission_classes = ()
    
        queryset = Account.objects.all()
        serializer_class = UserSerializer
        ordering = ['-created_tm']
        tag = ['用户']
    
        @swagger_auto_schema(tags=tag,
                             operation_id="login",
                             operation_summary='用户登录',
                             operation_description='明文密码',
                             responses={400010: "账号密码错误", 200: UserSerializer})
        def post(self, request, *args, **kwargs):
            """
            post: 用户登录
    
            400010:账号密码错误
            """
            username = str(request.data.get('username'))
            password = str(request.data.get('password'))
    
            try:
                Account.objects.get(username=username)
            except Account.DoesNotExist:
                return APIResponse(400010, '账号密码错误', success=False)
    
            try:
                Account.objects.get(password=password, username=username)
            except Account.DoesNotExist:
                return APIResponse(400010, '账号密码错误', success=False)
    
            user = Account.objects.filter(username=username, password=password).first()
            if user:
                # 登录成功,签发token,通过当前登录用户获取荷载(payload)
                payload = jwt_payload_handler(user)
                # 通过payload生成token串(三段:头,payload,签名)
                token = jwt_encode_handler(payload)
                response = {"user_id": user.user_id, "username": username, "token": token}
                return APIResponse(200, '登录成功', response)
    
    • 项目创建views
    from drf_yasg.utils import swagger_auto_schema
    from myProject.models import ProjectList
    from rest_framework import mixins
    from rest_framework.viewsets import GenericViewSet
    from serializers import ProjectListSerializer
    from render_response import APIResponse
    from rest_framework.response import Response
    from get_login_user_info import GetLoginUser
    
    
    # Create your views here.
    class AddProjectViews(mixins.CreateModelMixin, GenericViewSet):
        authentication_classes = []
        permission_classes = ()
    
        queryset = ProjectList.objects.all().order_by("-created_tm")
        serializer_class = ProjectListSerializer
        tag = ['项目']
    
        @swagger_auto_schema(tags=tag,
                             operation_summary='创建项目',
                             operation_id="project_create",
                             operation_description='项目名称必填',
                             responses={400014: "参数错误", 
                                        200: ProjectListSerializer,
                                        400013: "请检查输入字段是否正确(必填字段、未定义字段)", 
                                        500001: "项目名称长度需要1到20位", 
                                        500002: "项目已存在", 
                                        500003: "项目创建失败", })
        def create(self, request, *args, **kwargs):
            """新增项目"""
            try:
                project_name = request.data.get("project_name")
                project_desc = request.data.get("project_desc")
            except Exception:
                return APIResponse(400014, '参数错误', success=False)
    
            field_list = {}
            if project_name:
                field_list["project_name"] = project_name
            if project_desc:
                field_list["project_desc"] = project_desc
    
            # 获取当前登录用户信息
            user = GetLoginUser().get_login_user(request)
            if user["code"] == 200:
                field_list["editor"] = user["username"]
            else:
                return Response(user)
    
            # 检查账号密码是否有填写
            if "project_name" not in list(field_list.keys()):
                return APIResponse(400013, '请检查输入字段是否正确(必填字段、未定义字段)', success=False)
            else:
                if len(field_list["project_name"]) > 20 or len(field_list["project_name"]) < 1:
                    return APIResponse(500001, '项目名称长度需要1到20位', success=False)
    
            try:
                ProjectList.objects.get(project_name=field_list["project_name"])
                return APIResponse(500002, '项目已存在', success=False)
            except ProjectList.DoesNotExist:
                try:
                    ProjectList.objects.create(**field_list)
                    return APIResponse(200, '项目创建成功')
                except Exception as e:
                    print(e)
                    return APIResponse(500003, '项目创建失败', success=False)
    
    • token的传参
    token的传参
    • 返回我是这么定义的(来自网友)
    """
    自定义返回处理
    """
    from rest_framework.response import Response
    
    
    class APIResponse(Response):
        def __init__(self, code=200, msg='请求成功', data=None, status=None, headers=None, success=True, **kwargs):
            dic = {'code': code, 'message': msg, 'success': success, 'data': None}
            if data:
                dic['data'] = data
            dic.update(kwargs)  # 可以灵活的添加,需要返回的键值对
            super().__init__(data=dic, status=status, headers=headers)
    
    • 获取当前登录用户信息我是这么写的(原创)
    from myUser.models import Account
    from jwt import ExpiredSignatureError
    from render_response import APIResponse
    from rest_framework_jwt.settings import api_settings
    
    # 解析token
    jwt_decode_handler = api_settings.JWT_DECODE_HANDLER
    
    
    class GetLoginUser:
        @staticmethod
        def get_login_user(request):
            try:
                token = request.META.get('HTTP_AUTHORIZATION')
            except Exception:
                return APIResponse(400014, '参数错误', success=False)
    
            if token:
                try:
                    # 解密token,提取user_id
                    user_id = jwt_decode_handler(token)["user_id"]
                    username = Account.objects.filter(user_id=user_id).values('username').first()
                    return {"user_id": user_id, "username": username["username"], "code": 200}
                except ExpiredSignatureError:
                    return APIResponse(4031, 'token已过期', success=False)
            else:
                return APIResponse(403, '无访问权限,请重新登录或稍后再试!', success=False)
    
    • 简易的swagger文档


      简易的swagger文档
    • 用户登录


      用户登录
    • 项目创建

    项目创建 项目表

    相关文章

      网友评论

          本文标题:Django之使用自定义用户表(AbstractUser)/自定

          本文链接:https://www.haomeiwen.com/subject/mkuazrtx.html