商品点击数修改:
默认情况下 前端页面请求发送的参数中没有相应字段的话。后端mixins.RetrieveModelMixin类也不会额外增加请求参数之外的字段进行修改保存。所以 如果想要使后端自动增加点击数 就需要我们重写retrieve函数(该函数来源于mixins.RetrieveModelMixin类中)
goods/views.py/GoodsListViewset:
def retrieve(self, request, *args, **kwargs):
# 手动的修改click_num字段
instance = self.get_object()
instance.click_num += 1
instance.save()
serializer = self.get_serializer(instance)
return Response(serializer.data)
商品收藏数修改
同样收餐数也是 当用户点击收藏的时候,后台操作的是UserFave表。而不会影响到Goods表。所以我们需要做个修改使Goods表也能记录到收藏数
# apps/user_operation/UserFavViewset
def perform_create(self, serializer):
instance = serializer.save()
goods = instance.goods
goods.fav_num += 1
goods.save()
这是一种方法,同时也可以用信号量的方式:
1. 在goods创建singals.py
# encoding:utf-8
from django.db.models.signals import post_save
from django.dispatch import receiver
from django.contrib.auth import get_user_model
from .models import UserFav
User = get_user_model()
# 参数一,接收什么信号,接收哪个model的信号 也就是说信号来自哪里
@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()
取消收藏时也可以这么操作
# encoding:utf-8
from django.db.models.signals import post_delete
from django.dispatch import receiver
from django.contrib.auth import get_user_model
from .models import UserFav
User = get_user_model()
@receiver(post_delete, sender=UserFav)
def delete_user(sender, instance=None, created=False, **kwargs):
goods = instance.goods
goods.fav_num -= 1
goods.save()
商品库存的修改
商品库存 教程里面使用简单的关联,即购物车数据的变化影响商品库存的变化
所以购物车新增商品,则商品库存就减少商品 。购物车减少商品, 商品库存就增加商品
操作都在trade/views.py/ShoppingCartViewset中进行的
先说第一个,购物车新增商品
class ShoppingCartViewset(viewsets.ModelViewSet):
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()
# 要在delete()之前完成,否则无法找购物车中对应的商品
instance.delete()
修改
def perform_update(self, serializer):
# 先拿到购物车中的数量
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()
商品的销量: 使用支付成功与否来确定
// apps/trade/views.py/AliPayViewset/post
existed_orders = OrderInfo.objects.filter(order_sn=order_sn)
for existed_order in existed_orders:
# 主要是改这里 现货区订单中的商品
order_goods = existed_order.goods.all()
# 然后迭代中所有的善品 增加购物车中的销售数量
for order_good in order_goods:
goods = order_good.goods
goods.sold_num += order_good.goods_num
goods.save()
drf缓存
django自己本身有缓存机制。 不过教程中主要是说drf的缓存
https://docs.djangoproject.com/zh-hans/2.0/topics/cache/
所以接下来来说drf缓存吧, drf是使用一个drf-extensions的插件 它本质上也是对django的缓存进行扩展
先上github插件地址:https://github.com/chibisov/drf-extensions
文档地址:http://chibisov.github.io/drf-extensions/docs/
其他都不管,有兴趣自己去看,就看这里
这里面有简单的例子。我这里直接上
# settings.py
# 设置缓存更新的时间节点
REST_FRAMEWORK_EXTENSIONS = {
'DEFAULT_CACHE_RESPONSE_TIMEOUT': 60 * 15
}
# 在需要缓存的地方加上如下代码
from rest_framework_extensions.cache.mixins import CacheResponseMixin
# ---------------------> 这里 最好放在第一个来继承。
class GoodsListViewset(CacheResponseMixin, mixins.ListModelMixin, mixins.RetrieveModelMixin, viewsets.GenericViewSet):
缓存一般是用来处理公共展示的数据。 不涉及到修改数据的。
该方法有些问题。
1. 就是他是将数据保存至内存中。 服务重启之后他数据就丢失。
2. 不是所有的操作都是获取所有的goods商品,有些要加过滤,有些是不同的用户。
不可能所有的查询都指向同一组数据。
3. 为了解决这些问题,可以使用redis数据库做缓存
redis:
安装django专用的redis插件
github:https://github.com/niwinz/django-redis
文档:https://django-redis-chs.readthedocs.io/zh_CN/latest/
根据文档的说明安装然后进行配置即可
# settings.py
CACHES = {
"default": {
"BACKEND": "django_redis.cache.RedisCache",
# 有密码的话就在127前面加上密码 具体看redis教程(我没有哈哈哈哈)
"LOCATION": "redis://127.0.0.1:6379",
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
}
}
}
redis会根据不同的查询条件建立不同的key存储
这样,相同的查询条件会得到相同的key值,从而取出相同的缓存值。
throttle设置访问速度
这是rest_framework自带的
地址:https://www.django-rest-framework.org/api-guide/throttling/#throttling
用来防止爬虫频繁爬取网站造成服务器压力
使用方法:
# settings.py
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
# 'PAGE_SIZE': 10
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.BasicAuthentication',
'rest_framework.authentication.SessionAuthentication',
# 'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
# 'rest_framework.authentication.TokenAuthentication',
),
# 这里这里------限速
'DEFAULT_THROTTLE_CLASSES': (
# 匿名用户的限速(IP)
'rest_framework.throttling.AnonRateThrottle',
# 已登录的用户的限速(token)
'rest_framework.throttling.UserRateThrottle'
),
# 限速条件(具体可看文档 )
'DEFAULT_THROTTLE_RATES': {
'anon': '100/day',
'user': '1000/day'
}
}
views.py中:
# goods/views.py/class GoodsListViewset
from rest_framework.throttling import UserRateThrottle, AnonRateThrottle
class GoodsListViewset
throttle_classes = (UserRateThrottle, AnonRateThrottle)
这样就可以了。