" name="sm-site-verification"/>
侧边栏壁纸
博主头像
PySuper 博主等级

千里之行,始于足下

  • 累计撰写 206 篇文章
  • 累计创建 14 个标签
  • 累计收到 2 条评论

目 录CONTENT

文章目录
Web

Django RestFramework 自定义数据的校验与返回

PySuper
2020-10-30 / 0 评论 / 0 点赞 / 21 阅读 / 0 字
温馨提示:
本文最后更新于2024-05-28,若内容或图片失效,请留言反馈。 所有牛逼的人都有一段苦逼的岁月。 但是你只要像SB一样去坚持,终将牛逼!!! ✊✊✊

说真的每次分析源码,大多是迫不得已,实在是封装之后的函数我们没法直接使用当前的数据。但是应该和很多人一样,在我们最后分析源码之后,将数据正常返回,实现了项目功能的时候,还是很开心的。这就是开发的魅力吧!

需求分析

用户登录,前后端提供的字段

前端

  • username:用户名
  • password:密码
  • vercode:图片验证码

后端

  • user:用户对象
  • token:JWT生成的Token

分析

咋一看的时候,觉得还挺简单的,自定义一个返回的函数不就可以了嘛!

但是写完之后才发现,这个vercode一直没有用过啊!

哦豁~~

图片验证码

图片验证码是用户按钮之后,想后端发送请求,后端生成图片验证码,然后将图片返回给前端的

同时,在后端设置session:将用户的请求的图片验证码的字符串保存到session中

这里session中的vercode怎么获取呢???

获取用户输入

前端在发送数据的时候,会将用户输入的图片验证码的值,直接发送到后台

对于这种比较特殊的数据,JWT肯定不会都给我们返回了

源码分析

DRF_JWT

# rest_framwork_jwt/views.py/82

class ObtainJSONWebToken(JSONWebTokenAPIView):
    """
    API View that receives a POST with a user's username and password.

    Returns a JSON Web Token that can be used for authenticated requests.
    """
    serializer_class = JSONWebTokenSerializer

从这段代码我们可以看到 ObtainJSONWebToken 接收到POST请求后,会返回username 和 password

但是,是没有vercode的!

My_CODE

# 这段代码是关于DRF自定义的部分,还要在配置文件里面指定


def get_user_by_account(account):
    """选择自定义校验的用户信息"""
    try:
        user = User.objects.get(username=account)  # 帐号为用户名
    except User.DoesNotExist:
        return None
    else:
        return user


class UsernameMobileAuthBackend(ModelBackend):
    """自定义用户认证"""

    def authenticate(self, request, username=None, password=None, vercode=None, **kwargs):

        current_code = kwargs.get("code")  # 用户输入的图片验证码,
        print("用户输入的图片验证码:", current_code)

        user = get_user_by_account(username)
        if user is not None and user.password == encrypt.md5(password):
            return user


def jwt_response_payload_handler(token, user=None, request=None):
    """在这里修改用户登录后的配置信息"""
    data = {
        "code": 0
        , "msg": "登入成功"
        , "data": {
            'user': user,
            "access_token": token,
        }
    }
    return data

从上面UsernameMobileAuthBackend的authenticate()中我们可以测试

在不修改的情况下,我们是获取不到requestvercodekwargs

修改源码

当你看明白上面的原因和分析,我们可以想想

在request里面,我们连request.method都可以获取到,怎么可能获取不到前端提交的数据!!

从路由开始找!!!

其实找起来还是很快的:

url(r'^authorization/$', obtain_jwt_token, name="authorization"),

from rest_framework_jwt.views import obtain_jwt_token

obtain_jwt_token = ObtainJSONWebToken.as_view()

serializer_class = JSONWebTokenSerializer

这时候,我们进到JWT的序列化器了,分析一下吧

    def __init__(self, *args, **kwargs):
        """
        Dynamically add the USERNAME_FIELD to self.fields.
        """
        super(JSONWebTokenSerializer, self).__init__(*args, **kwargs)

        self.fields[self.username_field] = serializers.CharField()
        self.fields['password'] = PasswordField(write_only=True)

    @property
    def username_field(self):
        return get_username_field()

    def validate(self, attrs):
        credentials = {
            self.username_field: attrs.get(self.username_field),
            'password': attrs.get('password'),
            'code': self.initial_data["vercode"]    # 添加vercode
        }

这里为什么知道self.initial_data里面有vercode???

DeBUG大法了解一下!!!

OK,这里修改好了之后,在获取的时候,直接添加一个默认参数verocde就可以了!

0
  1. 支付宝打赏

    qrcode alipay
  2. 微信打赏

    qrcode weixin

评论区