【Django REST framework电商项目笔记】第08章 商品详情页和收藏功能

商品详情页接口实现

左侧商品轮播图 & 商品详情 描述,运费,库存量
热门商品放在另外一个 url
只需要在继承的里面添加这个 mixins.RetrieveModelMixin 就可以了

class GoodsAllViewSet(CacheResponseMixin,
                      mixins.ListModelMixin,
                      mixins.RetrieveModelMixin,
                      viewsets.GenericViewSet):

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

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

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


class GoodsSerializer(serializers.ModelSerializer):
    """
    list all goods
    """
    category = CategorySerializer()
    images = GoodsImageSerializer(many=True)  #这里嵌套了商品图片
    class Meta:
        model = Goods
        fields = "__all__"

将商品详情页完成后就可以来分析我们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
           }

热卖商品接口实现

商品goods中有一个字段是是否热销。获取热销产品,filter中加一个ishot
goods/filters.py 中可以看到已经添加了

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
            },
        }
    }

用户收藏接口实现

这属于用户操作的功能,所以我们将操作写在 user_operation 中
收藏的接口既要继承 viewset,添加收藏create,删除收藏destroy

user_operation/views.py

class UserFavViewSet(viewsets.GenericViewSet,
                     mixins.CreateModelMixin,
                     mixins.ListModelMixin,
                     mixins.DestroyModelMixin):
    """
    list:       用户收藏功能
    retrieve:   判断某个商品是否已经收藏
    create:     收藏商品
    """
    # queryset = UserFav.objects.all()
    permission_classes = (IsAuthenticated, IsOwnerOrReadOnly)
    # serializer_class = UserFavSerializer
    authentication_classes = (JSONWebTokenAuthentication, SessionAuthentication)

    lookup_field = "goods_id"

    def get_queryset(self):
        return UserFav.objects.filter(user=self.request.user)

    def get_serializer_class(self):
        if self.action == "list":
            return UserFavDetailSerializer
        elif self.action == "create":
            return UserFavSerializer

        return UserFavSerializer

user_operation/serializers.py

class UserFavDetailSerializer(serializers.ModelSerializer):
    goods = GoodsSerializer()

    class Meta:
        model = UserFav
        fields = ("goods", "id")

class UserFavSerializer(serializers.ModelSerializer):
    """
    默认的用户收藏的序列化
    """

    # 默认到当前用户 DRF官网:CurrentUserDefault
    user = serializers.HiddenField(
        default=serializers.CurrentUserDefault()
    )

    class Meta:
        model = UserFav

        validators = [
            UniqueTogetherValidator(
                queryset=UserFav.objects.all(),
                fields=("user", "goods"),
                message="已收藏"
            )
        ]

        fields = ("user", "goods", "id")

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

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

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

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

官方文档中
REST框架包含一些在这种情况下可能有用的默认值。
CurrentUserDefault
可用于表示当前用户的默认类。为了使用它,在实例化序列化程序时,'request’必须作为上下文字典的一部分提供。

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

删除功能实现

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

userfavs/id

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

用户反复的对一件商品进行收藏,理论上不应该生成两条收藏关系的记录。
这时候需要django model中的设置参数。

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

如果我们重复了,数据库会给我们抛出异常来
清空原有的表数据,进行makemigration 和 migrate

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

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

实际上 validator 中也为我们提供了 UniqueTogetherValidator
在 Serializer 的 meta 信息中你那个自己定义

   class Meta:
        model = UserFav

        validators = [
            UniqueTogetherValidator(
                queryset=UserFav.objects.all(),
                fields=("user", "goods"),
                message="已收藏"
            )
        ]

        fields = ("user", "goods", "id")

我们的 modelSerializer 和 modelform 一样与 model 紧密联系,所以 model 中的设置它会读取并配置。
这个validate是写在meta信息中的,是因为它不是作用于某一个字段之上了。
400错误,返回的错误消息存放在non_field_errors中。而具体的某一个字段出错,会指明字段的名称。

你可能感兴趣的:(Django)