Skip to content
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

Unable to make the ImageField as required in Swagger POST API #66

Closed
MounikaKommineni opened this issue Jan 21, 2019 · 29 comments
Closed
Assignees

Comments

@MounikaKommineni
Copy link

My model:

class Image(models.Model):
      image=models.ImageField(upload_to='photos')
      name=models.CharField(max_length=40,unique=False)

My serializer:

class imagesSerializer(serializers.ModelSerializer):
      image = Base64ImageField(required=True)
      class Meta:
         model = Image
         fields = ('id','name','image')

My swagger view:
kfrof

How to make the imagefield as required in swagger post request ?

@johnthagen
Copy link
Contributor

I noticed this too in generated Angular TypeScript. The image variables were always marked with ?, meaning they were optional.

@shafiyal
Copy link

I am also facing the same issue even though i specified required=True in serializer class

@baranugur
Copy link

I'm using the same serializer setup and mine seems to be working fine. Maybe this is an issue of differences in versions. Here are the versions of Django, Django Extra Fields, Django REST Framework and Django REST Swagger that I have used, so you can compare: Django==2.1.7, django-extra-fields==1.0.0, djangorestframework==3.9.2, django-rest-swagger==2.2.0.

swagger_correct

@johnthagen
Copy link
Contributor

I wonder if it's because of the readOnly property? Would a readOnly property make it optional because it's not required when writing to the API? Is this because of how the file is normally returned as a URL rather than the data directly? (I'm just spit balling at this point).

@baranugur
Copy link

ReadOnly fields cannot be required at the same time, therefore it's not possible to have a field where both required and read_only are set to True in the latest version of Django REST Framework.

@johnthagen
Copy link
Contributor

What's weird is in my case, I never set read_only to True. The serializer is a WritableNestedSerializer, but I don't see how that would affect the field.

@baranugur
Copy link

I've used the serializer below:

class ImageSerializer(WritableNestedModelSerializer):
    image = Base64ImageField(required=True)

    class Meta:
        model = Image
        fields = ('id', 'name', 'image')

It still seems to be working fine.

swagger

@johnthagen
Copy link
Contributor

johnthagen commented Mar 18, 2019

@baranugur Could you also post your Image Model?

I wonder why your image field doesn't say string($uri). That is how mine always is (and the OP's).

Also, I'm using drf-yasg == 1.13.0 instead of django-rest-swagger due to django-rest-swagger having low maintenance as of late. Perhaps others in the thread could comment on which they are using.

@baranugur
Copy link

The model that I've created is identical to OP's.

I think drf-yasg==1.13.0 is causing the problem here. I've just tried it with Base64ImageField and then I've used the built-in serializers.ImageField; this is what I've gotten in both cases:

yasg

@johnthagen
Copy link
Contributor

Cross posted to axnsan12/drf-yasg#332

@johnthagen
Copy link
Contributor

Confirmed this is drf-yasg specific (intended) behavior:

axnsan12/drf-yasg#332 (comment)

That is indeed the case. The field you linked breaks the contract of FileField by making it accept a string instead of an UploadedFile.

You can work around this with a custom FieldInspector that returns an appropriate Schema object of type string, which should be placed before the FileFieldInspector.

@yigitguler
Copy link
Member

Marking as completed.

@johnthagen
Copy link
Contributor

johnthagen commented Apr 18, 2019

@yigitguler There may be a way to work around this (at least in documentation): axnsan12/drf-yasg#332 (comment)

I don't quite understand what needs to be done, but if this issue were left open it might be useful. We may be able to at least document how to make this work with drf-yasg, which I think would be valuable given it's the best maintained OpenAPI generator available for Django currently.

Do you happen to understand the comment in the link above, and how we could fix it?

@yigitguler yigitguler reopened this Apr 18, 2019
@yigitguler
Copy link
Member

We can reopen the issue. However, I think there is nothing we can do to fix this situation. Developers of drf-yasg assumed that only multipart requests can contain files. Which is not true for our use case.

@johnthagen
Copy link
Contributor

Using Custom Schema Generation may be a method to solve this.

@WasinTh
Copy link
Contributor

WasinTh commented Aug 21, 2019

EDITED : Fix the class checking algorithm. My previous answer does not work on FileField or FieldMixin.

Hi! This is the work around code that I've overridden FieldInspector to mark Base64ImageField, Base64FileField, Base64FieldMixin as required field
NOTE: I've to remove format from the String because the POST, PUT, PATCH... method use SchemaRef which reference the schema from GET method.

from drf_yasg import openapi
from drf_yasg.inspectors import FieldInspector, SwaggerAutoSchema
from drf_yasg.app_settings import swagger_settings


class Base64FileFieldInspector(FieldInspector):
    BASE_64_FIELDS = ['Base64ImageField', 'Base64FileField', 'Base64FieldMixin']

    def __classlookup(self, cls):
        """List all base class of the given class"""
        c = list(cls.__bases__)
        for base in c:
            c.extend(self.__classlookup(base))
        return c

    def process_result(self, result, method_name, obj, **kwargs):
        if isinstance(result, openapi.Schema.OR_REF):
            base_classes = [x.__name__ for x in self.__classlookup(obj.__class__)]
            if any(item in Base64FileFieldInspector.BASE_64_FIELDS for item in base_classes):
                schema = openapi.resolve_ref(result, self.components)
                schema.pop('readOnly', None)
                schema.pop('format', None)  # Remove $url format from string

        return result


class Base64FileAutoSchema(SwaggerAutoSchema):
    field_inspectors = [Base64FileFieldInspector] + swagger_settings.DEFAULT_FIELD_INSPECTORS


class FormAttachmentViewSet(viewsets.ModelViewSet):
    queryset = .......
    serializer_class = ..........
    swagger_schema = Base64FileAutoSchema

Result:
Screen Shot 2562-08-21 at 21 15 39

@johnthagen
Copy link
Contributor

@WasinTh Looks pretty neat -- would you mind opening a PR to this repo's README? I think it would be good to document this for others and for others to test out.

@WasinTh
Copy link
Contributor

WasinTh commented Aug 23, 2019

@johnthagen sure this is the pull request on README.md file
#100

@zengzhengrong
Copy link

How about make it some example code to testprojet, this repo example does not have about flieupload or imageupload,it would be make good to use

@ilmesi
Copy link

ilmesi commented May 11, 2020

In Swagger API, I'm using the following setup to show the field as required without any problems:

class PDFBase64FileField(Base64FileField):
    ALLOWED_TYPES = ['pdf']

    class Meta:
        swagger_schema_fields = {
            'type': 'string',
            'title': 'File Content',
            'description': 'Content of the file base64 encoded',
            'read_only': False  # <-- FIX
        }

    def get_file_extension(self, filename, decoded_file):
        try:
            PyPDF2.PdfFileReader(io.BytesIO(decoded_file))
        except PyPDF2.utils.PdfReadError as e:
            logger.warning(e)
        else:
            return 'pdf'

And to use "string" format instead of an URL, you will need to create the field with use_url=False.

@alicertel
Copy link
Contributor

@ilmesi Thank you for the suggestion. This seems pretty simple to me compered to creating a FieldInspector. What do you think @WasinTh ?

@ilmesi
Copy link

ilmesi commented May 11, 2020

@alicertel No problem! I got it from the code at FieldInspector.add_manual_fields from yasg. It seems to work pretty well and it's less work than creating a new FieldInspector..

@johnthagen
Copy link
Contributor

johnthagen commented May 26, 2020

I can confirm that @ilmesi's answer works. It seems like the most ideal work-around thus far.

It would be good if this was documented somewhere officially.

@WasinTh
Copy link
Contributor

WasinTh commented May 27, 2020

@ilmesi Thank you for the suggestion. This seems pretty simple to me compered to creating a FieldInspector. What do you think @WasinTh ?

Agreed. The solution to override Base64FileField is much more simple.

@alicertel
Copy link
Contributor

@WasinTh Would you like to update your PR #100 with the suggested solution #66 (comment) ?

@WasinTh
Copy link
Contributor

WasinTh commented Aug 14, 2020

@WasinTh Would you like to update your PR #100 with the suggested solution #66 (comment) ?

@alicertel Sure. I've pushed the updated answer on those PRs.

@alicertel
Copy link
Contributor

Thanks @WasinTh

JoelLefkowitz added a commit to JoelLefkowitz/drf-yasg that referenced this issue Oct 12, 2020
* Add sample code to handle Base64 fields in drf-extra-fields project

* Fix format for .rst

* Update Redoc to 2.0.0-rc36

* Update answer to the easier version as suggested in Hipo/drf-extra-fields#66 (comment)

* Fix tox environment to properly test on Django 3.0

* Drop all compat support to Django < 2 urls

* Fix tox environment

* Update manifest

* Populate test db

* Fix broken URLs in README

* Feature/update travis (#17)

* Redefine travis steps to include linting

* Add stage specific install scripts

* Add docs and publish requirements

* Update travis.yml requirements

* Update travis pip executable

* Update flake8 ignore rules and rever pip3 to pip

* Separate deploy stage in travis

* Add tox dependency to test.txt

* Bump drf test targets

* Allow test against latest deps to fail

* Set build matrix against unittest task only

* Remove matrix key from travis.yml

* Use aliases to specify matrix style parallelism for unittests only

* Write tox-filter.sh

* Move linting and formatting conf into their scripts

* Run black and autoflake (#18)

* Fix documentation build (#12)

* Fix malformed RST in README

* Fix Sphinx configuration

Co-authored-by: JoelLefkowitz <45922542+JoelLefkowitz@users.noreply.github.com>

* Move dependencies to setup.py and metadata to setup.cfg (#19)

* Remove requirements, update .gitignore and remove flake8-isort (#20)

* Remove requirements, update .gitignore and remove flake8-isort from linting spec

* Patch test[s] typo

* Fix lint build and set as required on Travis (#22)

Co-authored-by: johnthagen <johnthagen@gmail.com>

* Feature/remove clutter (#21)

* Remove requirements, update .gitignore and remove flake8-isort from linting spec

* Patch test[s] typo

* Patch setup.py test requirements missing comma typo

* Replace pyproject.toml

* Update pyproject.toml

* Update and convert readme and license to md (#25)

* Remove compat.py typo (#26)

* Update license references to md

* Update python2.7 compatability test suite

* Pass sphinx build warnings

* Add bumbpversion.cfg and refactor dry-yasg2 to drf_yasg2

* Remove tox check

* Debump django dependency so that py27 tests can setup

* Update travis test-docs script path

* Add build shield to readme

* Debump pytest dep for python2.7 tests

* Debump djangorestframework-camel-case dep for python2.7 tests

* Debump django-cors-headers dep for python2.7 tests

* Remove swagger-spec-validator dep for python2.7 tests

* Update readme links and add python2.7 classifier

* Add dj_database_url heroku dependency

Co-authored-by: Terry <wasin.th@gmail.com>
Co-authored-by: Julia Nething <julia.nething@mobilityhouse.com>
Co-authored-by: johnthagen <johnthagen@users.noreply.github.com>
Co-authored-by: Fasih Ahmad Fakhri <fasih@email.com>
Co-authored-by: johnthagen <johnthagen@gmail.com>
JoelLefkowitz added a commit to JoelLefkowitz/drf-yasg that referenced this issue Oct 12, 2020
* Add sample code to handle Base64 fields in drf-extra-fields project

* Fix format for .rst

* Update Redoc to 2.0.0-rc36

* Update answer to the easier version as suggested in Hipo/drf-extra-fields#66 (comment)

* Fix tox environment to properly test on Django 3.0

* Drop all compat support to Django < 2 urls

* Fix tox environment

* Update manifest

* Populate test db

* Fix broken URLs in README

* Feature/update travis (#17)

* Redefine travis steps to include linting

* Add stage specific install scripts

* Add docs and publish requirements

* Update travis.yml requirements

* Update travis pip executable

* Update flake8 ignore rules and rever pip3 to pip

* Separate deploy stage in travis

* Add tox dependency to test.txt

* Bump drf test targets

* Allow test against latest deps to fail

* Set build matrix against unittest task only

* Remove matrix key from travis.yml

* Use aliases to specify matrix style parallelism for unittests only

* Write tox-filter.sh

* Move linting and formatting conf into their scripts

* Run black and autoflake (#18)

* Fix documentation build (#12)

* Fix malformed RST in README

* Fix Sphinx configuration

Co-authored-by: JoelLefkowitz <45922542+JoelLefkowitz@users.noreply.github.com>

* Move dependencies to setup.py and metadata to setup.cfg (#19)

* Remove requirements, update .gitignore and remove flake8-isort (#20)

* Remove requirements, update .gitignore and remove flake8-isort from linting spec

* Patch test[s] typo

* Fix lint build and set as required on Travis (#22)

Co-authored-by: johnthagen <johnthagen@gmail.com>

* Feature/remove clutter (#21)

* Remove requirements, update .gitignore and remove flake8-isort from linting spec

* Patch test[s] typo

* Patch setup.py test requirements missing comma typo

* Replace pyproject.toml

* Update pyproject.toml

* Update and convert readme and license to md (#25)

* Remove compat.py typo (#26)

* Bug/fix travis errors (#27)

* Update license references to md

* Update python2.7 compatability test suite

* Pass sphinx build warnings

* Add bumbpversion.cfg and refactor dry-yasg2 to drf_yasg2

* Remove tox check

* Debump django dependency so that py27 tests can setup

* Update travis test-docs script path

* Add build shield to readme

* Debump pytest dep for python2.7 tests

* Debump djangorestframework-camel-case dep for python2.7 tests

* Debump django-cors-headers dep for python2.7 tests

* Remove swagger-spec-validator dep for python2.7 tests

Co-authored-by: Terry <wasin.th@gmail.com>
Co-authored-by: Julia Nething <julia.nething@mobilityhouse.com>
Co-authored-by: johnthagen <johnthagen@users.noreply.github.com>
Co-authored-by: Fasih Ahmad Fakhri <fasih@email.com>
Co-authored-by: johnthagen <johnthagen@gmail.com>
@Hassanzadeh-sd
Copy link

you should change your parser like this :

    from rest_framework import permissions, viewsets
    from rest_framework.mixins import (CreateModelMixin, DestroyModelMixin,
                                       ListModelMixin, RetrieveModelMixin)
    from rest_framework.parsers import FormParser, MultiPartParser
    from .models import Customer
    from .permissions import CustomerPermission
    from .serializer import CustomerSerializer
    
    
    class CustomerViewSet(CreateModelMixin, ListModelMixin, RetrieveModelMixin, 
                          DestroyModelMixin, viewsets.GenericViewSet):
        permission_classes = [CustomerPermission]
        queryset = Customer.objects.all()
        serializer_class = CustomerSerializer
        parser_classes = (FormParser, MultiPartParser)

after that you can check your swagger :

image

I hope this can help you

@Krzyzaku21
Copy link

Krzyzaku21 commented Jan 13, 2022

If you want create no class views but use drf:

register_parameters = [openapi.Parameter(
    'date_of_birth', in_=openapi.IN_FORM, description='Add date like 2000-12-12', type=openapi.FORMAT_DATE,
    required=True)]


@swagger_auto_schema(methods=['post'], request_body=RegisterSerializer, manual_parameters=register_parameters)
@ api_view(['POST', ])
@ parser_classes([parsers.MultiPartParser, parsers.FormParser])
def user_register_serializer(request):
    if request.method == 'POST':
        new_data = {
            'response': f"Email send to {request.data['email']}",
        }
        serializer = RegisterSerializer(data=request.data)
        if serializer.is_valid():
            new_data.update(serializer.data)
            new_data.pop('password')
            serializer.save()
            user_email_send(request)
        else:
            new_data = serializer.errors
        return Response(new_data)

using manual_parameters you can override form in swagger and add new functions like default etc to image.

JoelLefkowitz pushed a commit to axnsan12/drf-yasg that referenced this issue Jul 20, 2023
* Add sample code to handle Base64 fields in drf-extra-fields project

* Fix format for .rst

* Update answer to the easier version as suggested in Hipo/drf-extra-fields#66 (comment)

* update readme.rst

`permission_classes` expects tuple but list was provided

* url from DEFAULT_API_URL now works

fix a bug: url from swagger_settings.DEFAULT_API_URL is not working

* Check for allow_null attribute

* Add utf-8 support for generated formats

* Added `many` support to example code.

* serialize pytz object as a string

* simplify if condition

* handle errors rendering with TemplateHTMLRenderer

This change fixes an `OPTIONS` request to the API page which will return
a successful response, but the `TemplateHTMLRender` will not be prepared
to render it since there is no template name provided in either the view
or response [1].

[1]: https://github.com/encode/django-rest-framework/blob/f0a5b958a134e8cd94e3ef3263e8fa623ac9b82f/rest_framework/renderers.py#L178-L189

* Allow specifying response as a reference

* [readme] Fix missing re_path import

* fix map source mapping

* Remove universal wheel, python 2 is unsupported

* Inline allow_unicode parameter

* Update changelog

* Update changelog typos

* Add cspell

* Fix old spelling errors

* Add ref_name to UserSerializer after removing suffix typo

* Set permission classes to a tuple

* Update chagnelog

* Add prepublish twine check

* Fix action version syntax

* Fix indentation in README.rst code blocks

* Add twine to publish dependencies

* Specify toxenv explicitly

* Specify all tox targets

* Add py prefix to toxenvs

* Update changelog

* Update changelog

* Declare Django 3.2 support in README, classifiers

This commit will make sure that `Django :: 3.2` will show up in the
classifiers list on PyPI: https://pypi.org/project/drf-yasg/

(The magic happens because we parse the README to get supported Django):
https://github.com/DavidCain/drf-yasg/blob/ee29412d3cdb311/setup.py#L36

3.2 support should already exist
================================
A closed pull request, #735,
noted support for Django 3.2 in both `tox.ini`, and the README.

That PR was closed in favor of
#741, which edited `tox.ini`
and switched to GitHub Actions.

#735 (comment)

This project has been testing on Django 3.2 for a long time (about a
year). I think we can declare it supported it the README!

* Fix `pip install` command for contributors on zsh

On `zsh` (a popular shell, and the default for macOS), install fails:

    $ pip install -U -e .[validation]
    zsh: no matches found: .[validation]

Quote the arguments so that `bash` or `zsh` will succeed.

* Dont use NullBooleanField if drf version >= 3.14.0

* Swap back BooleanField and NullBooleanField

* Update changelog

* Update README to use path instead of re_path in example

* Run tests with latest dependencies

- Django 4.0 & 4.1
- DRF 3.13 & 3.14
- Python 3.10

* Add python 3.10 in GH actions matrix

* Fix RecursiveField

* Change github actions runner from ubuntu-latest to ubuntu-20.04

* Change github actions runner from ubuntu-latest to ubuntu-20.04

* Remove python 3.6 tests since swagger-spec-validator no longer supports it

* Use a string literal for python versions such as "3.10"

* Add python 3.10 compatibility to README.md

* Update changelog

* Fix: Provide enums support for schema.

* Fix: Tests for Python 3.11.

* Refactoring: Removed old version code.

* Fix: Linting is now working.

* Fix: Provide usage of Enums as dict keys.

* Fix: Docs build with latest sphinx versions.

* keep path parameters in their given order

* Fix: Action build docs with latest tox version.

* Fix: Update python version for dj-master branch.

Django master branch bumped minimal python version
to Python 3.10. In latest version was added check for uniq basename.

* Feature: Migrate to PyYAML for yaml generator. (#845)

* Feature: Migrate to PyYAML for yaml generator.

Closes #833

* Chore: Update swagger ui and redoc dependencies.

* Fix: Remove required coreapi dependency. (#854)

* Feature: Migrate to PyYAML for yaml generator.

Closes #833

* Chore: Update swagger ui and redoc dependencies.

* Fix: Remove required coreapi dependency.

* Update Changelog

* Feature: Add ``drf_yasg.inspectors.query.DrfAPICompatInspector``. (#857)

* Feature: Provide to override default renderers via settings.

* Feature: Enable tests for django 4.2.

* Docs: Add information how to override ``DEFAULT_SPEC_RENDERERS``.

* Feature: Add ``drf_yasg.inspectors.query.DrfAPICompatInspector``.

This inspector should be main and replace ``CoreAPICompatInspector`` in the future.

* [fix] Fixed map source mapping (#859)

* Tests: Improve test coverage 95.91% -> 98.30%. (#862)

* Update Changelog

* Add python3.6 to the actions matrix but exclude it from tests

---------

Co-authored-by: Terry <wasin.th@gmail.com>
Co-authored-by: Sumit Singh <sumit.singh4613@gmail.com>
Co-authored-by: Core-Chan <i@coreja.com>
Co-authored-by: Krista Mae Rectra <krista.rectra@gmail.com>
Co-authored-by: mmurashov <m.murashov@ritm.media>
Co-authored-by: Christoph Beckmann <cbe@colibri-media.de>
Co-authored-by: MilanPecov <mpecov@yahoo.ca>
Co-authored-by: Terence D. Honles <terence@honles.com>
Co-authored-by: Cristi Vîjdea <cristi@cvjd.me>
Co-authored-by: Max Vorobev <vmax0770@gmail.com>
Co-authored-by: Damien Ramelet <damien.ramelet@protonmail.com>
Co-authored-by: Petr Dlouhý <petr.dlouhy@email.cz>
Co-authored-by: gopackgo90 <cbodendein@live.com>
Co-authored-by: David Cain <davidjosephcain@gmail.com>
Co-authored-by: Amir Andohkosh <4315615+amir-bio@users.noreply.github.com>
Co-authored-by: Nikolaos Michas <nikos.mixas@outlook.com>
Co-authored-by: Ignacio Orlandini <ignacioorlandini@gmail.com>
Co-authored-by: Sergey Klyuykov <onegreyonewhite@mail.ru>
Co-authored-by: Gagan Deep <the.one.above.all.titan@gmail.com>
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