DRF实战--首页剩余细节开发

首页轮播图的开发

views

class BannerViewset(mixins.ListModelMixin, viewsets.GenericViewSet):
    """
    获取轮播图列表
    """
    queryset = Banner.objects.all().order_by("index")
    serializer_class = BannerSerializer

serializers

class BannerSerializer(serializers.ModelSerializer):
    class Meta:
        model = Banner
        fields = "__all__"

添加首页新品,复用Goods接口,在filter中添加is_new

    class Meta:
        model = Goods
        fields = ['pricemin', 'pricemax', 'name', 'top_category', 'is_hot', 'is_new']

添加首页展示的商品

views

class IndexCategoryViewset(mixins.ListModelMixin, viewsets.GenericViewSet):
    '''
    首页商品分类数据
    '''
    # 只显示在tab页面上的一级分类下的数据
    queryset = GoodCategory.objects.filter(is_tab=True,name__in=['蔬菜水果','酒水饮料','粮油副食','生鲜食品'])
    serializer_class = IndexCategorySerializer

serializer(重要)

class IndexCategorySerializer(serializers.ModelSerializer):
    # 拿到一个分类之后,反向查询这个分类下的所有品牌
    # brands是GoodsCategoryBrand表中关联分类的外键的rela_name,用作反向查询
    brands = BrandsSerializer(many=True)
    # 拿到对应级别下的所有商品信息
    goods = serializers.SerializerMethodField()
    # sub_cat 是Category表中的自关联字段parent_category的relate_name,
    # 用于一对多反向引用时,点出二级分类,配置在多的那一方
    # 找出所有parent_category等于当前这个一级分类的parent_category的二级分类
    # many=True 表示会有多个
    # 向下找,找到所有的下级分类,也就是二级分类
    sub_cat = GoodCategorySerializer2(many=True)
    # 广告栏展示的商品图
    ad_goods = serializers.SerializerMethodField()

    def get_ad_goods(self, obj):
        print('get_ad_goods', obj.id)
        goods_json = {}
        # 这里传过来的只有'蔬菜水果','酒水饮料','粮油副食','生鲜食品'
        # 而他们的序号已经在IndexAd表中添加过了,所有会找到队友的商品纪录
        ad_goods = IndexAd.objects.filter(category_id=obj.id, )
        if ad_goods:
            good_ins = ad_goods[0].goods
            # 在serializer的方法中使用Serializer的时候,他会检察上下文中有没有包含request,
            # 如果有,那么在返回的图片url中会自动加上域名 http://....
            # 如果没有,那么返回的url只会加上路径 /media/goods/images/......
            goods_json = GoodsSerializer(good_ins, many=False, context={'request': self.context['request']}).data
        return goods_json

    # 该方法的命名为get_加上要序列化的字段
    def get_goods(self, obj):
        print('get_goods', obj.id)
        # 找到对应级别下的所有商品信息
        # category是外键 category_id找到对应的外键表的id(其实category_id是在数据库中保存的外键名)
        # category_id = 3 就是找类别为3的所有商品

        # parent_category_id是外键表自关联的外键,
        # category__parent_category_id=2就是找parent_category_id=2的所有category,
        # 然后再找属于这些category下面的所有goods
        # 或者说goods外键表中的parent_category_id=2等于二的goods

        # category__parent_category__parent_category_id=1
        # 就是找 goods所关联的category的所关联的parent_category中的parent_category_id为1的所有goods
        # goods对应的category是三级,可以通过这个category自身的parent_category_id找到所有的二级所对应的id
        # 或者通过parent_category找到所有的二级对象,而二级对象又可以通过parent_category_id找到所有的三级的id
        # 双下划线表示引出这个对象下所对应的某个值

        # 不会就画图来方便理解
        all_goods = Goods.objects.filter(Q(category_id=obj.id)|Q(category__parent_category_id=obj.id)
                               |Q(category__parent_category__parent_category_id=obj.id))
        # 拿到指定的所有商品之后,通过serializer进行序列化

        # 在serializer的方法中使用Serializer的时候,他会检察上下文中有没有包含request,
        # 如果有,那么在返回的图片url中会自动加上域名 http://....
        # 如果没有,那么返回的url只会加上路径 /media/goods/images/......
        goods_serializer = GoodsSerializer(all_goods,many = True, context={'request': self.context['request']})
        # 注意,这里返回的必须是.data,而不是这个class实例,
        # 在ListModelMinx源码中可以找到相应的用法
        return goods_serializer.data

    class Meta:
        # 拿到商品分类表中的所有字段
        model = GoodCategory
        fields = "__all__"

注意点一

使用自定制的字段

  • 这个字段是要找到对应分类下的所有商品
  • 而GoodCategory没有这个字段
goods = serializers.SerializerMethodField()

注意点二

  • 在serializer的方法中使用Serializer的时候,他会检察上下文中有没有包含request,
  • 如果有,那么在返回的图片url中会自动加上域名 http://…
  • 如果没有,那么返回的url只会加上路径 /media/goods/images/…
    goods_serializer = GoodsSerializer(all_goods,many = True, context={'request': self.context['request']})

自动增加点击数

GoodsListViewset

重写RetrieveModelMixin中的retrieve方法

    """
    Retrieve a model instance.
    """
    def retrieve(self, request, *args, **kwargs):
        instance = self.get_object()
        instance.click_num += 1
        instance.save()
        serializer = self.get_serializer(instance)
        return Response(serializer.data)

自动增加收藏数

UserFavViewSet

重写CreateModelMixin中的perform_create方法

    def perform_create(self, serializer):
        instance = serializer.save()
        goods = instance.goods
        goods.fav_num += 1
        goods.save()

或者,使用信号量完成增减收藏数量的操作

from django.db.models.signals import post_delete, post_save
from django.dispatch import receiver

from user_operation.models import UserFav


@receiver(post_save, sender=UserFav)
def create_userfav(sender, instance=None, created=False, **kwargs):
    if created:
        goods = instance.goods
        goods.fav_num += 1
        goods.save()


@receiver(post_delete, sender=UserFav)
def delete_userfav(sender, instance=None, created=False, **kwargs):
    goods = instance.goods
    goods.fav_num -= 1
    goods.save()
class UserOperationConfig(AppConfig):
    name = 'user_operation'

    def ready(self):
        import user_operation.signals

商品库存数的增减

ShopCartViewset

    def perform_create(self, serializer):
        shop_cart = serializer.save()
        goods = shop_cart.goods
        nums = serializer.validated_data['nums']
        goods.goods_num -= nums
        # goods.goods_num -= shop_cart.nums 错了
        goods.save()

    def perform_destroy(self, instance):
        goods = instance.goods
        goods.goods_num += instance.nums
        goods.save()
        instance.delete()

    def perform_update(self, serializer):
        # 修改商品的库存,通过比对购物车更新前后该商品的数量
        # newstorage = oldstorage + (after-before)
        existed_record = ShoppingCart.objects.get(id=serializer.instance.id)
        existed_nums = existed_record.nums
        saved_record = serializer.save()
        nums = saved_record.nums-existed_nums
        goods = saved_record.goods
        goods.goods_num -= nums
        goods.save()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值