Danny
Danny

Reputation: 327

How to upload multiple images with django rest framework CreateAPI in view and create method in serializers

I have a post serializer and a postimage serializer to upload multiple images to a post. I have this serializer, but I am not sure how to make it in a way, so that I can upload multiple images, for example 5 images with a single post, like how we use with formsets coz now I can upload only 1 image in 'images' field.

These are the serializers. Please do have a look and let me know what changes I have to make...

Thanks

class PostImageSerializer(serializers.ModelSerializer):
    class Meta:
        model = PostImage
        fields = ['id', 'images',]

class PostSerializer(TaggitSerializer, serializers.ModelSerializer):
    user = serializers.ReadOnlyField(source='user.username')
    post_date = serializers.ReadOnlyField()
    postimage_set = PostImageSerializer(many=True)
    likes = UserSerializer(many=True)
    class Meta:
        model = Post
        fields = ['id','title', 'post_date', 'updated', 'user', 'image', 'postimage_set']

    def create(self,validated_data):
        user = self.context['request'].user
        title = validated_data['title']
        image = self.context['request'].FILES.get('image')
        images = self.context['request'].FILES.get('images')

        m1 = Post(user=user,title=title,image=image,)
        m1.save()
        m2 = PostImage(post=m1, images= images)
        m2.save()
        validated_data['images']=m2.images
        validated_data['image']=m1.image
        return validated_data

views

class CreatePostAPIView(generics.CreateAPIView):
    serializer_class = PostCreateSerializer
    permission_classes = [IsAuthenticated]

    def create(self, request, *args, **kwargs):
        serializer = PostCreateSerializer(data=request.data, context={'request':request,})
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

Upvotes: 1

Views: 1516

Answers (3)

Danny
Danny

Reputation: 327

This solved the problem

def create(self, validated_date):
    images = self.context['request'].FILES.getlist('images')

    for image in list(images):
        m2 = PostImage(post=m1, images= image)
        m2.save()

Upvotes: 2

federico
federico

Reputation: 69

I would do it like this. Make a PostModel and a PostImageModel (with a post ForeignKey) for each post image. And then in the serializer, make relation field with both. Something like this:

models.py

class Post(Model):
    post details ...

class PostImage(Model):
    post = models.ForeigKey(Post, ...)
    image = models.ImageField(...)

serializers.py

class PostImageSerializer(serializers.ModelSerializer):
    class Meta:
        model = PostImage
        fields = '__all__'

class PostSerializer(serialiers.ModelSerializer):
    
    images = serializers.SlugRelatedField(slug_field='image', many=True, ...)

    class Meta:
        model = Post
        fields = [..., 'images']

views.py

class CreatePostView(CreateView):
    classForm = PostForm (with images field)
    
    def form_valid(self, form):
        new_post = form.save(commit=False)
        for image in new_post.images:
            new_image = PostImage(post=new_post, image=image)
            new_image.save()
        new_post.save()
        return super()form_valid(form)

So then in your api you should be able to see the post model with the images attached to it.

Upvotes: 0

vpdiongzon
vpdiongzon

Reputation: 679

This is how you do the multiple upload on drf: example below on create you can access the multiple item you posted:

e.g posted:

Formdata

images: File.jpeg
images: File2.jpeg
images: File3.jpeg

class TestSerializer(serializers.Serializer):
    images = serializers.ListField(child=serializers.FileField())


class CreatePostAPIView(generics.CreateAPIView):
    permission_classes = [AllowAny]
    serializer_class = TestSerializer

    def create(self, request, *args, **kwargs):
        images = request.data['images']

Upvotes: 0

Related Questions