百木园-与人分享,
就是让自己快乐。

Django之使用自定义用户表(AbstractUser)/自定义登录验证(jwt)/获取当前登录用户

基本步骤:

一、自定义用户表:

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文档

  • 用户登录
    用户登录

  • 项目创建

项目创建

项目表


来源:https://www.cnblogs.com/lsc-blog/p/16827761.html
本站部分图文来源于网络,如有侵权请联系删除。

未经允许不得转载:百木园 » Django之使用自定义用户表(AbstractUser)/自定义登录验证(jwt)/获取当前登录用户

相关推荐

  • 暂无文章