如何发布到具有相关型号的Django REST框架API [英] How to post to a Django REST Framework API with Related Models
问题描述
我有两个相关模型(活动+地点),其中包含如下所示的序列号:
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屋!