Django Rest Framework中@detail_route报错:对象无caption属性求助
解决DRF @detail_route中的属性错误问题
嘿,我一眼就瞅出问题所在了——你创建Photo对象时用了self.caption、self.image这些写法,但self指的是你的视图类实例啊,它根本没有这些属性!这些值本该从请求的POST数据里取,不是直接从视图实例里捞。
错误原因拆解
你写的caption=self.caption,相当于在找UploadAvatarPhotoAPIView这个类有没有caption属性,显然没有,所以才会抛出'UploadAvatarPhotoAPIView' object has no attribute 'caption'的错误。正确的姿势是用DRF的序列化器来处理请求数据,既安全又符合框架的最佳实践。
修改后的代码
class PhotoUpdateSerializer(ModelSerializer): class Meta: model = Photo fields = ['image', 'is_public', 'caption'] class UploadAvatarPhotoAPIView(ModelViewSet): # 换成ModelViewSet更合理,因为需要写操作 serializer_class = PhotoUpdateSerializer queryset = Photo.objects.all() @detail_route(methods=['POST']) def upload_avatar(self, request, username): # 用序列化器验证请求数据,自动处理字段规则 serializer = PhotoUpdateSerializer(data=request.data, context={'request': request}) serializer.is_valid(raise_exception=True) # 保存对象时传入当前用户(因为你的Photo模型应该有user外键,且序列化器里没包含这个字段) avatar_photo = serializer.save(user=request.user) return Response(serializer.data)
几个关键改进点
- 用序列化器处理数据:不再手动提取字段,序列化器会帮你验证数据格式(比如
image是否是合法文件、is_public是否为布尔值),避免手动处理的低级错误。 - 替换ReadOnlyModelViewSet:
ReadOnlyModelViewSet只提供只读的GET方法,你需要POST操作,换成ModelViewSet更贴合需求(如果确实不需要其他写操作,也可以保留,但ModelViewSet更通用)。 - Serializer.save()传参:因为
user字段不在你的序列化器fields里,所以需要在保存时手动传入当前登录用户request.user。
额外提示(针对DRF新版本)
如果你用的是DRF 3.10及以上版本,官方已经弃用了@detail_route,推荐使用@action装饰器,用法几乎一致:
from rest_framework.decorators import action @action(detail=True, methods=['POST']) def upload_avatar(self, request, username): # 逻辑和上面完全一致 ...
内容的提问来源于stack exchange,提问作者KitKit
相关产品推荐
相关产品推荐

