如何通过Django REST Framework API发布带有关联模型的内容
如何通过Django REST Framework API发布带有关联模型的内容
我有两个相关的模型(Events + Locations),并且有一个如下所示的序列化器:\n
class Locations title = models.CharField(max_length=250) address = model.CharField(max_length=250) class Events title = models.CharField(max_length=250) locations = models.ForeignKey(Locations, related_name='events' class EventsSerializer(serializers.ModelSerializer): class Meta: model = Events depth = 1
\n我在序列化器中将深度设置为1,这样我可以从Locations模型中获取信息,而不仅仅是一个单独的id。然而,当这样做时,我不能使用位置信息进行post到事件。我只能使用标题属性进行post。如果我在序列化器中删除深度选项,我可以同时使用标题和位置id进行post。\n我尝试创建一个没有深度字段的第二个序列化器(EventsSerialzerB),目的是将第一个序列化器用作只读响应,但是当我创建第二个序列化器,视图集,并将其添加到路由器时,它会自动覆盖原始视图集。\n我是否可以创建一个序列化器,输出相关模型字段,并允许直接对单个模型进行post? \n// 编辑 - 这是我尝试进行post的内容\n
$scope.doClick = function (event) { var test_data = { title: 'Event Test', content: 'Some test content here', location: 2, date: '2014-12-16T11:00:00Z' } // $resource.save() doesn't work? $http.post('/api/events/', test_data). success(function(data, status, headers, config) { console.log('sucess', status); }). error(function(data, status, headers, config) { console.log('error', status); }); }
\n当序列化器是平的时候,我可以post所有这些字段。位置字段是相关的Locations表中的位置id。当它们是嵌套的时候,我不能在测试数据中包含位置字段。
如何在Django REST Framework API中使用相关模型发布内容
问题出现的原因:
在序列化器上设置depth
选项时,您告诉它将任何关系嵌套而不是平坦化。在大多数情况下,默认情况下应将嵌套序列化器视为只读,因为在Django REST Framework 2.4中它们存在错误,并且在3.0中有更好的处理方式。
解决方法:
为了在读取时获得嵌套表示,在写入时获得平坦表示,可以尝试以下解决方法:
class LocationsSerializer(serializers.ModelSerializer): class Meta: model = Locations fields = ('title', 'address', ) class EventsSerializer(serializers.ModelSerializer): locations = LocationsSerializer(read_only=True) class Meta: model = Events fields = ('locations', ) class EventViewSet(viewsets.ModelViewSet): queryet = Event.objects.all() serializer_class = EventsSerializer def perform_create(self, serializer): serializer.save(locations=self.request.data['locations']) def perform_update(self, serializer): serializer.save(locations=self.request.data['locations'])
解决方法解析:
上述代码中,创建了一个新的LocationsSerializer
,它将处理Locations
对象的只读嵌套表示。通过重写perform_create
和perform_update
方法,我们可以传入与请求主体中传入的位置id对应的位置,以便仍然可以更新位置。
另外,应避免使用复数形式的模型名称。当Events.locations
是单个位置时,这会引起混淆,尽管Locations.events
是位置的事件列表。Event.location
和Location.events
读起来更清晰,Django admin将合理显示它们,并且其他开发人员可以轻松理解关系的设置方式。
然而,这种解决方法仍然无法通过给出位置的id来发布新的事件项。我只能输入事件的信息。传统上,在处理这样的相关模型时,我应该保持两个序列化器分开和平坦,然后使用JS在前端执行连接操作吗?还是应该有一套只读嵌套数据的序列化器,然后另外一套用于发布数据的平坦序列化器?