• Django REST framework+Vue 打造生鲜电商项目(笔记十)


     (from:https://www.cnblogs.com/derek1184405959/p/8877643.html  有修改)

    十三、首页、商品数量、缓存和限速功能开发

    首先把pycharm环境改成本地的,vue中local_host也改成本地

    1、轮播图接口实现

    (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")

     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']

    3、首页商品分类显示功能

    首先是大类,然后里面有

    • 商品商标(多个)
    • 大类下的二级类
    • 广告商品
    • 所有商品

    (1)goods/serializers.py

    class BrandSerializer(serializers.ModelSerializer):
        '''
        大类下面的宣传商标
        '''
        class Meta:
            model = GoodsCategoryBrand
            fields = "__all__"
    
    
    class IndexCategorySerializer(serializers.ModelSerializer):
        #某个大类的商标,可以有多个商标,一对多的关系
        brands = BrandSerializer(many=True)
       # 这里容易犯的错是用goods = GoodsSerialize(),但是这是错的。
    # good虽然有一个外键category,但这个外键指向的是三级类,(因为商品一般都是放在第三类之下)。但是我们的GoodsCategory是一级类。
    # 直接反向通过外键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 # 自定义获取方法
    # 格式"get_XXX(self, obj)"
    # obj就是model对象
    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")

    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)

    (3)用信号量实现收藏数的+1和-1

    delete和create的时候django model都会发送一个信号量出来,用信号量的方式代码分离性更好

    (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

    5、商品库存和销量修改

    库存数量

    商品库存数量的行为:

    • 新增商品到购物车
    • 修改购物车数量
    • 删除购物车记录

    trade/views.py

    # 添加到购物车后,修改库存数
        def perform_create(self, serializer):
            shop_cart = serializer.save()
            goods = shop_cart.goods
            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):
            # 获取修改前购物车的记录
            # 获取modelform对应的实例
            exited_record = ShoppingCart.objects.filter(id=serializer.instance.id)
            # 购物车商品数量
            exited_nums = exited_record.nums
            # 修改后购物车记录
            saved_record = serializer.save()
            # 修改前后购物车商品数量变化
            nums = saved_record.nums - exited_nums
            # 获取库存商品
            goods = saved_record.goods
            # 修改库存商品数量
            goods.goods_num -= nums
            goods.save()

    商品销量

    商品的销量只有在支付成功后才会 +1

    这一部分功能是写在AlipayView上的,因为我没有配置阿里支付宝付费服务,所以没有写

    trade/views.py

    for order_good in order_goods:
        goods = order_good.goods
        goods.sold_num += order_good.goods_num
        goods.save()

    6、drf的缓存设置

    为了加速网站的访问速度,将一些数据放到缓存当中,取数据的时候首先去缓存中去,然后再去数据库中取

    我们用drf的一个扩展来实现缓存,github上面的使用说明:http://chibisov.github.io/drf-extensions/docs/#caching

    (1)安装

    pip install drf-extensions

    (2)使用方法

    导入

    from rest_framework_extensions.cache.mixins import CacheResponseMixin

    在GoodsListViewSet中添加缓存功能

    #CacheResponseMixin一定要放在第一个位置
    class GoodsListViewSet(CacheResponseMixin,mixins.ListModelMixin, mixins.RetrieveModelMixin,viewsets.GenericViewSet):

    设置过期时间,settings里面

    #缓存配置
    REST_FRAMEWORK_EXTENSIONS = {
        'DEFAULT_CACHE_RESPONSE_TIMEOUT': 5   #5s过期,时间自己可以随便设定
    }

    这个缓存使用的是内存,每次重启之后就会失效,下面介绍redis缓存

    7、drf配置redis缓存

    使用django-redis第三方库:http://django-redis-chs.readthedocs.io/zh_CN/latest/#id8    (文档说明)

    (1)安装

    pip install django-redis

    (2)在setting.py里添加

    # redis缓存
    CACHES = {
        "default": {
            "BACKEND": "django_redis.cache.RedisCache",
            "LOCATION": "redis://127.0.0.1:6379",
            "OPTIONS": {
                "CLIENT_CLASS": "django_redis.client.DefaultClient",
            }
        }
    }

    8、drf的throttle设置api的访问速率

    为了防止爬虫对服务器造成的重大压力,对数据进行访问速率限制就显得非常的重要了

    官网使用说明:http://www.django-rest-framework.org/api-guide/throttling/

    (1)settings中配置

    REST_FRAMEWORK = {
        'DEFAULT_AUTHENTICATION_CLASSES': (
            'rest_framework.authentication.BasicAuthentication',
            'rest_framework.authentication.SessionAuthentication',
        ),
        #限速设置
        'DEFAULT_THROTTLE_CLASSES': (
                'rest_framework.throttling.AnonRateThrottle',   #未登陆用户,根据ip判断
                'rest_framework.throttling.UserRateThrottle'    #登陆用户,根据token判断
            ),
        'DEFAULT_THROTTLE_RATES': {
            'anon': '3/minute',                   #每分钟可以请求三次
            'user': '5/minute'                    #每分钟可以请求五次
        }

    (2)goods/views.py中使用

  • 相关阅读:
    golang_并发安全: slice和map并发不安全及解决方法
    什么情况下需要用到互斥锁sync.Mutex?
    使用Charles进行HTTPS抓包
    centos6 yum 源失效 404,终于解决了
    GOMAXPROCS你设置对了吗?
    容器资源可见性问题与 GOMAXPROCS 配置
    gflags 使用方式
    分布式训练问题
    NCCL常用环境变量
    git 常用命令
  • 原文地址:https://www.cnblogs.com/linyuhong/p/9949519.html
Copyright © 2020-2023  润新知