美文网首页django.tip
Vue+Django REST framework 打造生鲜电商

Vue+Django REST framework 打造生鲜电商

作者: 吕阳 | 来源:发表于2018-01-10 14:01 被阅读90次

    7-6

    jie sha le vue deng l ,ya an an

    MD: dian ha ha ma e neng deng lu
    1.settng

    AUTHENTICATION_BACKENDS = (
        'users.views.CustomBackend',
    )
    
    1. User/views
    from django.contrib.auth.backends import ModelBackend
    from django.db.models import Q
    from django.shortcuts import render
    
    # Create your views here.
    from django.contrib.auth import get_user_model
    
    User = get_user_model()
    
    
    class CustomBackend(ModelBackend):
        """
        自定义用户验证
        """
        def authenticate(self, username=None, password=None, **kwargs):
            try:
                user = User.objects.get(Q(username=username)|Q(mobile=username))
                if user.check_password(password):
                    return user
            except Exception as e:
                return None
    
    1. url
     #jwt
        url(r'^login/', obtain_jwt_token),
    
    
    

    微信截图_20180109141110.png

    jwt setting

    import datetime
    JWT_AUTH = {
        'JWT_EXPIRATION_DELTA': datetime.timedelta(days=7),
        'JWT_AUTH_HEADER_PREFIX': 'JWT',
    }
    

    7-7

    发送短信
    1.utill/yunian.py

    import json
    import requests
    
    
    class YunPian(object):
    
        def __init__(self, api_key):
            self.api_key = api_key
            self.single_send_url = "https://sms.yunpian.com/v2/sms/single_send.json"
    
        def send_sms(self, code, mobile):
            parmas = {
                "apikey": self.api_key,
                "mobile": mobile,
                "text": "【慕学生鲜】您的验证码是{code}。如非本人操作,请忽略本短信".format(code=code)
            }
    
            response = requests.post(self.single_send_url, data=parmas)
            re_dict = json.loads(response.text)
            return re_dict
    
    
    if __name__ == "__main__":
        yun_pian = YunPian("")
        yun_pian.send_sms("2017", "")
    
    
    

    ip白名单

    微信截图_20180109144938.png
    • setting
    #手机号码正则表达式
    REGEX_MOBILE = "^1[358]\d{9}$|^147\d{8}$|^176\d{8}$"
    
    
    #云片网设置
    APIKEY = ""
    

    7-8~7-9 发送短信验证码

    • user/views.py
    class SmsCodeViewset(CreateModelMixin, viewsets.GenericViewSet):
        """
        发送短信验证码
        """
        serializer_class = SmsSerializer
    
        def generate_code(self):
            """
            生成四位数字的验证码
            :return:
            """
            seeds = "1234567890"
            random_str = []
            for i in range(4):
                random_str.append(choice(seeds))
    
            return "".join(random_str)
    
        def create(self, request, *args, **kwargs):
            serializer = self.get_serializer(data=request.data)
            serializer.is_valid(raise_exception=True)
    
            mobile = serializer.validated_data["mobile"]
    
            yun_pian = YunPian(APIKEY)
    
            code = self.generate_code()
    
            sms_status = yun_pian.send_sms(code=code, mobile=mobile)
    
            if sms_status["code"] != 0:
                return Response({
                    "mobile":sms_status["msg"]
                }, status=status.HTTP_400_BAD_REQUEST)
            else:
                code_record = VerifyCode(code=code, mobile=mobile)
                code_record.save()
                return Response({
                    "mobile":mobile
                }, status=status.HTTP_201_CREATED)
    
    
    
    • user/serializer.py
    import re
    from rest_framework import serializers
    from django.contrib.auth import get_user_model
    from datetime import datetime
    from datetime import timedelta
    from rest_framework.validators import UniqueValidator
    
    from .models import VerifyCode
    
    from MxShop.settings import REGEX_MOBILE
    
    User = get_user_model()
    
    
    class SmsSerializer(serializers.Serializer):
        mobile = serializers.CharField(max_length=11)
    
        def validate_mobile(self, mobile):
            """
            验证手机号码
            :param data:
            :return:
            """
    
            # 手机是否注册
            if User.objects.filter(mobile=mobile).count():
                raise serializers.ValidationError("用户已经存在")
    
            # 验证手机号码是否合法
            if not re.match(REGEX_MOBILE, mobile):
                raise serializers.ValidationError("手机号码非法")
    
            # 验证码发送频率
            one_mintes_ago = datetime.now() - timedelta(hours=0, minutes=1, seconds=0)
            if VerifyCode.objects.filter(add_time__gt=one_mintes_ago, mobile=mobile).count():
                raise serializers.ValidationError("距离上一次发送未超过60s")
    
            return mobile
    

    这两节主题内容是服务器产生4位数字验证码,发给云片网,自己保存在服务器。

    7-10~7-11

    • 接受前端注册发送过来的表单,其中验证码不在user的models字段里面。

    • user/views.py

    class UserViewset(CreateModelMixin, mixins.UpdateModelMixin, mixins.RetrieveModelMixin, viewsets.GenericViewSet):
        """
        用户
        """
        serializer_class = UserRegSerializer
        queryset = User.objects.all()
        authentication_classes = (JSONWebTokenAuthentication, authentication.SessionAuthentication )
    
        def get_serializer_class(self):
            if self.action == "retrieve":
                return UserDetailSerializer
            elif self.action == "create":
                return UserRegSerializer
    
            return UserDetailSerializer
    
        # permission_classes = (permissions.IsAuthenticated, )
        def get_permissions(self):
            if self.action == "retrieve":
                return [permissions.IsAuthenticated()]
            elif self.action == "create":
                return []
    
            return []
    
        def create(self, request, *args, **kwargs):
            serializer = self.get_serializer(data=request.data)
            serializer.is_valid(raise_exception=True)
            user = self.perform_create(serializer)
    
            re_dict = serializer.data
            payload = jwt_payload_handler(user)
            re_dict["token"] = jwt_encode_handler(payload)
            re_dict["name"] = user.name if user.name else user.username
    
            headers = self.get_success_headers(serializer.data)
            return Response(re_dict, status=status.HTTP_201_CREATED, headers=headers)
    
        def get_object(self):
            return self.request.user
    
        def perform_create(self, serializer):
            return serializer.save()
    
    • user/serializer.py
    class UserRegSerializer(serializers.ModelSerializer):
        code = serializers.CharField(required=True, write_only=True, max_length=4, min_length=4,label="验证码",
                                     error_messages={
                                         "blank": "请输入验证码",
                                         "required": "请输入验证码",
                                         "max_length": "验证码格式错误",
                                         "min_length": "验证码格式错误"
                                     },
                                     help_text="验证码")
        username = serializers.CharField(label="用户名", help_text="用户名", required=True, allow_blank=False,
                                         validators=[UniqueValidator(queryset=User.objects.all(), message="用户已经存在")])
    
        password = serializers.CharField(
            style={'input_type': 'password'},help_text="密码", label="密码", write_only=True,
        )
    
        # def create(self, validated_data):
        #     user = super(UserRegSerializer, self).create(validated_data=validated_data)
        #     user.set_password(validated_data["password"])
        #     user.save()
        #     return user
    
        def validate_code(self, code):
            # try:
            #     verify_records = VerifyCode.objects.get(mobile=self.initial_data["username"], code=code)
            # except VerifyCode.DoesNotExist as e:
            #     pass
            # except VerifyCode.MultipleObjectsReturned as e:
            #     pass
            verify_records = VerifyCode.objects.filter(mobile=self.initial_data["username"]).order_by("-add_time")
            if verify_records:
                last_record = verify_records[0]
    
                five_mintes_ago = datetime.now() - timedelta(hours=0, minutes=5, seconds=0)
                if five_mintes_ago > last_record.add_time:
                    raise serializers.ValidationError("验证码过期")
    
                if last_record.code != code:
                    raise serializers.ValidationError("验证码错误")
    
            else:
                raise serializers.ValidationError("验证码错误")
    
        def validate(self, attrs):
            attrs["mobile"] = attrs["username"]
            del attrs["code"]
            return attrs
    
        class Meta:
            model = User
            fields = ("username", "code", "mobile", "password")
    
    
    • mxshop/url
    router.register(r'codes', SmsCodeViewset, base_name="codes")
    
    
    router.register(r'users', UserViewset, base_name="users")
    
    
    • users/models.py
    class UserProfile(AbstractUser):
        """
        用户
        """
        name = models.CharField(max_length=30, null=True, blank=True, verbose_name="姓名")
        birthday = models.DateField(null=True, blank=True, verbose_name="出生年月")
        gender = models.CharField(max_length=6, choices=(("male", u"男"), ("female", "女")), default="female", verbose_name="性别")
        mobile = models.CharField(null=True, blank=True, max_length=11, verbose_name="电话")
        email = models.EmailField(max_length=100, null=True, blank=True, verbose_name="邮箱")
    
        class Meta:
            verbose_name = "用户"
            verbose_name_plural = verbose_name
    
        def __str__(self):
            return self.username
    
    
    • 用户的电话字段,设为空,可以不添加电话登陆。
    • users/signals
    # _*_ coding: utf-8 _*_
    __author__ = 'lv'
    __date__ = '2018/1/10 13:51'
    
    from django.db.models.signals import post_save
    from django.dispatch import receiver
    from rest_framework.authtoken.models import Token
    from django.contrib.auth import get_user_model
    
    User = get_user_model()
    
    @receiver(post_save, sender=User)
    def create_user(sender, instance=None, created=False, **kwargs):
        if created:
            password = instance.password
            instance.set_password(password)
            instance.save()
    
    
    • 如果没写signals就会报错,没有返回taken

    1.在xadmin后台添加验证码

    微信截图_20180110135416.png

    2.在users提交post 表单会返回token自动登陆,测试如下:

    微信截图_20180110135509.png
    • 返回错误字段
    http_code
    {
        codo:[""],
        username:[""]
    }
    

    比传统的

    status: 1
    {
        msg:{
        mobile:[""],
        code:[""]
    }
          
    }
    
    
    
    * 更改数据库 迁移
    
    * 信号就是全局通知,这个信号就是在创建用户的时候,发送全局通知,然后在信号中处理,存入数据库。
    
    
    * 如果要返回token,直接登陆就要在views.py里面引入framework_jwt生成token。
    
    
    
    
    
    
    
    
    

    相关文章

      网友评论

        本文标题:Vue+Django REST framework 打造生鲜电商

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