Django REST framework and creating two table entri

2019-03-03 22:16发布

问题:

I want to create entries in two tables (Log and Post) using the DRF Browseable API POST form.

The example below is contrived, but it outlines what I am trying to do.

class Post(models.Model):
    info = models.CharField()

class Log(TimeStampedModel):
    ip = models.GenericIPAddressField(('IP Address'))
    name = models.CharField()
    data = models.ForeignKey(Post)                                       

I want to use the browseable API to submit a form to create a Log entry. Here are the serializers:

class PostSerializer(serializers.ModelSerializer):
    class Meta:
        model = Post
        fields = ('info',)

class LogSerializer(serializers.ModelSerializer):                          
    data = serializers.Field()

    class Meta:
        model = Log
        fields = ('ip', 'name', 'data')

The problem with the above is that serializer.Field is read only so does not show up on the POST form. If I change it to CharField it shows up, but then I get an error because an instance of a Post is expected not just a field of the Post object.

Here are my views:

class LogMixin(object):
    queryset = Log.objects.all()                                           
    serializer_class = LogSerializer



class LogList(LogMixin, ListCreateAPIView):
    pass


class LogDetail(LogMixin, RetrieveUpdateDestroyAPIView):
    pass

What's the correct way of doing this?

回答1:

From what I can tell you want to create a nested Log object. There are 2 ways of doing this:

  1. Send 2 POST Requests, One to create the Post, and the other to create the Log contained the received HTTP 200 data from the API.
  2. (Django and best way) Send the data all in one POST and parse it server side. Django Rest Framework takes care of this for you.

I have changed your code so that it should work. Source

class LogSerializer(serializers.ModelSerializer):                          
   class Meta:
        model = Log
        fields = ('ip', 'name')


class PostSerializer(serializers.ModelSerializer):
    log = LogSerializer()
    class Meta:
        model = Post
        fields = ('info', 'log')

views.py

import generics

class PostCreateAPIView(generics.CreateAPIView):
    model = Post
    serializer_class = PostSerializer

Then you can send a POST Request containing 'info', 'ip', and 'name'.