如何使用相关模型发布到Django REST Framework API

我有两个相关的模型(事件位置),如下所示:

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

我在序列化器中将深度设置为1,这样我就可以从Locations模型中获取信息而不是单个id.但是,当我这样做时,我无法发布带有位置信息的事件.我只能使用title属性执行帖子.如果我删除了序列化程序中的深度选项,我可以使用标题和位置ID执行帖子.

我尝试创建没有深度字段的第二个序列化器(EventsSerialzerB),意图使用第一个作为只读响应,但是当我创建第二个序列化器,视图集并将其添加到路由器时,它会自动覆盖原始视图集.

我是否可以创建一个输出相关模型字段的序列化程序,并允许您直接发布到单个模型?

//编辑 – 这是我要发布的内容

$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);
        });
}

因此,当序列化器是扁平的时,我可以发布所有这些字段.位置字段是相关位置表中位置的ID.当它们嵌套时,我不能在测试数据中包含位置字段.

最佳答案 通过在序列化程序上设置深度选项,您可以告诉它使嵌套而不是平面的任何关系.在大多数情况下,默认情况下嵌套序列化程序应该被认为是只读的,因为它们在Django REST Framework 2.4中是错误的,并且有更好的方法在3.0中处理它们.

听起来你想要在阅读时使用嵌套表示,但在写作时需要平面表示.虽然不推荐这样做,因为这意味着GET请求与PUT请求不匹配,但可以通过让每个人都满意的方式来实现.

在Django REST Framework 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管理员会合理地显示它们,而你的开发人员将能够轻松地理解关系的设置方式.

点赞