1

I would like to have a model for which you can upload multiple images on create(post).

In DRF web view on api/animals/ in the post form I would like to add multiple images and create the new Animal with the images attached.

Let us assume I have the following models:

class Animal(models.Model):
    slug = models.CharField(max_length=20, unique=True)


class AnimalImage(models.Model):
    animal = models.ForeignKey(Animal, on_delete=models.CASCADE)
    image = models.ImageField(upload_to='animal_pics/')

The I have the following serializers:

class AnimalImageSerializer(serializers.ModelSerializer):
    class Meta:
        model = AnimalImage
        fields = ('animal', 'image', )


class AnimalSerializer(serializers.HyperlinkedModelSerializer):
     images = AnimalImageSerializer(many=True)
     class Meta:
         model = Animal
         lookup_field = 'slug'
         extra_kwargs = {
             {'url': {'lookup_field': 'slug'}
         }
         fields = ('slug', 'images', )

The I have the following rest views:

 class AnimalViewSet(viewsets.ModelViewSet):
     queryset = Animal.objects.all()
     serializer_class = AnimalSerializer
     lookup_filed = 'slug'
     parser_classes = (JSONParser, MultiPartParser, FormParser)

When I use the the drf web interface:

enter image description here

Vlad Otrocol
  • 2,952
  • 7
  • 33
  • 55

1 Answers1

5

I solved it by overriding the create method and making images readonly:

class AnimalSerializer(serializers.HyperlinkedModelSerializer):

     images = AnimalImageSerializer(many=True, read_only=True)

     def create(self, validated_data):
         images_data = self.context['request'].FILES
         animal = Animal.objects.create(
             slug=validated_data.get('slug', 'default-slug')
         )
         for image_data in images_data.getlist('file'):
             AnimalImage.objects.create(animal=animal, image=image_data)

     class Meta:
         model = Animal
         lookup_field = 'slug'
         extra_kwargs = {
             {'url': {'lookup_field': 'slug'}
         }
         fields = ('slug', 'images', )

Also make sure you remove JsonParser from the ModelViewSet

JSONParser

Make sure that if you use Postman, you only use the form-data type of body

Also make sure that you add all fields required to create your model, Animal

Don't add the images field and make it readonly in the serializer

Make a new field and call it file and make it of type File instead of Text.

The name of the field must be file because you will use getlist('file'). Name has to be the same. This is what messed me up.

enter image description here

Vlad Otrocol
  • 2,952
  • 7
  • 33
  • 55
  • This answer, is the simplest solution for uploading multiple images through ForeignKey reverse relationship with Django REST Framework. I spent one day digging to find an alternative way. Don't waste your time, trust me. [KISS](https://en.wikipedia.org/wiki/KISS_principle) – Metehan Gülaç Apr 11 '20 at 01:39
  • I found a solution to an alternative scenario where you can upload multiple images with form-data, validate and send nested json. You can examine my [answer](https://stackoverflow.com/a/61179429/8569342) . – Metehan Gülaç Apr 13 '20 at 14:40