javascriptdjango-rest-frameworkopenapiopenapi-generatordrf-spectacular

OpenAPI Generator doesn't generate functions for multipart/form-data


I have an OpenAPI schema that I generated using DRF-Spectacular. The part that matters is this:

...
    patch:
      operationId: patient_partial_update
      parameters:
      - in: path
        name: patient_id
        schema:
          type: string
          format: uuid
        description: A UUID string identifying this patient.
        required: true
      tags:
      - comp
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PatchedPatientSerialiser'
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/PatchedPatientSerialiser'
          multipart/form-data:
            schema:
              $ref: '#/components/schemas/PatchedPatientSerialiser'
...
components:
  schemas:
    ImageSerialiser:
      type: object
      properties:
        image:
          type: string
          format: uri
        alt:
          type: string
          maxLength: 150
        session:
          type: integer
          maximum: 9223372036854775807
          minimum: -9223372036854775808
          format: int64
          title: Session Number
        angle:
          allOf:
          - $ref: '#/components/schemas/AngleEnum'
          minimum: -9223372036854775808
          maximum: 9223372036854775807
      required:
      - alt
      - image
    PatchedPatientSerialiser:
      type: object
      properties:
        patient_no:
          type: string
          title: Patient Number
          maxLength: 25
        f_name:
          type: string
          nullable: true
          title: First Name
          maxLength: 100
        l_name:
          type: string
          nullable: true
          title: Last Name
          maxLength: 100
        sessions:
          type: integer
          maximum: 9223372036854775807
          minimum: 0
          format: int64
        images:
          type: array
          items:
            $ref: '#/components/schemas/ImageSerialiser'
...

As you can see, the PATCH request has a definition for multipart/form-data, however the client generated by openapi-generator-cli only includes handling for application/json input and passing FormData in results in an empty request. Obviously, passing it in as JSON doesn't work either because I'm working with file uploads, so I'm wondering if I've done something wrong or if I just have to write my own functions for this specific use case.


Solution

  • So I managed to find a workaround, but I'm still not sure if there's another way I should be doing it.

    Firstly, I created a separate API endpoint for the Image instead of having nested data (probably a better way to do it anyway).

    Secondly, I added COMPONENT_SPLIT_REQUEST=True to my REST_FRAMEWORK settings as per the drf-spectacular documentation. This separates create requests from retrieve requests and changes the image property to this as opposed to the uri format in the initial schema:

        ImageSerialiserRequest:
          type: object
          properties:
            image:
              type: string
              format: binary
    

    This allows you to pass in the blob/file directly to the API and have it handled correctly.

    Finally, I had to go into my schema file and manually remove the alternate requestBody entries so my imageCreateRequest looked like this:

        post:
          operationId: image_create
          tags:
          - comp
          requestBody:
            content:
              multipart/form-data:
                schema:
                  $ref: '#/components/schemas/ImageSerialiserRequest'
    

    This was the only way I could get the API client to generate properly and send data as FormData. Even with the image being in binary format, it only generated 'application/JSON' methods. I'm not sure if this is an issue with the OpenAPI-generator or if there's some configuration options I've missed that could have fixed this for me, but it does seem weird that with all request types defined, it only generates for one regardless of the data types. I'm happy to hear if anyone else has found a different solution. For reference, I'm using the typescript-fetch generator if that makes a difference.