网站开发python从入门到精通python 实战实验室

12- vue django restful framework

2018-03-15  本文已影响492人  天涯明月笙

Vue+Django REST framework实战

搭建一个前后端分离的生鲜超市网站

商品详情页,商品收藏

viewsets实现商品详情页接口

左侧商品轮播图 & 商品详情 描述,运费,库存量。

热门商品放在另外一个url

只需要在继承的里面添加这个mixins.RetrieveModelMixin就可以了。

实现代码:

class GoodsListViewSet(mixins.ListModelMixin, mixins.RetrieveModelMixin,viewsets.GenericViewSet):

查看Serializer,将其中的外键指向的Goodsimage

如何执行外键型的字段Serializer呢?答案: 进行嵌套的使用。

实现代码:

class GoodsImageSerializer(serializers.ModelSerializer):
    class Meta:
        model = GoodsImage
        fields = ("image", )

如上面代码新建一个Serializer。然后下面进行字段的嵌套

实现代码:

GoodsSerializer中

    images = GoodsImageSerializer(many=True)

这里的值叫什么名称与我们在models中自定义的related_name有关。
一个goods对应的GoodsImage是有多条的。一定要添加many=true

将商品详情页完成后就可以来分析我们vue的源码。组件是productDetail productDetail.vue

    created () {
        this.productId = this.$route.params.productId;
        var productId = this.productId
        if(cookie.getCookie('token')){
          getFav(productId).then((response)=> {
            this.hasFav = true
          }).catch(function (error) {
            console.log(error);
          });
        }
        this.getDetails();
    },

列表页跳转到某一个详情页的时候,vue router里面有一个productId
会通过router里面的productdetail传递进来

src/router/index.js实现代码:

 {
            path: 'productDetail/:productId',
            name: 'productDetail',
            component: productDetail,
            meta: {
              title: '商品详情',
              need_log: false
            }
          

src/api/api.js中商品详情接口配置,改为本地的api接口localhost

//商品详情
export const getGoodsDetail = goodId => { return axios.get(`${host}/goods/${goodId}`+'/') }

热卖商品接口实现

商品goods中有一个字段是是否热销。获取热销产品,filter中加一个ishot

goods/filters.py:

实现代码:

        fields = ['pricemin', 'pricemax', 'name', 'is_hot']

在后台管理系统之中添加三条热卖数据为true

markmark

可以看到这其中的HotSales

src/views/productDetail/hotSales.vue:

它在create的时候调用了getHotSales

            getHotSales() { //请求热卖商品
              getGoods({
                is_hot:true
              })
                .then((response)=> {
                    console.log(response.data)
                    this.hotProduct = response.data.results;

                }).catch(function (error) {
                    console.log(error);
                });
            }

实际上还是调用了getGoods接口,只是设置了参数is_hot为true而已
返回的json值会被放入response的data里面,而我们的数据放在result里面

返回的json格式:

{
    "count": 3,
    "next": null,
    "previous": null,
    "results": [
        {
            "id": 102,
            "category": {
                "id": 55,
                "name": "方便速食",
                "code": "方便速食",
                "desc": "",
                "category_type": 2,
                "is_tab": false,
                "add_time": "2018-02-14T03:45:05.659267",
                "parent_category": 40
            },
        }
    }
markmark

将数据进行过滤之后,vue进行v-for的遍历,遍历之后使用router-link做一个跳转

然后将值进行填充。

用户收藏接口实现

这属于用户操作的功能,所以我们将操作写在user_operation中

收藏的接口既要继承viewset,添加收藏create,删除收藏destroy

实现代码:

class UserFavViewset(viewsets.GenericViewSet, mixins.CreateModelMixin, mixins.DestroyModelMixin):

新建一个配套的Serializers.py

实现代码:

# encoding: utf-8
__author__ = 'mtianyan'
__date__ = '2018/3/10 0010 09:54'
from rest_framework import serializers
from user_operation.models import UserFav


class UserFavSerializer(serializers.ModelSerializer):
    class Meta:
        model = UserFav
        fields = ("user", "goods")

此时在views中继续进行配置queryset等

class UserFavViewset(viewsets.GenericViewSet, mixins.CreateModelMixin, mixins.DestroyModelMixin):
    """
    用户收藏功能
    """
    queryset = UserFav.objects.all()
    serializer_class = UserFavSerializer

配置相应的url等在urls.py中

# 配置用户收藏的url
router.register(r'userfavs', UserFavViewset, base_name="userfavs")
markmark

当前的实现是我们可以选择用户,选择商品进行post,但是实际的逻辑应该是获取到当前的用户,我们只需要post商品过去就可以了。

我们希望我们的UserFavSerializer获取的是当前登录用户的user。

如何让Serializer自动帮我们填充当前的user?

http://www.django-rest-framework.org/api-guide/validators/#currentuserdefault

官方文档中

REST框架包含一些在这种情况下可能有用的默认值。

CurrentUserDefault
可用于表示当前用户的默认类。为了使用它,在实例化序列化程序时,'request'必须作为上下文字典的一部分提供。

owner = serializers.HiddenField(
    default=serializers.CurrentUserDefault()
)

为我们的UserFavSerializer添加代码:

    user = serializers.HiddenField(
        default=serializers.CurrentUserDefault()
    )

如果对于一个Serializer我们想为它添加删除的功能,就要将该条记录的id也返回回来
取消收藏就会变得容易。

添加商品收藏列表功能

实现代码:

class UserFavViewset(viewsets.GenericViewSet, mixins.ListModelMixin, mixins.CreateModelMixin, mixins.DestroyModelMixin):

目前这样的配置只会返回我们商品的id以及这条收藏关系记录的id

删除功能实现

restful api 删除时要用到的http里面的delete方法。

url格式为

userfavs/id

删除哪一个收藏记录。id为收藏关系对应的id。

markmark

204代表删除成功,2开头的一般都是操作成功的。

用户反复的对一件商品进行收藏,理论上不应该生成两条收藏关系的记录。

这时候需要django model中的设置参数。

        # 多个字段作为一个联合唯一索引
        unique_together = ("user", "goods")

如果我们重复了,数据库会给我们抛出异常来

清空原有的表数据,进行makemigration 和 migrate

markmark

可以通过navicat查看到我们的唯一索引

{
    "non_field_errors": [
        "字段 user, goods 必须能构成唯一集合。"
    ]
}

实际上validator中也为我们提供了UniqueTogetherValidator

在Serializer的meta信息中你那个自己定义

        # 使用validate方式实现唯一联合
        validators = [
            UniqueTogetherValidator(
                queryset=UserFav.objects.all(),
                fields=('user', 'goods'),
                message="已经收藏"
            )
        ]

我们的modelSerializer和modelform一样与model紧密联系,所以model中的设置它会读取并配置。

这个validate是写在meta信息中的,是因为它不是作用于某一个字段之上了。

400错误,返回的错误消息存放在non_field_errors中。而具体的某一个字段出错,会指明字段的名称。

整体错误信息。

上一篇下一篇

猜你喜欢

热点阅读