web-dev-qa-db-fra.com

Django Rest Framework ImageField

Je ne peux pas enregistrer l'image dans cet ImageField.

lors du renvoi des données:

{
    "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

rl.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'),)

boucle

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/
36
M.Hoffa

Vous semblez manquer le request.FILES argument du constructeur du sérialiseur dans les gestionnaires your post et put.

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

Je pense que vous pouvez utiliser request.data à la place après Django rest framework 3.0. L'utilisation de request.DATA et request.FILES est désormais en attente de dépréciation au profit d'un seul request.data attribut qui contient toutes les données analysées.

Vous pouvez le vérifier à partir de ici

36
Scofield77

Téléchargement de fichiers image avec 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)

J'espère que cela aide quelqu'un.

9
Ajeet Shah

Ce qui suit devrait fonctionner si vous publiez l'image en tant que chaîne base64 et que votre sérialiseur est défini en conséquence et qu'il hérite du sérialiseur.

 # 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)
4
chandan