Django Rest Framework ImageField

Question:

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/
Asked By: M.Hoffa

||

Answers:

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)
Answered By: Kevin Stone

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

Answered By: Scofield77

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)
Answered By: chandan

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.

Answered By: Ajeet Shah
**
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`**
Answered By: Mohit Verma