如何通过Django REST Framework API发布带有关联模型的内容

9 浏览
0 Comments

如何通过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。当它们是嵌套的时候,我不能在测试数据中包含位置字段。

0
0 Comments

如何在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_createperform_update方法,我们可以传入与请求主体中传入的位置id对应的位置,以便仍然可以更新位置。

另外,应避免使用复数形式的模型名称。当Events.locations是单个位置时,这会引起混淆,尽管Locations.events是位置的事件列表。Event.locationLocation.events读起来更清晰,Django admin将合理显示它们,并且其他开发人员可以轻松理解关系的设置方式。

然而,这种解决方法仍然无法通过给出位置的id来发布新的事件项。我只能输入事件的信息。传统上,在处理这样的相关模型时,我应该保持两个序列化器分开和平坦,然后使用JS在前端执行连接操作吗?还是应该有一套只读嵌套数据的序列化器,然后另外一套用于发布数据的平坦序列化器?

0