个人中心开发
使用DRF生成开发文档
https://www.django-rest-framework.org/topics/documenting-your-api/
提供接口获取单个用户的个人信息
复用ConsumerViewset 继承RetrieveModelMixin
class ConsumerViewset(CreateModelMixin, mixins.UpdateModelMixin, mixins.RetrieveModelMixin, viewsets.GenericViewSet):
动态获取permission
- 当用户获取数据时需要验证是否登录
这时的url 应当为 user/id,一般的做法是
# permission_classes = (permissions.IsAuthenticated, )
但是我们已经复用了ConsumerViewset类,因为该类还实现了用户注册的功能,而注册时是不需要验证是否已经登录的
所有我们需要设置动态的permission
def get_permissions(self):
if self.action == "retrieve":
return [permissions.IsAuthenticated()]
elif self.action == "create":
return []
return []
补充:或者我们将user_id返回给前端,让前端带着id来请求url user/id
- 最后加入用户认证的功能,上面的方法只是判断用户是否登录,并不会进行认证,只有认证过的用户才算登录
JSONWebTokenAuthentication 是使用JWT模式进行认证
SessionAuthentication 是使用Session模式进行认证,方便浏览器端的调试
authentication_classes = (JSONWebTokenAuthentication, authentication.SessionAuthentication )
动态获取serializer
- 当返回数据给前端时,我们不能在使用注册时的Serializer,重写一个DetailSerializer专门用来返回用户信息
class ConsumerDetailSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ("name", "birthday", "mobile", "gender", "email")
- 因为是复用的同一个View,所有判断是注册还是retrieve操作来获取不同的serializer,重写get_serializer_class方法动态指定serializer
def get_serializer_class(self):
if self.action == "retrieve":
return ConsumerDetailSerializer
elif self.action == "create":
return ConsumerRegSerializer
return ConsumerDetailSerializer
修改用户个人资料
- 继承UpdateModelMixin,它支持put 和 patch 请求
补充,小tips,get_object方法
# 当Retrieve和Update,Destroy的时候都会用到该方法
def get_object(self):
return self.request.user
完善个人收藏
因为个人收藏中要包含收藏的商品,而原来的serializer只会返回goods_id 和 id ,所有需要重写序列号类,用于返回收藏详情页的信息
- 新建serializer
class UserFavDetailSerializer(serializers.ModelSerializer):
goods = GoodsSerializer()
class Meta:
model = UserFav
field = ('goods','id')
因为goods本身就是外键,只会调用出一个对象出来,所有就会不用再设置many=True了,所有many=True,就相当于xxx_set的set,只有没有设置外键要反向引用的时候才会设置
- 这里也涉及到了动态调用Serializer class的问题,所以也需要重写get_serializer_class方法
# serializer_class = UserFavSerializer
def get_serializer_class(self):
if self.action == "list":
return UserFavDetailSerializer
elif self.action == "create":
return UserFavSerializer
return UserFavSerializer
小tips,serializers.HiddenField,隐藏了该字段,会做后端的操作,但不会序列号返回给前端
# 获取当前用户,并且隐藏了该字段,不会序列号返回给前端
user = serializers.HiddenField(
default=serializers.CurrentUserDefault()
)
用户留言功能
- views
class UserRemarkViewset(mixins.CreateModelMixin,mixins.RetrieveModelMixin,
mixins.DestroyModelMixin,mixins.ListModelMixin,viewsets.GenericViewSet):
"""
list:
获取用户留言
create:
添加留言
delete:
删除留言功能
"""
queryset = UserRemark.objects.all()
serializer_class = UserRemarkSerializer
permission_classes = (IsAuthenticated,IsOwnerOrReadOnly)
authentication_classes = (JSONWebTokenAuthentication, SessionAuthentication)
def get_queryset(self):
return UserRemark.objects.filter(user=self.request.user)
- serializers
class UserRemarkSerializer(serializers.ModelSerializer):
# 获取当前用户,并且隐藏了该字段,不会序列号返回给前端
user = serializers.HiddenField(
default=serializers.CurrentUserDefault()
)
# read_only=True 这个值只返回给前端不让前端提交
# write_only=True 这个值只会提交,不会返回给前端
# format 设置日期格式
add_time = serializers.DateTimeField(read_only=True, format='%Y-%m-%d %H:%M')
class Meta:
model = UserRemark
fields = ("user", "message_type", "subject", "message", "file", "id" ,"add_time")
注意:
read_only=True 这个值只返回给前端,不让前端提交
write_only=True 这个值只会让前端提交,不会再返回给前端
用戶收穫地址
- views
class UserAddressViewset(viewsets.ModelViewSet):
"""
收货地址管理
list:
获取收货地址
create:
添加收货地址
update:
更新收货地址
delete:
删除收货地址
"""
queryset = UserAddress.objects.all()
serializer_class = UserAdressSerializer
permission_classes = (IsAuthenticated, IsOwnerOrReadOnly)
authentication_classes = (JSONWebTokenAuthentication, SessionAuthentication)
def get_queryset(self):
return UserAddress.objects.filter(user=self.request.user)
因为这里用到了 增删改查 四个接口,所有可以直接继承Modelviewset
- serialiers
class UserAdressSerializer(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")