• 07-商品详情页功能


    一、商品详情页功能

    1、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__" #将全部字段显示出来

    这样商品的详情页就完成啦。

     2、热卖商品接口实现

    数据的模型类中有is_hot这个字段,因此过滤商品的时候我们应该加上is_hot字段。前端的逻辑中,有这个is_hot的条件,因此在过滤器中加上过滤字段为:

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

     会发现数据没有热销的,因此我们需要去后台管理系统去修改几条数据展示。修改好之后,验证数据。结果出现热搜啦。

     3、用户收藏接口实现

    用户收藏,是用户操作的,因此需要到user_operation中的视图中操作:

    user_operation/views.py:

    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.pymodel---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") #数据库联合索引的认证

     完成了收藏功能,以及删除功能。

    4、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',
        ]
    }

     

     

     

     整个用户的收藏以及取消收藏功能开发完成。

  • 相关阅读:
    K-Means++ 聚类之数据可视化:使用gnuplot
    QQ设计第1-5步
    QQ设计第1-5步
    为什么有很深的windows基础还是不能动摇linux半步
    常用命令
    在线会计_金蝶友商网
    XP使用VNC远程桌面CentOS 6
    Fatal error: Call to undefined function mb_substr()
    如何汉化 po 文件及编译成 mo 文件
    idoerp
  • 原文地址:https://www.cnblogs.com/lishuntao/p/11918364.html
Copyright © 2020-2023  润新知