yasg with tutorial framework drf coreapi python django django-rest-framework swagger django-swagger

python - with - Django REST Framework+Django REST Swagger+ImageField



drf yasg documentation (3)

Creé un modelo simple con un ImageField y quiero hacer una vista de API con django-rest-framework + django-rest-swagger, que está documentado y es capaz de cargar el archivo.

Esto es lo que obtuve:

models.py

from django.utils import timezone from django.db import models class MyModel(models.Model): source = models.ImageField(upload_to=u''/photos'') is_active = models.BooleanField(default=False) created_at = models.DateTimeField(default=timezone.now) def __unicode__(self): return u"photo {0}".format(self.source.url)

serializer.py

from .models import MyModel class MyModelSerializer(serializers.ModelSerializer): class Meta: model = MyModel fields = [ ''id'', ''source'', ''created_at'', ]

views.py

from rest_framework import generics from .serializer import MyModelSerializer class MyModelView(generics.CreateAPIView): serializer_class = MyModelSerializer parser_classes = (FileUploadParser, ) def post(self, *args, **kwargs): """ Create a MyModel --- parameters: - name: source description: file required: True type: file responseMessages: - code: 201 message: Created """ return super(MyModelView, self).post(self, *args, **kwargs)

urls.py

from weddings.api.views import MyModelView urlpatterns = patterns( '''', url(r''^/api/mymodel/$'', MyModelView.as_view()), )

Para mí esto debería ser bastante simple. Sin embargo, no puedo hacer que la carga funcione. Siempre recibo esta respuesta de error:

He leído esta parte de la documentación de django-rest-framework :

If the view used with FileUploadParser is called with a filename URL keyword argument, then that argument will be used as the filename. If it is called without a filename URL keyword argument, then the client must set the filename in the Content-Disposition HTTP header. For example Content-Disposition: attachment; filename=upload.jpg.

Sin embargo, el encabezado se pasa por django-rest-swagger en la propiedad Solicitar carga útil (desde la consola de Chrome).

Si necesita más información, hágamelo saber.

Estoy usando Django==1.8.8 , djangorestframework==3.3.2 y django-rest-swagger==0.3.4 .


Lo hice funcionar haciendo un par de cambios en tu código.

Primero, en models.py , cambie el nombre de ImageField a file y use la ruta relativa para cargar la carpeta. Cuando carga un archivo como transmisión binaria, está disponible en el diccionario request.data bajo la clave de archivo ( request.data.get(''file'') ), por lo que la opción más limpia es asignarlo al campo modelo con el mismo nombre.

from django.utils import timezone from django.db import models class MyModel(models.Model): file = models.ImageField(upload_to=u''photos'') is_active = models.BooleanField(default=False) created_at = models.DateTimeField(default=timezone.now) def __unicode__(self): return u"photo {0}".format(self.file.url)

En serializer.py , cambie el nombre del campo de origen al archivo:

class MyModelSerializer(serializers.ModelSerializer): class Meta: model = MyModel fields = (''id'', ''file'', ''created_at'')

En views.py, no llame a super, sino que llame a create ():

from rest_framework import generics from rest_framework.parsers import FileUploadParser from .serializer import MyModelSerializer class MyModelView(generics.CreateAPIView): serializer_class = MyModelSerializer parser_classes = (FileUploadParser,) def post(self, request, *args, **kwargs): """ Create a MyModel --- parameters: - name: file description: file required: True type: file responseMessages: - code: 201 message: Created """ return self.create(request, *args, **kwargs)

He usado la extensión Postman Chrome para probar esto. He subido imágenes como binarios y he configurado manualmente dos encabezados:

Content-Disposition: attachment; filename=upload.jpg Content-Type: */*


Según mi experiencia, FileUploadParser funciona con este formato de solicitud:

curl -X POST -H "Content-Type:multipart/form-data" / -F "file=@{filename};type=image/jpg" / https://endpoint.com/upload-uri/

El request.data[''file''] en su vista tendrá el archivo.

Tal vez si prueba un Content-Type:multipart/form-data , tendrá suerte.


Esta es la solución final que se me ocurrió:

from rest_framework import generics from rest_framework.parsers import FormParser, MultiPartParser from .serializer import MyModelSerializer class MyModelView(generics.CreateAPIView): serializer_class = MyModelSerializer parser_classes = (FormParser, MultiPartParser) def post(self, *args, **kwargs): """ Create a MyModel --- parameters: - name: source description: file required: True type: file responseMessages: - code: 201 message: Created """ return super(MyModelView, self).post(self, *args, **kwargs)

Todo lo que tuve que hacer fue cambiar los analizadores de FileUploadParser a (FormParser, MultiPartParser)