代码下载
教程
学习自慕课网-前端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)

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

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

ShoppingCartViewset
商品销量
商品的销量只有在支付成功后才会 +1
trade/views.py
for order_good in order_goods:
goods = order_good.goods
goods.sold_num += order_good.goods_num
goods.save()
AlipayView
13.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过期,时间自己可以随便设定
}
这个缓存使用的是内存,每次重启之后就会失效
13.7.drf配置redis缓存
使用django-redis第三方库:http://django-redis-chs.readthedocs.io/zh_CN/latest/#id8 (文档说明)

(1)安装
pip install django-redis
(2)settings

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

13.8.drf的throttle设置api的访问速率
为了防止爬虫对服务器造成的重大压力,对数据进行访问速率限制就显得非常的重要了
官网使用说明:http://www.django-rest-framework.org/api-guide/throttling/

(1)settings中配置

REST_FRAMEWORK = {
#限速设置
'DEFAULT_THROTTLE_CLASSES': (
'rest_framework.throttling.AnonRateThrottle', #未登陆用户
'rest_framework.throttling.UserRateThrottle' #登陆用户
),
'DEFAULT_THROTTLE_RATES': {
'anon': '3/minute', #每分钟可以请求两次
'user': '5/minute' #每分钟可以请求五次
}
}

(2)goods/views.py中使用

from rest_framework.throttling import UserRateThrottle,AnonRateThrottle
class GoodsListViewSet(CacheResponseMixin,mixins.ListModelMixin, mixins.RetrieveModelMixin,viewsets.GenericViewSet): . .
throttle_classes = (UserRateThrottle, AnonRateThrottle)


本文详细介绍了一个在线生鲜超市项目的前后端开发过程,包括Vue前端与Django后端的结合,实现了首页轮播图、新品展示、商品分类、商品库存与销量管理等功能,并介绍了缓存与限速设置的方法。
2459

被折叠的 条评论
为什么被折叠?



