zoukankan      html  css  js  c++  java
  • 关于REST风格API的设计

    用户地址管理代码

    后端

    在users/views.py中添加视图

    class AddressViewSet(mixins.CreateModelMixin, mixins.UpdateModelMixin, GenericViewSet):
        """
        用户地址新增与修改
        """
        serializer_class = serializers.UserAddressSerializer
        permissions = [IsAuthenticated]
    
        def get_queryset(self):
            return self.request.user.addresses.filter(is_deleted=False)
    
        # GET /addresses/
        def list(self, request, *args, **kwargs):
            """
            用户地址列表数据
            """
            queryset = self.get_queryset()
            serializer = self.get_serializer(queryset, many=True)
            user = self.request.user
            return Response({
                'user_id': user.id,
                'default_address_id': user.default_address_id,
                'limit': constants.USER_ADDRESS_COUNTS_LIMIT,
                'addresses': serializer.data,
            })
    
        # POST /addresses/
        def create(self, request, *args, **kwargs):
            """
            保存用户地址数据
            """
            # 检查用户地址数据数目不能超过上限
            count = request.user.addresses.count()
            if count >= constants.USER_ADDRESS_COUNTS_LIMIT:
                return Response({'message': '保存地址数据已达到上限'}, status=status.HTTP_400_BAD_REQUEST)
    
            return super().create(request, *args, **kwargs)
    
        # delete /addresses/<pk>/
        def destroy(self, request, *args, **kwargs):
            """
            处理删除
            """
            address = self.get_object()
    
            # 进行逻辑删除
            address.is_deleted = True
            address.save()
    
            return Response(status=status.HTTP_204_NO_CONTENT)
    
        # put /addresses/pk/status/
        @action(methods=['put'], detail=True)
        def status(self, request, pk=None):
            """
            设置默认地址
            """
            address = self.get_object()
            request.user.default_address = address
            request.user.save()
            return Response({'message': 'OK'}, status=status.HTTP_200_OK)
    
        # put /addresses/pk/title/
        # 需要请求体参数 title
        @action(methods=['put'], detail=True)
        def title(self, request, pk=None):
            """
            修改标题
            """
            address = self.get_object()
            serializer = serializers.AddressTitleSerializer(instance=address, data=request.data)
            serializer.is_valid(raise_exception=True)
            serializer.save()
            return Response(serializer.data)
    

    在users/serializers.py中添加序列化器

    class UserAddressSerializer(serializers.ModelSerializer):
        """
        用户地址序列化器
        """
        province = serializers.StringRelatedField(read_only=True)
        city = serializers.StringRelatedField(read_only=True)
        district = serializers.StringRelatedField(read_only=True)
        province_id = serializers.IntegerField(label='省ID', required=True)
        city_id = serializers.IntegerField(label='市ID', required=True)
        district_id = serializers.IntegerField(label='区ID', required=True)
    
        class Meta:
            model = Address
            exclude = ('user', 'is_deleted', 'create_time', 'update_time')
    
        def validate_mobile(self, value):
            """
            验证手机号
            """
            if not re.match(r'^1[3-9]d{9}$', value):
                raise serializers.ValidationError('手机号格式错误')
            return value
    
        def create(self, validated_data):
            """
            保存
            """
            validated_data['user'] = self.context['request'].user
            return super().create(validated_data)
    
    
    class AddressTitleSerializer(serializers.ModelSerializer):
        """
        地址标题
        """
        class Meta:
            model = Address
            fields = ('title',)
    

    在users/urls.py中添加路由

    router = routers.DefaultRouter()
    router.register(r'addresses', views.AddressViewSet, base_name='addresses')
    
    urlpatterns += router.urls
    # POST /addresses/ 新建  -> create
    # PUT /addresses/<pk>/ 修改  -> update
    # GET /addresses/  查询  -> list
    # DELETE /addresses/<pk>/  删除 -> destroy
    # PUT /addresses/<pk>/status/ 设置默认 -> status
    # PUT /addresses/<pk>/title/  设置标题 -> title
    

    前端

    修改user_center_site.js的mounted

    mounted: function(){
            ...
            // 补充获取地址数据的请求
            axios.get(this.host + '/addresses/', {
                    headers: {
                        'Authorization': 'JWT ' + this.token
                    },
                    responseType: 'json'
                })
                .then(response => {
                    this.addresses = response.data.addresses;
                    this.limit = response.data.limit;
                    this.default_address_id = response.data.default_address_id;
                })
                .catch(error => {
                    status = error.response.status;
                    if (status == 401 || status == 403) {
                        location.href = 'login.html?next=/user_center_site.html';
                    } else {
                        alert(error.response.data.detail);
                    }
                })
        },
    

    修改user_center_site.js的methods

            // 保存地址
            save_address: function(){
                if (this.error_receiver || this.error_place || this.error_mobile || this.error_email || !this.form_address.province_id || !this.form_address.city_id || !this.form_address.district_id ) {
                    alert('信息填写有误!');
                } else {
                    this.form_address.title = this.form_address.receiver;
                    if (this.editing_address_index === '') {
                        // 新增地址
                        axios.post(this.host + '/addresses/', this.form_address, {
                            headers: {
                                'Authorization': 'JWT ' + this.token
                            },
                            responseType: 'json'
                        })
                        .then(response => {
                            // 将新地址添加大数组头部
                            this.addresses.splice(0, 0, response.data);
                            this.is_show_edit = false;
                        })
                        .catch(error => {
                            console.log(error.response.data);
                        })
                    } else {
    
                        // 修改地址
                        axios.put(this.host + '/addresses/' + this.addresses[this.editing_address_index].id + '/', this.form_address, {
                            headers: {
                                'Authorization': 'JWT ' + this.token
                            },
                            responseType: 'json'
                        })
                        .then(response => {
                            this.addresses[this.editing_address_index] = response.data;
                            this.is_show_edit = false;
                        })
                        .catch(error => {
                            alert(error.response.data.detail || error.response.data.message);
                        })
                    }
                }
            },
            // 删除地址
            del_address: function(index){
                axios.delete(this.host + '/addresses/' + this.addresses[index].id + '/', {
                        headers: {
                            'Authorization': 'JWT ' + this.token
                        },
                        responseType: 'json'
                    })
                    .then(response => {
                        // 从数组中移除地址
                        this.addresses.splice(index, 1);
                    })
                    .catch(error => {
                        console.log(error.response.data);
                    })
            },
            // 设置默认地址
            set_default: function(index){
                axios.put(this.host + '/addresses/' + this.addresses[index].id + '/status/', {}, {
                        headers: {
                            'Authorization': 'JWT ' + this.token
                        },
                        responseType: 'json'
                    })
                    .then(response => {
                        this.default_address_id = this.addresses[index].id;
                    })
                    .catch(error => {
                        console.log(error.response.data);
                    })
            },
            // 展示编辑标题
            show_edit_title: function(index){
                this.input_title = this.addresses[index].title;
                for(var i=0; i<index; i++) {
                    this.is_set_title.push(false);
                }
                this.is_set_title.push(true);
            } ,
            // 保存地址标题
            save_title: function(index){
                if (!this.input_title) {
                    alert("请填写标题后再保存!");
                } else {
                    axios.put(this.host + '/addresses/' + this.addresses[index].id + '/title/', {
                            title: this.input_title
                        }, {
                            headers: {
                                'Authorization': 'JWT ' + token
                            },
                            responseType: 'json'
                        })
                        .then(response => {
                            this.addresses[index].title = this.input_title;
                            this.is_set_title = [];
                        })
                        .catch(error => {
                            console.log(error.response.data);
                        })
                }
            },
            // 取消保存地址
            cancel_title: function(index){
                this.is_set_title = [];
            }
  • 相关阅读:
    Cookie和Session
    Servlet中关于中文乱码
    单例模式
    document对象-操作元素的文档结构
    JS实现简单的多选选项的全选反选按钮
    js实现表单验证
    servlet
    http(Hyper Text Transfer Protocol)
    Vue之webpack打包
    Flink用户画像系统之实时品牌爱好
  • 原文地址:https://www.cnblogs.com/user0712/p/10094509.html
Copyright © 2011-2022 走看看