如何发布到具有相关型号的Django REST框架API [英] How to post to a Django REST Framework API with Related Models

查看:116
本文介绍了如何发布到具有相关型号的Django REST框架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,所以我可以从位置模型,而不是单个 id ,但是,我不能发布位置信息的事件,我只能执行一个标题属性的帖子如果我删除了序列化程序中的深度选项,我可以使用标题和位置ID执行该职位。



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



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



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

  $ scope.doClick = function(event){

var test_data = {
title:'Event Test',
content:'Some test content here',
位置:2,
日期:'2014-12-16T11:00:00Z'
}

// $ resource.save()不工作?
$ 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中处理它们。





在Django REST框架3.0,您可以尝试以下操作来获取所需内容:

  class LocationsSerializer(serializers.ModelSerializer):

class Meta:
model =位置
fields =('title','address',)

class EventsSerializer(serializers.ModelSerializer):
位置= LocationsSerializer(read_only = True)

class Meta:
model = Events
fields =('locations',)

class EventViewSet viewets.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管理员将合理地显示它们,您的同伴开发人员将能够轻松了解如何建立关系。


I have two related models (Events + Locations) with a serialzer shown below:

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

I set the depth to 1 in the serializer so I can get the information from the Locations model instead of a single id. When doing this however, I cant post to events with the location info. I can only perform a post with the title attribute. If I remove the depth option in the serializer, I can perform the post with both the title and location id.

I tried to create a second serializer (EventsSerialzerB) without the depth field with the intention of using the first one as a read-only response, however when I created a second serializer, viewset, and added it to the router, it would automatically override the original viewset.

Is it possible for me to create a serializer that outputs the related model fields, and allows you to post directly to the single model?

// EDIT - Here's what I'm trying to post

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

So when the serializers are flat, I can post all of these fields. The location field is the id of a location from the related Locations table. When they are nested, I can't include the location field in the test data.

解决方案

By setting the depth option on the serializer, you are telling it to make any relation nested instead of flat. For the most part, nested serializers should be considered read-only by default, as they are buggy in Django REST Framework 2.4 and there are better ways to handle them in 3.0.

It sounds like you want a nested representation when reading, but a flat representation when writing. While this isn't recommended, as it means GET requests don't match PUT requests, it is possible to do this in a way to makes everyone happy.

In Django REST Framework 3.0, you can try the following to get what you want:

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'])

A new LocationsSerializer was created, which will handle the read-only nested representation of the Locations object. By overriding perform_create and perform_update, we can pass in the location id that was passed in with the request body, so the location can still be updated.

Also, you should avoid having model names being plurals. It's confusing when Events.locations is a single location, even though Locations.events is a list of events for the location. Event.location and Location.events reads a bit more clearly, the Django admin will display them reasonably, and your fellow developers will be able to easily understand how the relations are set up.

这篇关于如何发布到具有相关型号的Django REST框架API的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆