DRF实战---实现商品详情页

商品详情页

1.GoodsListView中继承RetrieveModelMixin

class GoodsListViewSet(mixins.ListModelMixin,mixins.RetrieveModelMixin,viewsets.GenericViewSet):

2.serializer中加入外键,获取轮播图

class GoodsImageSerializer(serializers.ModelSerializer):
    class Meta:
        model = GoodsImage
        fields = ('image', )  # 包含所有字段

class GoodsSerializer(serializers.ModelSerializer):
    category = GoodCategorySerializer()
    # images为GoodImage中外键的relate_name,用于反向查询
    images = GoodsImageSerializer(many=True) # 反向查询,一对多

展示热卖商品

  • filter中加入ishot字段

用户收藏

  • 用户操作views
class UserFavViewSet(mixins.CreateModelMixin,mixins.DestroyModelMixin,
    mixins.ListModelMixin,mixins.RetrieveModelMixin,viewsets.GenericViewSet):
    """
    list:
        获取用户收藏列表
    retrieve:
        判断某个商品是否已经收藏
    create:
        收藏商品
    """
    # ListModelMixin 展示所有查到的数据,以列表形式返回
    # RetrieveModelMixin 用来 userfav/2/ 时,可以查询到单个详情,实现当个实例的GET方法
    # queryset = UserFav.objects.all()
    # serializer_class = UserFavSerializer
    def get_serializer_class(self):
        if self.action == "list":
            return UserFavDetailSerializer
        elif self.action == "create":
            return UserFavSerializer

        return UserFavSerializer

    # def perform_create(self, serializer):
    #     instance = serializer.save()
    #     goods = instance.goods
    #     goods.fav_num += 1
    #     goods.save()

    # 设置JSONWebTokenAuthentication为局部,让用户访问Goods列表时不做登录限制
    # 设置SessionAuthentication,让已登录用户访问收藏列表时不会提示用户认证未提供,方便开发时的调试(因为调试时,往往不会讲token放到header中),
    # 这个类的设置主要是为了使用token或者session验证方式获取用户信息,然后交给permission验证
    authentication_classes = (JSONWebTokenAuthentication, SessionAuthentication)
    lookup_field = "goods_id"  # 因为goods是外键,所有加下划线

    # 重写get_queryset,只返回当前用户的收藏信息
    def get_queryset(self):
        return UserFav.objects.filter(user=self.request.user)

用户删除

http://127.0.0.1:8000/userfavs/1/ Method:Delete

设置联合唯一

models中

    unique_together={('user', 'goods')},
如果数据库报错django.db.utils.IntegrityError: (1062, “Duplicate entry ‘6-1’ for key ‘user_operation_userfav_user_id_goods_id_2dbadda7_uniq’”)

表中已经存在重复的记录了,删除重复记录,重新migrate

serializers中

    class Meta:
        model = UserFav
        validators = [
            UniqueTogetherValidator(
                queryset=UserFav.objects.all(),
                fields=('user', 'goods'),
                message="已经收藏"
            )
        ]
        # 返回id,便于后续删除跟新操作
        fields = ('user','goods','id')

权限认证

判断用户是否登登录

让用户只能对自己的收藏列表进行操作

  • 创建permissions.py
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`.
        # obj就是数据库中查出来的那个对象
        return obj.user == request.user

设置authentication_classes类

设置JSONWebTokenAuthentication为局部,让用户访问Goods列表时不做登录限制

设置SessionAuthentication,让已登录用户访问收藏列表时不会提示用户认证未提供,方便开发时的调试(因为调试时,往往不会讲token放到header中),

这个类的设置主要是为了使用token或者session验证方式获取用户信息,然后交给permission验证

  • views中配置
class UserFavViewSet(mixins.CreateModelMixin,mixins.DestroyModelMixin,
    mixins.ListModelMixin,mixins.RetrieveModelMixin,viewsets.GenericViewSet):
    """
    list:
        获取用户收藏列表
    retrieve:
        判断某个商品是否已经收藏
    create:
        收藏商品
    """
    # ListModelMixin 展示所有查到的数据,以列表形式返回
    # RetrieveModelMixin 用来 userfav/2/ 时,可以查询到单个详情,实现当个实例的GET方法
    queryset = UserFav.objects.all()
    serializer_class = UserFavSerializer

    # IsAuthenticated 判断是否登录 IsOwnerOrReadOnly 让用户只能对自己的收藏列表进行操作
    permission_classes = (IsAuthenticated,IsOwnerOrReadOnly)
    # 设置JSONWebTokenAuthentication为局部,让用户访问Goods列表时不做登录限制
    # 设置SessionAuthentication,让已登录用户访问收藏列表时不会提示用户认证未提供,
    # 猜测,是用来保存token的,表示这个类已经验证过token了
    # 当请求的消息头没有带上token时就会返回"detail": "Authentication credentials were not provided."
    # 如果带了,就会直接返回结果
    authentication_classes = (JSONWebTokenAuthentication, SessionAuthentication)
    lookup_field = "goods_id"  # 因为goods是外键,所有加下划线

    # 重写get_queryset,只返回当前用户的收藏信息
    def get_queryset(self):
        return UserFav.objects.filter(user=self.request.user)

views中设置lookup_field,通过商品id查询,而不是用户收藏记录表中的ID

lookup_field = “goods_id” # 因为goods是外键,所有加下划线

lookup_field是在get_queryset进行筛选之后执行的,因此不用担心查到其他不属于当前用户的good

查询或删除的url

http://127.0.0.1:8000/userfavs/16/ 16为goods_id

你可能感兴趣的:(Django,Rest,Framework)