python动态类型在django-redis里的坑

问题

在django项目有如下场景:使用django-redis从redis中读取数据并且与请求数据完成比对,比如短信验证码的比对。
依赖包:

django-redis==4.11.0
djangorestframework==3.11.0

SMSCodeView.check_SMSCode方法:

def check_SMSCode(mobile):
    """
    获取短信验证码
    :param mobile:
    :return:
    """
    conn = get_redis_connection('verify_code')
    real_sms = conn.get(f'sms_code_{mobile}').decode()
    return real_sms

首先,当我们使用django-redis从redis中取数据时,得到的数据是byte类型,所以需要使用decode()处理。此时,real_sms得到的是str类型。
校验字段的hook

def validate(self, attrs):
    """
    验证密码及短信验证码
    :param attrs:
    :return:
    """
    # 密码
    if attrs['password'] != attrs['password2']:
        raise serializers.ValidationError('两次密码不一致')

    # 短信验证码
    real_sms_code = SMSCodeView.check_SMSCode(attrs['mobile'])
    # print(real_sms_code)
    # print(type(real_sms_code))
    # print(type(attrs['sms_code']))
    # print(int(attrs['sms_code']))
    if real_sms_code is None:
        raise serializers.ValidationError('短信验证码过期')
    if int(real_sms_code) != int(attrs['sms_code']):
        raise serializers.ValidationError('短信验证码错误')

    return attrs

因此,代码块中的real_sms_codestr类型,而attrs['sms_code']也是str类型。bug发生前,我想当然的认为,他们本质都是短信验证码,只不过是str类型,因此可以直接比对是否相等。但是项目运行后一直在报错,并且提示短信验证码错误。当我print相关对象后,才发现了问题。
print结果

 355888
<class 'str'>
<class 'str'>
355888

显然,redis返回给我们的字符串多一个空格。测试了短信验证码生成的逻辑代码后,发现是错误书写f-string时带来的问题。

import random


print(f'{random.randint(0, 999999):06}')
print(f'{random.randint(0, 999999): 06}')

输出

779392
 200457

所以,一定不要随便加空格!

小结

Python自身的特性保证了代码的简洁书写,但是也在一定程度上增加了debug的成本。建议大家好好利用Python类型注解来构建代码。
项目地址:https://github.com/LMFrank/django_library

你可能感兴趣的:(django)