我正在尝试在ModelViewSet的super().create()
方法中获取由create()
创建的模型的副本。最简单的方法是什么?
我有一个ModelViewSet,它接受通用的POST
请求,我知道这很好,因为我最终在数据库中有了一条新记录。我要做的是获取刚刚创建的对象,以便将其pk
返回给客户端。但是,以下操作无效:
class ItemViewSet(viewsets.ModelViewSet):
model = Item
# ...
def create(self, request, *args, **kwargs):
super().create(request, *args, **kwargs) # Successfully creates instance
instance = self.get_object() # Throws error
return Response({'status': 'success', 'pk': instance.pk})
与其他DRF ModelViewSet方法一样,我希望self.get_object()
能为我创建实例,尽管通常只能在“详细途径”中使用。我得到的是以下错误:
AssertionError: Expected view CultivarStockViewSet to be called with a URL keyword argument named "pk". Fix your URL conf, or set the `.lookup_field` attribute on the view correctly.
任何见识都受到赞赏!
答案 0 :(得分:2)
通过进一步的调试,我弄清楚了。为了后代的缘故,这是我工作的create()
方法:
def create(self, request, *args, **kwargs):
response = super().create(request, *args, **kwargs)
instance = response.data
return Response({'status': 'success', 'pk': instance['pk']})
答案 1 :(得分:2)
由于Django使用参数执行过滤,因此您确实无法使用get_object
[classy-doc]获取对象。实际上,get_object
实现看起来像:
def get_object(self): # ... queryset = self.filter_queryset(self.get_queryset()) # Perform the lookup filtering. lookup_url_kwarg = self.lookup_url_kwarg or self.lookup_field # ... filter_kwargs = {self.lookup_field: self.kwargs[lookup_url_kwarg]} obj = get_object_or_404(queryset, **filter_kwargs) # May raise a permission denied self.check_object_permissions(self.request, obj) return obj
这些self.kwargs
不可用,因此get_object
调用失败。
不过,我们可以修补create
[classy-doc]函数并在此处使用serializer.instance
[drf-doc]:
class ItemViewSet(viewsets.ModelViewSet):
model = Item
# ...
def create(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
self.perform_create(serializer)
return Response({'status': 'success', 'pk': serializer.instance.pk})
答案 2 :(得分:1)
我知道我很晚才回答这个问题。但是如果有人遇到这种问题,@JohnnyHammersticks 提供的答案效果很好。但问题是,此解决方案将创建对象两次(就我而言,我也有 perform_create
函数)。处理这种情况的最佳方法如下,
def create(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
self.perform_create(serializer)
if serializer.is_valid():
instance = serializer.data
pk = data['id']
return Response({'status': 'success', 'pk': instance['pk']})