用户个人中心
retrieve 方式添加
用户中心的数据来源是对单一用户的详细数据请求, 因此需要在原有基础上加上对 retrieve 的处理
mixins.RetrieveModelMixin
用户 id 传递
同时因为对单一用户的请求需要指明用户id, 有两种方式可以传递
第一种 直接在数据里面提供当前用户 id
第二种 重写 get_object 获取当前用户
# 因为要涉及到 个人中心的操作需要传递过去 用户的 id, 重写 get_object 来实现 def get_object(self): return self.request.user
权限分离
用户中心必须指定当前用户只能访问自己, 因此需要对是否登录进行验证
但是当前视图的其他类型请求比如 create 的注册则不需要进行验证, 因此 permission_classes 无法满足需求
源码剖析
在继承了 ViewSetMixin 之后内部的 initialize_request 方面里面的 提供了 .action 在 request 中可以对请求类型进行分离
同时 APIView 内部的 get_permissions 方法负责提取认证类型, 因此重写此方法即可完成
此为 源码, 可见是直接使用一个列表表达式来获取当前视图的 permission_classes 里面的所有认证方式
实现重写
基于我们自己的需求进行重写, 利用 action 进行分流
注意其他未设置的最后一定要返回空
# permission_classes = (permissions.IsAuthenticated, ) # 因为根据类型的不同权限的认证也不同, 不能再统一设置了 def get_permissions(self): if self.action == "retrieve": return [permissions.IsAuthenticated()] elif self.action == "create": return [] return []
序列化组件分离
创建组件
之前设置的序列化组件是为了注册用的, 只采集了注册相关的字段, 无法满足用户中心的其他字段处理
因此需要重新设置一个用户详情的 序列化组件
# 用户详情信息序列化类 class UserDetailSerializer(serializers.ModelSerializer): class Meta: model = User fields = ("name", "gender", "birthday", "email", "mobile")
源码剖析
同样是基于对 action 的方法进行分流, 对于 action 的位置在 权限分流的部分有图,
在 GenericAPIView 中存在 get_serializer_class 方法, 用于获取当前视图中的 序列化组件
实现重写
基于 action 进行分流, 然后进行对 get_serializer_class 进行重写
实现方式类似于 权限的分流
def get_serializer_class(self): if self.action == "retrieve": return UserDetailSerializer elif self.action == "create": return UserRegSerializer return UserDetailSerializer
个人收藏
整体逻辑类似于 个人中心,
收藏 ----> 注册
收藏详情 -----> 用户信息
序列化组件
收藏详情需要用到收藏的商品全部内容, 序列化的时候需要进行组件的嵌套, 将商品序列化组件嵌进去
# 收藏详情 class UserFavDetailSerializer(serializers.ModelSerializer): goods = GoodsSerializer(many=True) class Meta: model = UserFav fields = ("goods", "id")
收藏的时候需要注意设置一个联合唯一索引, 在序列化中设置后或者 models 中设置皆可
# 用户收藏 class UserFavSerializer(serializers.ModelSerializer): user = serializers.HiddenField( default=serializers.CurrentUserDefault() ) class Meta: model = UserFav # 联合唯一可以在 model 中创建的时候进行操作, 通过 ModelSerializer 自然会帮你完成验证 # 也可以在这里完成, 注意是在 Meta 中进行设置, 因为这是多字段的处理 validators = [ UniqueTogetherValidator( queryset=UserFav.objects.all(), fields=('user', 'goods'), message="已经收藏过了" ) ] fields = ("user", "goods", "id") # 删除的需要因此加上 id, 这样方便删除操作
视图
整体逻辑类似于个人中心
依旧是 分流处理序列化组件, 因为收藏功能的全部请求都需要在用户登录下查看
因此不需认证分流
# 用户收藏功能 class UserFavViewset(mixins.CreateModelMixin, mixins.ListModelMixin, mixins.RetrieveModelMixin, mixins.DestroyModelMixin, viewsets.GenericViewSet): """ list: 获取用户收藏列表 retrieve: 判断某个商品是否已经收藏 create: 收藏商品 destroy: 取消商品收藏 """ # queryset = UserFav.objects.all() # 只能看自己的收藏记录 permission_classes = (IsAuthenticated, IsOwnerOrReadOnly) serializer_class = UserFavSerializer authentication_classes = (JSONWebTokenAuthentication, SessionAuthentication) lookup_field = "goods_id" # 分流处理 序列化组件 def get_serializer_class(self): if self.action == "list": return UserFavDetailSerializer elif self.action == "create": return UserFavSerializer return UserFavSerializer def get_queryset(self): return UserFav.objects.filter(user=self.request.user)
用户留言
基本上所用的字段什么的在上面都有用过了
序列化组件
需要注意的是留言时间的格式, 以及只读属性
注意 user 字段的传入应该是默认的当前用户, 且此字段可以设置成隐藏
# 用户留言 class LeavingMessageSerializer(serializers.ModelSerializer): # 设置隐藏字段 user = serializers.HiddenField( # 默认值为当前用户 default=serializers.CurrentUserDefault() ) # 留言的时间不能自己指定, 应该是系统自动根据当前的时间, 因此设置为只读 add_time = serializers.DateTimeField(read_only=True, format='%Y-%m-%d %H:%M') class Meta: model = UserLeavingMessage fields = ("user", "message_type", "subject", "message", "file", "id", "add_time")
视图
# 用户留言 class LeavingMessageViewset(mixins.ListModelMixin, mixins.DestroyModelMixin, mixins.CreateModelMixin, viewsets.GenericViewSet): """ list: 获取用户留言 create: 添加留言 delete: 删除留言功能 """ permission_classes = (IsAuthenticated, IsOwnerOrReadOnly) authentication_classes = (JSONWebTokenAuthentication, SessionAuthentication) serializer_class = LeavingMessageSerializer def get_queryset(self): return UserLeavingMessage.objects.filter(user=self.request.user)
用户收货地址
基本上和留言一样了.
序列化组件
# 收货地址 class AddressSerializer(serializers.ModelSerializer): user = serializers.HiddenField( default=serializers.CurrentUserDefault() ) add_time = serializers.DateTimeField(read_only=True, format='%Y-%m-%d %H:%M') class Meta: model = UserAddress fields = ("id", "user", "province", "city", "district", "address", "signer_name", "add_time", "signer_mobile")
视图
# 收货地址 class AddressViewset(viewsets.ModelViewSet): """ 收货地址管理 list: 获取收货地址 create: 添加收货地址 update: 更新收货地址 delete: 删除收货地址 """ permission_classes = (IsAuthenticated, IsOwnerOrReadOnly) authentication_classes = (JSONWebTokenAuthentication, SessionAuthentication) serializer_class = AddressSerializer def get_queryset(self): return UserAddress.objects.filter(user=self.request.user)