首页轮播图的开发
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()