11

I am able to upload a single image with the following code. If I select multiple images then only the last image among the selected image is getting uploaded.

models.py

class Image(models.Model):
property_id = models.ForeignKey(
                'properties.Address',
                null=False,
                default=1,
                on_delete=models.CASCADE
            )
image = models.ImageField(upload_to=directory_path)

serializers.py

class ImageSerializer(serializers.ModelSerializer):
class Meta:
    model = Image
    fields = (
        'property_id',
        'image'
    )

views.py

class ImageView(APIView):
parser_classes = (MultiPartParser, FormParser)

def get(self, request):
    all_images = Image.objects.all()
    serializer = ImageSerializer(all_images, many=True)
    return JsonResponse(serializer.data, safe=False)

def post(self, request, *args, **kwargs):
    file_serializer = ImageSerializer(data=request.data)
    if file_serializer.is_valid():
        file_serializer.save()
        return Response(file_serializer.data, status=status.HTTP_201_CREATED)
    else:
        return Response(file_serializer.errors, status=status.HTTP_400_BAD_REQUEST)


I am a little new to Django. I want to loop over my array of images which is received in the request.data Can anyone tell me how to do it?

2
  • Try file_serializer = ImageSerializer(data=request.FILES, many=isinstance(request.FILES, list)) Commented Oct 20, 2018 at 7:12
  • No, it is not working. Moreover, it is uploading all the images to the same property folder Commented Oct 20, 2018 at 7:18

4 Answers 4

22

So I finally got a workaround in my own way falling back to the basics as I didn't find any way to do it in a DRF way. I hope this answer is helpful to the Django community. I kept my model and serializers same changing the views to iterate over every image and save it using the serializer.

views.py

class ImageView(APIView):
    parser_classes = (MultiPartParser, FormParser)

    def get(self, request):
        all_images = Image.objects.all()
        serializer = ImageSerializer(all_images, many=True)
        return JsonResponse(serializer.data, safe=False)

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

        # converts querydict to original dict
        images = dict((request.data).lists())['image']
        flag = 1
        arr = []
        for img_name in images:
            modified_data = modify_input_for_multiple_files(property_id,
                                                            img_name)
            file_serializer = ImageSerializer(data=modified_data)
            if file_serializer.is_valid():
                file_serializer.save()
                arr.append(file_serializer.data)
            else:
                flag = 0

        if flag == 1:
            return Response(arr, status=status.HTTP_201_CREATED)
        else:
            return Response(arr, status=status.HTTP_400_BAD_REQUEST)

helpers.py

def modify_input_for_multiple_files(property_id, image):
    dict = {}
    dict['property_id'] = property_id
    dict['image'] = image
    return dict

models.py

class Image(models.Model):
    property_id = models.ForeignKey(
                    'properties.Address',
                    null=False,
                    default=1,
                    on_delete=models.CASCADE
                )
    image = models.ImageField(upload_to=directory_path)

serializers.py

class ImageSerializer(serializers.ModelSerializer):
    class Meta:
        model = Image
        fields = (
            'property_id',
            'image'
        )

The request comes in the form of querydict. The line images = dict((request.data).lists())['image'] coverts query dict to python dict and then looping over the array under the 'image' key.

The postman request looks like below:

enter image description here Posts images to the media folder of file system

Sign up to request clarification or add additional context in comments.

4 Comments

Could you please share your form data structure you sending to Django API? I am in a similar problem and can't get it to work...
I have fully described it in question as well as the answer. Go through it throughly
@uneet7 How to retrieve the images as a list like ["img1.png", "img2.png"] Instead of a list of objects like [ {"property_id":"1", "image":"img1.png"}, {"property_id":"2", "image":"img2.png"}] ?
Instead of using flag variable, please consider using serializer.is_valid(raise_exception=True) (notice that the if is not needed here)
1

models.py

class Image(models.Model):
    property_id = models.ForeignKey(
                'properties.Address',
                null=False,
                default=1,
                on_delete=models.CASCADE
            )
    image = models.ImageField(upload_to=directory_path)

serializers.py

class ImageSerializer(serializers.ModelSerializer):
    class Meta:
        model = Image
        fields = (
            'property_id',
            'image'
        )

views.py

class ImageAPIView(ListCreateAPIView):
    queryset = Image.objects.all()
    serializer_class = ImageSerializer
    def post(self, request, *args, **kwargs):
        property_id = request.data['property']
        form_data = {}
        form_data['property']= property_id
        success = True
        response = []
        for images in request.FILES.getlist('images'):
            form_data['images']=images
            print(form_data)
            serializer = PropertyImageSerializers(data=form_data)
            if serializer.is_valid():
                serializer.save()
                response.append(serializer.data)
            else:
                success = False
        if success:
            #return Response(response, status=status.HTTP_201_CREATED)
           
            return Response({
            'status' : 1, 
            'message' : 'Success',
            'Data' : response,
            })
            
          #returnResponse(response,status=status.HTTP_400_BAD_REQUEST)

        return Response({
            'status' : 0, 
            'message' : 'Error!',
        })    

Comments

0

views.py

class ImageAPIView(APIView):
    parser_classes = (MultiPartParser, FormParser)
    def post(self, request):
        pictures = request.FILES.getlist('pictures')
        serializer = PropertySerilaizer(data=request.data)
        if serilaizer.is_valid():
            property = serilaizer.save()
            if pictures:
                image_serilaizer = ImageSerializer(data=[{'image': pic} for pic in pictures],many=True)
                    if image_serializer.is_valid():
                        image_serializer.save(property=property)

this is my approach to handle multiple image and store it in different related model

data = {
     "name": "",
     "pictures": [image1,image2,image3]
}

this is the pattern you can use in form data

Comments

-1

Solution for you should be using ListCreateAPIView. You dont have to implement your own view and handle everything.

class ImageView(generics.ListCreateAPIView):
    parser_classes = (MultiPartParser, FormParser)
    queryset = Image.objects.all()
    serializer_class = ImageSerializer

    def get_serializer(self, *args, **kwargs):
        if isinstance(kwargs.get('data', {}), list):
            kwargs['many'] = True
        return super(CreateListModelMixin, self).get_serializer(*args, **kwargs)

2 Comments

@UnitPatel It can but basically you will be reimplementing the code that is already written in DRF
It is still uploading single image. I have updated my question. Can you please look it into once more?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.