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/
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)
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
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)
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.
**
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`**
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/
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)
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
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)
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.
**
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`**