42

I can not save the image in this ImageField.

when sending data back:

{
    "image": ["No file was submitted. Check the encoding type on the form."]
}

model.py

class MyPhoto(models.Model):
    owner = models.ForeignKey('auth.User', related_name='image')
    image = models.ImageField(upload_to='photos', max_length=254)

serializers.py

class PhotoSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = MyPhoto
        fields = ('url', 'id', 'image', 'owner')
        owner = serializers.Field(source='owner.username')

view.py

class PhotoList(APIView):
    permission_classes = (permissions.IsAuthenticatedOrReadOnly, IsOwnerOrReadOnly)

    def get(self, request, format=None):
        photo = MyPhoto.objects.all()
        serializer = PhotoSerializer(photo, many=True)
        return Response(data=serializer.data, status=status.HTTP_200_OK)

    def post(self, request, format=None):
       serializer = PhotoSerializer(data=request.DATA)
       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)

    def pre_save(self, obj):
        obj.owner = self.request.user


class PhotoDetail(APIView):

    permission_classes = (permissions.IsAuthenticatedOrReadOnly, IsOwnerOrReadOnly)

    def get_object(self, pk):
        try:
            return MyPhoto.objects.get(pk=pk)
        except MyPhoto.DoesNotExist:
            raise Http404

    def get(self, request, pk, format=None):
        photo = self.get_object(pk)
        serializer = PhotoSerializer(photo)
        return Response(serializer.data)

    def put(self, request, pk, format=None):
        photo = self.get_object(pk)
        serializer = PhotoSerializer(photo, data=request.DATA)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

    def delete(self, request, pk, format=None):
        photo = self.get_object(pk)
        photo.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)

    def pre_save(self, obj):
        obj.owner = self.request.user

url.py

urlpatterns = patterns('',
    url(r'^$', 'main.views.main_page'),
    url(r'^api/photo/$', views.PhotoList.as_view(), name='myphoto-list'),
    url(r'^api/photo/(?P<pk>[0-9]+)/$', views.PhotoDetail.as_view(), name='myphoto-detail'),)

curl

curl -X POST -S \
  -H 'Content-Type: application/json' \
  -u "michael:bush_pass" \
  --data-binary '{"owner":"/users/1/", \
    "image":"/Users/test/Downloads/1383310998_05.jpg"}' \
  127.0.0.1:8000/api/photo/
0

5 Answers 5

40

I think you can use request.data instead after django rest framework 3.0. The usage of request.DATA and request.FILES is now pending deprecation in favor of a single request.data attribute that contains all the parsed data.

You can check it from here

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

1 Comment

This works, as an aside for some reason you cannot access the image data using serializer.data['file_field'], you must instead use serializer.validated_data['file_field'] - caught me out but spotted it in @ckman's answer!
27

You seem to be missing the request.FILES argument to the serializer constructor in the your post and put handlers.

serializer = PhotoSerializer(data=request.DATA, files=request.FILES)

1 Comment

This has not been correct since 2014: django-rest-framework.org/community/3.0-announcement/…
11

Uploading image files with Django Rest Framework:

models.py:

class MyPhoto(models.Model):
    name = models.CharField(max_length=255)
    image = models.ImageField(upload_to='myphoto/%Y/%m/%d/', null=True, max_length=255)

serializers.py:

class MyPhotoSerializer(serializers.ModelSerializer):
    class Meta:
        model = MyPhoto
        fields = ('id', 'name', 'image')

views.py:

class PhotoList(APIView):
    def post(self, request, format=None):
        serializer = MyPhotoSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        else:
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

Hope it helps someone.

3 Comments

How does one upload image to this implementation @Orions ?
@Pedrum In my answer, I have used Django-Rest-Framework's serializer for the model: MyPhoto. When user submits a post request, Image gets uploaded or saved to the path mentioned in the model (path includes year, month and daywise folders). Let me know if it is still not clear.
I am getting this error "detail": "Multipart form parse error - Invalid boundary in multipart: None"
5

Following should work if you are posting the image as base64 string and your serializer set accordingly and it inherits serializer.Serializer

 # views.py 
import base64
import os
from django.core.files import File 

class PhotoList(APIView):
    def post(self,request,format=None):
        serializer = PhotoSerializer(data=request.data)
        if serializer.is_valid():
            # access the data as serializer.validated_data['keys']
            # save the MyPhoto obj lets call it myphoto
            # get the base64 string 
            imgstr64 = serializer.validated_data['corresponding filed in the serializer']
            imgdata = base64.b64decode(imgstr64)
            fname = '/tmp/%s.jpg'%(str(myphoto.id))
            with open(fname,'wb') as f:
                f.write(imgdata)
            imgname = '%s.jpg'%(str(myphoto.id))
            myphoto.image.save(imgname,File(open(fname,'r')))
            os.remove(fname)

Comments

0
**
Django Rest Framework Image Upload
views.py
    class FileUploadView(APIView):
    permission_classes = []
    parser_class = (FileUploadParser,)

    @csrf_exempt
    def uploatuserprofile( request):

        #fetches specific user image
        if request.method=='GET':
            user_data=JSONParser().parse(request)
            obj=UserProfile.objects.filter(user=user_data["user"])
            serializer=UserProfileSerializer(obj,many=True)
            return JsonResponse(serializer.data,safe=False)



        if request.method == 'POST':
            # print('=====================================================================================>',request.FILES['profile_image'])
            
            # print("##################################################################################### ",request.POST['user'])
            try:
                s = UserProfile.objects.create(user_id = request.POST['user'], profile_image=request.FILES['profile_image'])
                s.save()
            except:
                return JsonResponse('Failed to upload Integrity error',safe=False)

            

            # file_serializer=UserProfileSerializer(request.POST,request.FILES)
        
            # if file_serializer.is_valid():
            #     file_serializer.save()
            return JsonResponse('profile uploded Sucessfully!!',safe=False)
        return JsonResponse('Failed to upload',safe=False)

urls.py of application

 url(r'^uploatuserprofile/$',views.FileUploadView.uploatuserprofile),


urls.py of project
from django.conf import settings
from django.conf.urls.static import static

from django.contrib import admin
from django.urls import path
from django.conf.urls import url,include
urlpatterns = [
    path('admin/', admin.site.urls),
    url(r'^',include('ChatApp.urls'))
]
if settings.DEBUG:
    urlpatterns += static(settings.MEDIA_URL,
                          document_root=settings.MEDIA_ROOT)

models.py

class UserProfile(models.Model):
    user = models.ForeignKey(Users,on_delete=models.CASCADE)
    profile_image = models.ImageField(upload_to='images/', blank=True, null=True)



    def __str__(self):
        return self.profile_image.name





setting.py

STATIC_URL = '/images/'
STATICFILES_DIRS = [
os.path.join(BASE_DIR, "images"),

]
STATIC_DIR = os.path.join(BASE_DIR, 'images')
# Base url to serve media files
MEDIA_URL = '/media/'

# Path where media is stored
MEDIA_ROOT = os.path.join(BASE_DIR, 'media/')`enter code here`**

1 Comment

Welcome to StackOverflow. While this code may solve the question, including an explanation of how and why this solves the problem would really help to improve the quality of your post, and probably result in more up-votes. Remember that you are answering the question for readers in the future, not just the person asking now. Please edit your answer to add explanations and give an indication of what limitations and assumptions apply.

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.