dan_boy
dan_boy

Reputation: 2009

How to create two object instances from two different models with a single POST request?

I am learning the Django-Rest Framework. I want to create an object instance for both my Story model and my File model with a single post request. So the incoming data contains a title and a file. I want then to create a story object with a title and the image field contains a reference (fk) to the id of the file instance. In the File model a own instance of File is created with the incoming file data.

# File Model
class File(models.Model):
    file = models.FileField(upload_to='audio_stories/', null=True, default='some_value')

# Story Model
class Story (models.Model):
    title = models.CharField(max_length=100,blank=True)
    image = models.ForeignKey(File,on_delete=models.CASCADE, blank=True, default=None)

# Story  Serializer
class StoryCreateUpdateSerializer (serializers.ModelSerializer):
    image = TestFileSerializer()

    class Meta:
        model = Story
        fields =  ('title','image')
        
        def create(self, validated_data):
            image = validated_data.pop('image')
            title = validated_data.pop('title')
            image_instance = File.objects.create(file=image)
            story_instance = Story.objects.create(title=title, image=image_instance)
            return story_instance

# File Serializer
class TestFileSerializer (serializers.ModelSerializer):

    class Meta:
        model = File
        fields =  ('__all__')

If I send the formdata via Postman to my server it responses with "image": ["This field is required."]. If this is an obvious mistake, I apologize in advance.

I am grateful for any clarification.

Upvotes: 1

Views: 53

Answers (1)

MadCowDisease
MadCowDisease

Reputation: 303

I suspect you have an indentation error in your StoryCreateUpdateSerializer the def create() should be at the same indentation level as class Meta:

Besides that, I compared your code to something similar I worked on recently, where in one serializer class you pop data off of the request, and call another serializer. You seem to be doing this correctly unless we're both missing something.

An example:

class BookSerializer(serializers.ModelSerializer):
    pages = PageSerializer(many=True)
    class Meta:
        model = Book
        fields = ['id', 'title', 'pages']
    
    def create(self, validated_data):
        pages_data = validated_data.pop('pages')
        book = book.objects.create(**validated_data)
        for page_data in pages_data:
            # Page has foreign key to book
            Page.objects.create(book=book, **page_data)
        return book

Upvotes: 1

Related Questions