Django注册功能API

基本步骤

还是和之前的开发一个API功能的步骤一样:

  1. 在views.py里面新建一个视图
  2. 指明queryset和序列化器
  3. 在urls.py中声明访问路径

新建视图

from rest_framework.generics import CreateAPIView
from .models import User
from .serializers import UserModelSerializer
class UserAPIView(CreateAPIView):
    """用户信息视图"""
    #这里的queryset可加可不加
    queryset = User.objects.all()
    serializer_class = UserModelSerializer

这个注册视图继承的是CreateAPIView,看了一下源码,CreateAPIView里面已经实现好post方法了,相当于是专门拿来做新建数据的API。继承了它,我们不需要在UserAPIView中重写post方法。然后是定义queryset,其实这里加不加都不影响,因为是post方法。最后定义序列化器。

新建序列化器

得新建一个文件serializers.py,里面的代码如下:

from rest_framework import serializers
from .models import User
import re
from .utils import get_user_by_account
from django.contrib.auth.hashers import make_password
class UserModelSerializer(serializers.ModelSerializer):
    sms_code = serializers.CharField(min_length=4, max_length=6, required=True, write_only=True, help_text="短信验证码")
    token = serializers.CharField(max_length=1024, read_only=True, help_text="token认证字符串")
    class Meta:
        model = User
        fields = ['id', 'username', 'token', 'mobile', 'sms_code', 'password']
        extra_kwargs = {
            "mobile":{
                "write_only": True,
            },
            "username":{
                "read_only": True,
            },
            "id":{
                "read_only": True,
            },
            "password":{
                "write_only": True,
            }
        }

    def validate(self, attrs):
        mobile = attrs.get("mobile")
        sms_code = attrs.get("sms_code")
        password = attrs.get("password")
        # 验证手机号码的格式
        if not re.match("^1[3-9]\d{9}", mobile):
            raise serializers.ValidationError("对不起,手机号码格式有误")

        # 验证手机号是否已经注册过
        ret = get_user_by_account(mobile)
        if ret is not None:
            raise serializers.ValidationError("对不起,手机已经被注册")

        # todo 验证短信验证码是否正确

        return attrs

    def create(self, validated_data):
        """保存用户信息"""
        validated_data.pop("sms_code") #移除掉不需要的数据
        #对密码进行加密
        raw_password = validated_data.get("password")
        hash_password = make_password(raw_password)
        #对用户名设置一个默认值
        username = validated_data.get("mobile")
        #调用序列化器提供的create方法
        # super().create()
        user = User.objects.create(
            mobile=username,
            username=username,
            password=hash_password,
        )

        from rest_framework_jwt.settings import api_settings
        # 使用restframework.jwt提供手动生成token的方法生成登录状态
        jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
        jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
        payload = jwt_payload_handler(user)
        user.token = jwt_encode_handler(payload)

        return user

之前有提到过,序列化器中可以完成:字段声明、模型序列化器声明、验证方法、存储数据方法,4个功能。注册API中全部都用到了。
因为sms_code和token是User表中不存在的字段,因此我们需要在序列化器中声明。Meta是内部类,指定所用的模型表和需要序列化的字段。之所以我们post的时候需要传三个值(mobile, sms_code, password),成功插入之后返回(id, username, token),是因为我们设置了每个值的write_only和read_only字段,write_only为True表示只写,只能通过post发过来,read_only为True表示只读,将结果返回回去。
我们还需要对手机号码进行验证,所以重写了validate方法,使用正则检查手机号的格式是否正确,在数据库中查找手机号是不是已经注册过,只有条件都符合了才进行下一步,否则抛出异常。
注册post还希望在我们验证成功之后对用户的信息进行保存,所以重写create方法。因为在数据模型中不存在sms_code这个字段,所以我们使用set的pop方法将其删除。密码不能明文存储,所以调用内置的make_password对密码进行加密。使用User.objects.create方法将准备好的数据插入数据库。我们还希望用户通过注册之后不需要在去登录,所以要返回一个token,使用rest_framework_jwt生成token,返回。

路由设置

path(r'reg/', views.UserAPIView.as_view()),

至此,就完成了用户发送post请求之后,验证手机号码,存储用户信息,生成token,返回的注册API功能。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值