当前位置: 动力学知识库 > 问答 > 编程问答 >

python - How to post to a Django REST Framework API with Related Models

问题描述:

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.

分享给朋友:
您可能感兴趣的文章:
随机阅读: