Skip to content

DRF doesn't change the media type of request body to multipart/form-data automatically #6863

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
5 of 6 tasks
knivets opened this issue Aug 9, 2019 · 7 comments
Open
5 of 6 tasks

Comments

@knivets
Copy link
Contributor

knivets commented Aug 9, 2019

Checklist

  • I have verified that that issue exists against the master branch of Django REST framework.
  • I have searched for similar issues in both open and closed tickets and cannot find a duplicate.
  • This is not a usage question. (Those should be directed to the discussion group instead.)
  • This cannot be dealt with as a third party library. (We prefer new functionality to be in the form of third party libraries where possible.)
  • I have reduced the issue to the simplest possible case.
  • I have included a failing test as a pull request. (If you are unable to do so we can still accept the issue.)

Steps to reproduce

# view.py
from rest_framework import generics
from rest_framework import serializers
from django.db import models

class Book(models.Model):
  title = models.CharField(max_length=200)

class BookSerializer(serializers.ModelSerializer):
  cover = serializers.FileField()
  class Meta:
    model = Book
    fields = ('cover',)

class BooksView(generics.CreateAPIView):
  queryset = Book.objects.all()   
  serializer_class = BookSerializer

# urls.py
urlpatterns = [
...
path('api/books/', views.BooksView.as_view()),
...
]

Expected behavior

./manage.py generateschema 
openapi: 3.0.2
info:
  title: ''
  version: TODO
paths:
  /api/books/:
    post:
      operationId: CreateBook
      parameters: []
      requestBody:
        content:
          multipart/form-data:
            schema:
              required:
              - cover
              properties:
                cover:
                  type: string
                  format: binary
      responses:
        '200':
          content:
            application/json:
              schema:
                required:
                - cover
                properties:
                  cover:
                    type: string

Actual behavior

./manage.py generateschema 
openapi: 3.0.2
info:
  title: ''
  version: TODO
paths:
  /api/books/:
    post:
      operationId: CreateBook
      parameters: []
      requestBody:
        content:
          application/json:
            schema:
              required:
              - cover
              properties:
                cover:
                  type: string
      responses:
        '200':
          content:
            application/json:
              schema:
                required:
                - cover
                properties:
                  cover:
                    type: string

There are two things going on here:

  1. There is no support for automatic multipart/form-data media type generation
  2. The FileField generates incomplete OpenAPI schema: it doesn't include format: binary. Finally, it should only generate format: binary for requests, since you can't have a binary string field within application/json media type. We could probably add a format: uri in case use_url=True.

https://swagger.io/docs/specification/describing-request-body/multipart-requests/

On unrelated note I noticed that DRF doesn't put type: object under schema even though this spec passes validation here

@tomchristie
Copy link
Member

Yeah seems valid to me. Of course it’s less obvious what we should do if we have both FileField and composite field types (that multipart can’t support.)

@knivets
Copy link
Contributor Author

knivets commented Aug 9, 2019

Could you please give an example of request body with file and composite field?

@tomchristie
Copy link
Member

Eg. Anything with both FileField and DictField

@tomchristie
Copy link
Member

Or FileField and a nested serializer

@carltongibson
Copy link
Collaborator

@knivets you fancy taking a pop at this? As Tom says, we should be able to do the simple cases at least.

(There may come a complexity level where we say “use a subclass to specify this particular case” rather than try and solve everything, but we’re not there yet...)

@knivets
Copy link
Contributor Author

knivets commented Aug 10, 2019

Yes! I’ll work on this over the weekend.

@gnuletik
Copy link
Contributor

gnuletik commented Feb 11, 2020

@knivets Do you have an idea what is the expected schema using OpenAPI Components ?
Component's goal is to keep the same properties for request and response and reference them.

In the example you posted in "Expected behavior", the format: binary property is only in the "requestBody".
Should the schema include a different component for request and response?

I wasn't able to find any example about this on the web.
Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants