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中使用