Using FileField/ImageField with Swagger UI and drf-spectacular

4.8k views Asked by At

I have a Django REST Framework project which uses a ModelViewSet to create APIs for a model containing a FileField.

I've shared a full example of a Django project demonstrating this issue here. But to summarise the key components:

models.py

from django.db import models


class Profile(models.Model):
    image = models.FileField(upload_to='uploads/%Y/%m/%d/')

views.py

from rest_framework import (
    viewsets,
    serializers,
    parsers,
)

from sample import models


class ProfileSerializer(serializers.ModelSerializer):

    class Meta:
        model = models.Profile
        fields = ['id', 'image']
        read_only_fields = ['id']


class ProfileViewSet(viewsets.ModelViewSet):
    serializer_class = ProfileSerializer
    queryset = models.Profile.objects.all()

urls.py

from drf_spectacular.views import (
    SpectacularAPIView,
    SpectacularSwaggerView,
)

from django.contrib import admin
from django.urls import path, include
from django.conf.urls.static import static
from django.conf import settings

from rest_framework.routers import DefaultRouter

from sample import views


router = DefaultRouter()
router.register('profile', views.ProfileViewSet)


urlpatterns = [
    path('admin/', admin.site.urls),
    path('api/schema/', SpectacularAPIView.as_view(), name='api-schema'),
    path(
        'api/docs/',
        SpectacularSwaggerView.as_view(url_name='api-schema'),
        name='api-docs',
    ),
    path('', include(router.urls)),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

settings.py (REST_FRAMEWORK configuration only):

REST_FRAMEWORK = {
    'DEFAULT_SCHEMA_CLASS': 'drf_spectacular.openapi.AutoSchema',
}

requirements.txt

Django==3.2.3
djangorestframework==3.12.4
drf-spectacular==0.16.0

I am generating browsable Swagger-UI docs using drf-spectacular to document the API.

The problem is that the FileField input in Swagger-UI is a string input, and doesn't give the option to set a file:

enter image description here

I would like to have a file input where I can choose a file which will be sent to the API.

My question is: How can I configure DRF or drf-spectacular to show this field?

1

There are 1 answers

5
LondonAppDev On

After some digging through the drf-spectacular docs and GitHub issues, I found that the FileField can be set to binary by adding the following to in settings.py:

SPECTACULAR_SETTINGS = {
    'COMPONENT_SPLIT_REQUEST': True
}

Also in Swagger UI, make sure you change the content-type from application/json to multipart/form-data and click Try it out. The upload button will apppear.