Uploading a file with Django REST framework ListCreateAPIView

django, django-rest-framework

Solution

I believe the issue is in your serializer class where you define the `image` model field as `Field`. The generic `Field` is read-only, so that may be the source of the problem. Try simply removing that from your serializer, as it isn't necessary:

class PhotoSerializer(serializers.ModelSerializer):

    class Meta:
        model = Photo

Hope this helps, let me know how you get along.

Problem

Using Django REST framework's generic `ListCreateAPIView`, I've created an end point that I think should be able to upload photos via POST requests. I am modeling my code on this tutorial. So far I have attempted to POST a file to this endpoint using both Android and curl, and observed the same behavior: a new record is created, but the file is not attached. Because the file is a required field, the server then returns a 500 error. This question looks similar, but he's not using REST framework's generic views and I'm not sure why... I'd like to take advantage of them where applicable. Here is my Django view: ``` class PhotoList(generics.ListCreateAPIView): model = Photo serializer_class = PhotoSerializer permission_classes = [ permissions.AllowAny ] ``` ...my model: ``` def get_unique_image_file_path(instance=None, filename='dummy.jpg'): """ function to determine where to save images. assigns a uuid (random string) to each and places it in the images subdirectory below media. by default, we assume the file is a .jpg """ ext = filename.split('.')[-1] filename = "%s.%s" % (uuid.uuid4(), ext) # TODO: 'images' is hard coded return os.path.join('images', filename) class Photo(models.Model): post = models.ForeignKey(Post, related_name='photos', null=True, blank=True) image = models.ImageField(upload_to=get_unique_image_file_path) def get_image_abs_path(self): return os.path.join(settings.MEDIA_ROOT, self.image.name) ``` ... and my serializer: ``` class PhotoSerializer(serializers.ModelSerializer): image = serializers.Field('image.url') class Meta: model = Photo ``` Reproducing the bug To generate the behavior, I POST to the server using the following `curl` command (exactly the same thing happens with my Android client code): ``` curl --form image=@test_image.jpg http://localhost:8000/rest_tutorial/photos ``` Looking into `generics.ListCreateAPIView`, the `create()` method looks like this: ``` # Copied from rest_framework.mixins.CreateModelMixin def create(self, request, *args, **kwargs): serializer = self.get_serializer(data=request.DATA, files=request.FILES) if serializer.is_valid(): self.pre_save(serializer.object) self.object = serializer.save(force_insert=True) self.post_save(self.object, created=True) headers = self.get_success_headers(serializer.data) return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) ``` As I step through the above code in PyCharm's debugger, I can clearly see my file in the serializer's `init_files` field after `serializer.get_serializer()`. However, serializer's `object` field has a bunch of tracebacks but no references to my image file. Maybe something is wrong here? After `self.object = serializer.save(force_insert=True)` the record is created with an empty image field, the file is not uploaded, and `self.object.image.file` just contains a traceback referring to a `ValueError`. Any ideas? Thanks!

Original source

Related problems