一、viewsets實現商品詳情頁接口前端
商品詳情頁,須要加上mixins.RetrieveModelMixin,由於路由爲/goods/id/,所以在以前商品列表頁視圖中繼承詳情頁類。代碼邏輯爲:數據庫
class GoodsListViewSet(mixins.ListModelMixin,mixins.RetrieveModelMixin,viewsets.GenericViewSet): """ 商品列表頁 分頁 搜索 過濾 排序 """ queryset = Goods.objects.all() serializer_class = GoodsSerializer pagination_class = GoodsSetPagination filter_backends = [DjangoFilterBackend,filters.SearchFilter,filters.OrderingFilter] #這是精確搜索過濾,咱們須要的是模糊搜索 # filterset_fields = ['name', 'shop_price'] filter_class = GoodsFilter search_fields = ("name","goods_brief","goods_desc") ordering_fields = ("shop_price","sold_num","add_time")
goods/serializers.py中的邏輯爲:
from rest_framework import serializers from .models import Goods,GoodsCategory,GoodsImage class GoodsImageSerializer(serializers.ModelSerializer): class Meta: model = GoodsImage fields = ("image",) class GoodsSerializer(serializers.ModelSerializer): """ 在這裏能夠利用新寫的字段來覆蓋已有字段 """ category = GoodsCategorySerializer() #在這裏實例化外鍵的序列化器,就能夠完成 images = GoodsImageSerializer(many=True) #名字必定要和related_name="images"中的名字同樣 class Meta: model = Goods #指明model #fields = ['category', 'goods_sn', 'name', 'click_num','sold_num','fav_num','add_time'] #指明字段 fields = "__all__" #將所有字段顯示出來
這樣商品的詳情頁就完成啦。django
二、熱賣商品接口實現spa
數據的模型類中有is_hot這個字段,所以過濾商品的時候咱們應該加上is_hot字段。前端的邏輯中,有這個is_hot的條件,所以在過濾器中加上過濾字段爲:3d
import django_filters from django.db.models import Q from .models import Goods class GoodsFilter(django_filters.rest_framework.FilterSet): """ 商品過濾器 """ pricemin = django_filters.NumberFilter(field_name="shop_price",lookup_expr="gte") pricemax = django_filters.NumberFilter(field_name="shop_price", lookup_expr="lte") name = django_filters.CharFilter(field_name="name", lookup_expr="icontains") #這裏過濾的字段要和前端傳過來的字段同樣 top_category = django_filters.NumberFilter(method="top_category_filter") def top_category_filter(self,queryset,name,value): return queryset.filter(Q(category_id=value)|Q(category__parent_category_id=value)|Q(category__parent_category__parent_category_id=value)) class Meta: model = Goods fields = ["pricemin","pricemax","name","top_category","is_hot"]
會發現數據沒有熱銷的,所以咱們須要去後臺管理系統去修改幾條數據展現。修改好以後,驗證數據。結果出現熱搜啦。rest
三、用戶收藏接口實現code
用戶收藏,是用戶操做的,所以須要到user_operation中的視圖中操做:jwt
user_operation/views.py:blog
from django.shortcuts import render from rest_framework import viewsets from rest_framework import mixins from .models import UserFav from .serializers import UserFavSerializer # Create your views here. #添加一條記錄, 獲取收藏商品列表的功能 刪除一條記錄 所以繼承 class UserFavViewset(mixins.CreateModelMixin,mixins.ListModelMixin,mixins.DestroyModelMixin,viewsets.GenericViewSet): """ 用戶收藏功能 """ queryset = UserFav.objects.all() serializer_class = UserFavSerializer
user_operaton/serializers.py:排序
from rest_framework import serializers from rest_framework.validators import UniqueTogetherValidator from .models import UserFav class UserFavSerializer(serializers.ModelSerializer): """ 用戶會收藏同一商品屢次,所以這是不合理的 因此利用Django的model來實現這一合理操做(也能夠下面本身配置) """ user = serializers.HiddenField( default=serializers.CurrentUserDefault() ) class Meta: model = UserFav validators = [ UniqueTogetherValidator( queryset=UserFav.objects.all(), fields=['user', 'goods'], message="已經收藏" ) ] fields = ("user","goods","id")
在user_operation/models.py的model---UserFav中的元類中定義聯合索引去重:
class UserFav(models.Model): """ 用戶收藏 """ user = models.ForeignKey(User, verbose_name="用戶",on_delete=models.CASCADE) goods = models.ForeignKey(Goods, verbose_name="商品", help_text="商品id",on_delete=models.CASCADE) add_time = models.DateTimeField(default=datetime.now, verbose_name=u"添加時間") class Meta: verbose_name = '用戶收藏' verbose_name_plural = verbose_name unique_together = ("user", "goods") #數據庫聯合索引的認證
完成了收藏功能,以及刪除功能。
四、DRF的權限驗證
由於上面的操做有必定的問題,任何一我的均可以刪除數據庫中的收藏,所以DRF官方文檔中提供了權限認證
user_operation/views.py
from django.shortcuts import render from rest_framework import viewsets from rest_framework import mixins from rest_framework.permissions import IsAuthenticated from rest_framework_jwt.authentication import JSONWebTokenAuthentication from rest_framework.authentication import SessionAuthentication from utils.permissions import IsOwnerOrReadOnly from .models import UserFav from .serializers import UserFavSerializer # Create your views here. #添加一條記錄, 獲取收藏商品列表的功能 刪除一條記錄 所以繼承 class UserFavViewset(mixins.CreateModelMixin,mixins.ListModelMixin,mixins.DestroyModelMixin,viewsets.GenericViewSet): """ 用戶收藏功能 """ # queryset = UserFav.objects.all() #配置以後,必須登陸才能獲取相關操做 permission_classes = (IsAuthenticated,IsOwnerOrReadOnly)
#由於項目是JWT認證,所以將認證放到具體的認證中,而不是全局設置中 authentication_classes = (JSONWebTokenAuthentication,SessionAuthentication) serializer_class = UserFavSerializer
lookup_field = "goods_id" #直接能夠看商品id查詢收藏的,就不用來找收藏的id啦
#咱們只能獲取當前用戶的UserFav,所以咱們要重載get_queryset方法
def get_queryset(self):
return UserFav.objects.filter(user=self.request.user)
utils/permissions.py:(DRF官網permissions提供的權限驗證)
from rest_framework import permissions class IsOwnerOrReadOnly(permissions.BasePermission): """ Object-level permission to only allow owners of an object to edit it. Assumes the model instance has an `owner` attribute. """ def has_object_permission(self, request, view, obj): # Read permissions are allowed to any request, # so we'll always allow GET, HEAD or OPTIONS requests. if request.method in permissions.SAFE_METHODS: return True # Instance must have an attribute named `owner`. return obj.user == request.user
MxShop/settings.py:
#配置用戶認證,將JSONWebTokenAuthentication拿到具體用戶操做認證,否則常規的商品列表頁都不能訪問 REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': [ # 'rest_framework_jwt.authentication.JSONWebTokenAuthentication', 'rest_framework.authentication.BasicAuthentication', 'rest_framework.authentication.SessionAuthentication', 'rest_framework.authentication.TokenAuthentication', ] }
整個用戶的收藏以及取消收藏功能開發完成。