目录
生鲜超市(十) 生鲜超市(十一) 生鲜超市(十二) 生鲜超市(十三)
代码下载
教程
学习自慕课网-前端vue结合后端DjangoFramework的在线生鲜超市
十三、首页、商品数量、缓存和限速功能开发
13.1.轮播图接口实现
首先把pycharm环境改成本地的,vue中local_host也改成本地
(1)goods/serializer
class BannerSerializer(serializers.ModelSerializer): ''' 轮播图 ''' class Meta: model = Banner fields = "__all__"
(2)goods/views.py
class BannerViewset(mixins.ListModelMixin, viewsets.GenericViewSet): """ 首页轮播图 """ queryset = Banner.objects.all().order_by("index") serializer_class = BannerSerializer
(3)url
# 配置首页轮播图的url router.register(r'banners', BannerViewset, base_name="banners")
在后台添加首页轮播图图片
13.2.新品接口功能开发
在设计Goods model时候有一个字段is_new
is_new = models.BooleanField("是否新品",default=False)
实现这个接口只要在goods/filters/GoodsFilter里面添加一个过滤就可以了
class Meta: model = Goods fields = ['pricemin', 'pricemax','is_hot','is_new']
在后台设置几个商品 is_new
13.3.首页商品分类显示功能
首先是大类,然后里面有
- 商品商标(多个)
- 大类下的二级类
- 广告商品
- 所有商品
(1)goods/serializers.py
class BrandSerializer(serializers.ModelSerializer): ''' 大类下面的宣传商标 ''' class Meta: model = GoodsCategoryBrand fields = "__all__" class IndexCategorySerializer(serializers.ModelSerializer): #某个大类的商标,可以有多个商标,一对多的关系 brands = BrandSerializer(many=True) # good有一个外键category,但这个外键指向的是三级类,直接反向通过外键category(三级类),取某个大类下面的商品是取不出来的 goods = serializers.SerializerMethodField() # 在parent_category字段中定义的related_name="sub_cat" # 取二级商品分类 sub_cat = CategorySerializer2(many=True) # 广告商品 ad_goods = serializers.SerializerMethodField() def get_ad_goods(self, obj): goods_json = {} ad_goods = IndexAd.objects.filter(category_id=obj.id, ) if ad_goods: #取到这个商品Queryset[0] good_ins = ad_goods[0].goods #在serializer里面调用serializer的话,就要添加一个参数context(上下文request),嵌套serializer必须加 # serializer返回的时候一定要加 “.data” ,这样才是json数据 goods_json = GoodsSerializer(good_ins, many=False, context={'request': self.context['request']}).data return goods_json #自定义获取方法 def get_goods(self, obj): # 将这个商品相关父类子类等都可以进行匹配 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)) goods_serializer = GoodsSerializer(all_goods, many=True, context={'request': self.context['request']}) return goods_serializer.data class Meta: model = GoodsCategory fields = "__all__"
(2)goods/views.py
class IndexCategoryViewset(mixins.ListModelMixin, viewsets.GenericViewSet): """ 首页商品分类数据 """ # 获取is_tab=True(导航栏)里面的分类下的商品数据 queryset = GoodsCategory.objects.filter(is_tab=True, name__in=["生鲜食品", "酒水饮料"]) serializer_class = IndexCategorySerializer
(3)url
# 首页系列商品展示url router.register(r'indexgoods', IndexCategoryViewset, base_name="indexgoods")
13.4.商品点击数和收藏数
(1)点击数
GoodsListViewSet其中继承了mixins.RetrieveModelMixin(获取商品详情)
源码
class RetrieveModelMixin(object): """ Retrieve a model instance. """ def retrieve(self, request, *args, **kwargs): instance = self.get_object() serializer = self.get_serializer(instance) return Response(serializer.data)
我们只要重写他的retrieve方法就可以了
goods/views
#商品点击数 + 1 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)
class GoodsListViewSet(mixins.ListModelMixin, mixins.RetrieveModelMixin,viewsets.GenericViewSet): ''' list: 商品列表,分页,搜索,过滤,排序 retrieve: 获取商品详情 ''' # authentication_classes = (TokenAuthentication,) #这里必须要定义一个默认的排序,否则会报错 queryset = Goods.objects.all().order_by('id') # 分页 pagination_class = GoodsPagination #序列化 serializer_class = GoodsSerializer filter_backends = (DjangoFilterBackend,filters.SearchFilter,filters.OrderingFilter) # 设置filter的类为我们自定义的类 #过滤 filter_class = GoodsFilter #搜索 search_fields = ('name', 'goods_brief', 'goods_desc') #排序 ordering_fields = ('sold_num', 'shop_price') #商品点击数 + 1 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)
(2)收藏数
前面已经写了UserFavViewset,其中继承了mixins.CreateModelMixin,添加收藏实际就是创建数据库
这里重写它的perform_create方法就可以了
user_operation/view.py
# 用户收藏的商品数量+1 def perform_create(self, serializer): instance = serializer.save() # 这里instance相当于UserFav model,通过它找到goods goods = instance.goods goods.fav_num += 1 goods.save()
class UserFavViewset(viewsets.GenericViewSet, mixins.ListModelMixin, mixins.CreateModelMixin, mixins.DestroyModelMixin): ''' 用户收藏 ''' #permission是用来做权限判断的 # IsAuthenticated:必须登录用户;IsOwnerOrReadOnly:必须是当前登录的用户 permission_classes = (IsAuthenticated,IsOwnerOrReadOnly) #auth使用来做用户认证的 authentication_classes = (JSONWebTokenAuthentication,SessionAuthentication) #搜索的字段 lookup_field = 'goods_id' #动态选择serializer def get_serializer_class(self): if self.action == "list": return UserFavDetailSerializer elif self.action == "create": return UserFavSerializer return UserFavSerializer def get_queryset(self): #只能查看当前登录用户的收藏,不会获取所有用户的收藏 return UserFav.objects.filter(user=self.request.user) # 用户收藏的商品数量+1 def perform_create(self, serializer): instance = serializer.save() # 这里instance相当于UserFav model,通过它找到goods goods = instance.goods goods.fav_num += 1 goods.save()
(3)用信号量实现
delete和create的时候django model都会发送一个信号量出来,用信号量的方式代码分离性更好
收藏数+1和-1
(1)user_operation/signal.py
# users_operation/signals.py from django.db.models.signals import post_save,post_delete from django.dispatch import receiver from user_operation.models import UserFav # post_save:接收信号的方式 #sender: 接收信号的model @receiver(post_save, sender=UserFav) def create_UserFav(sender, instance=None, created=False, **kwargs): # 是否新建,因为update的时候也会进行post_save 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()
(2)user_operation/apps.py
from django.apps import AppConfig class UserOperationConfig(AppConfig): name = 'user_operation' verbose_name = "操作管理" def ready(self): import user_operation.signals
13.5.商品库存和销量修改
库存数量
商品库存数量的行为:
- 新增商品到购物车
- 修改购物车数量
- 删除购物车记录
trade/views.py
# 库存数-1 def perform_create(self, serializer): shop_cart = serializer.save() goods = shop_cart.goods goods.goods_num -= shop_cart.nums goods.save() # 库存数+1 def perform_destroy(self, instance): goods = instance.goods goods.goods_num += instance.nums goods.save() instance.delete() # 更新库存,修改可能是增加页可能是减少 def perform_update(self, serializer): #首先获取修改之前的库存数量 existed_record = ShoppingCart.objects.get(id=serializer.instance.id) existed_nums = existed_record.nums # 先保存之前的数据existed_nums saved_record = serializer.save() #变化的数量 nums = saved_record.nums-existed_nums goods = saved_record.goods goods.goods_num -= nums goods.save()
class ShoppingCartViewset(viewsets.ModelViewSet): """ 购物车功能 list: 获取购物车详情 create: 加入购物车 delete: 删除购物记录 """ permission_classes = (IsAuthenticated, IsOwnerOrReadOnly) authentication_classes = (JSONWebTokenAuthentication, SessionAuthentication) serializer_class = ShopCartSerializer #商品的id lookup_field = "goods_id" def get_serializer_class(self): if self.action == 'list': return ShopCartDetailSerializer else: return ShopCartSerializer #获取购物车列表 def get_queryset(self): return ShoppingCart.objects.filter(user=self.request.user) # 库存数-1 def perform_create(self, serializer): shop_cart = serializer.save() goods = shop_cart.goods goods.goods_num -= shop_cart.nums goods.save() # 库存数+1 def perform_destroy(self, instance): goods = instance.goods goods.goods_num += instance.nums goods.save() instance.delete() # 更新库存,修改可能是增加页可能是减少 def perform_update(self, serializer): #首先获取修改之前的库存数量 existed_record = ShoppingCart.objects.get(id=serializer.instance.id) existed_nums = existed_record.nums # 先保存之前的数据existed_nums saved_record = serializer.save() #变化的数量 nums = saved_record.nums-existed_nums goods = saved_record.goods goods.goods_num -= nums goods.save()