DRF中CreateAPIView重写perform_create传参watchlist的疑问
DRF中ReviewCreate视图的运行逻辑解惑
问题描述
用户提供的视图代码:
class ReviewCreate(generics.CreateAPIView): # queryset=Review.objects.all() serializer_class=ReviewSerializer def perform_create(self, serializer): pk=self.kwargs.get('pk') # print(pk) watchlist=WatchList.objects.get(pk=pk) serializer.save(watchlist=watchlist) print("1")
同时查看了DRF CreateModelMixin的源码:
class CreateModelMixin: """ Create a model instance. """ def create(self, request, *args, **kwargs): serializer = self.get_serializer(data=request.data) serializer.is_valid(raise_exception=True) self.perform_create(serializer) headers = self.get_success_headers(serializer.data) return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers) def perform_create(self, serializer): serializer.save() def get_success_headers(self, data): try: return {'Location': str(data[api_settings.URL_FIELD_NAME])} except (TypeError, KeyError): return {}
用户有三个核心疑问:
- 为何要在
serializer.save(watchlist=watchlist)中传入watchlist=watchlist? - 父类
perform_create已调用serializer.save(),为何自定义的perform_create还要再次调用并传参? - Review模型还有其他字段,仅传watchlist为何能创建数据?
解答
1. 传入watchlist=watchlist的原因
Review模型和WatchList模型应该是外键关联的(比如Review有一个watchlist外键字段指向WatchList)。这个字段的值不能从前端提交的request.data里获取——它是通过URL中的pk参数确定对应WatchList实例的,不属于用户输入的数据。
DRF序列化器调用save()时,会把传入的额外关键字参数直接赋值给模型实例的对应字段。这样就能自动给新创建的Review绑定指定的WatchList,既避免了用户手动提交外键可能带来的错误,也简化了前端的请求逻辑。
2. 重写perform_create后仍需调用serializer.save()的原因
父类的perform_create只是一个默认实现,当你重写这个方法时,父类的默认逻辑会被完全覆盖,不会再执行。所以必须在自定义的perform_create里手动调用serializer.save(),同时补充上请求体里没有的参数——这不是重复调用,而是替换了父类的默认调用行为。
3. 仅传watchlist就能创建数据的原因
并非只传了watchlist,实际是两种数据来源合并后创建的实例:
- 序列化器已经通过
self.get_serializer(data=request.data)加载了前端提交的其他字段数据,只要这些字段通过了序列化器的验证,就会被用来创建实例。 Review模型的其他字段要么是允许为空(null=True/blank=True),要么有默认值,即使前端没提交也能满足模型的创建要求。
内容的提问来源于stack exchange,提问作者Rishi Goyal
相关产品推荐
相关产品推荐

