Code Monkey home page Code Monkey logo

Comments (11)

kemingy avatar kemingy commented on August 25, 2024 2

Are there some reasons for choosing to add both request.form or request.json in the same @api.validate(json=Schema)? Instead of declaring the two different schemas?

The request body can be either JSON data (maybe other serialized type) or a file.

There is a PR related to this:

This PR doesn't have activities for a long time. Hope we can work together to improve it.

from spectree.

kemingy avatar kemingy commented on August 25, 2024 1

Thanks for your feedback.

Pydantic doesn't have a file type. Actually, flask will create a werkzeug.datastructures.FileStorage object. To support this, you need to provide a File type.

from werkzeug.datastructures import FileStorage
from pydantic import BaseModel


class File:
    file: FileStorage
    class Config:
        arbitrary_types_allowed = True

Let's say if you have multiple items in the form, then you may need to create the schema like this:

from werkzeug.datastructures import FileStorage
from pydantic import BaseModel


class Form:
    file: FileStorage
    user: str
    addr: str

    class Config:
        arbitrary_types_allowed = True

I'll create a PR to support this.

from spectree.

gomeslucasm avatar gomeslucasm commented on August 25, 2024 1

The problem is that spectree only parse request body for json on docs generation.

if hasattr(func, "json"):
        data = {"content": {"application/json": {"schema": {"$ref": f"#/components/schemas/{func.json}"}}}}

In the request context, spectree convert both request.form and request.json in the same request.context.json.

I'm start to use spectree in my work and I made some modifications to put @api.validate(json=JsonSchema) or @api.validate(form=FormSchema), using that, I modificate the request body parser for docs, to diferentiate the two types

if hasattr(func, "json"):
        data = {"content": {"application/json": {"schema": {"$ref": f"#/components/schemas/{func.json}"}}}}

if hasattr(func, "form"):
        data = {"content": {"multipart/form-data": {"schema": {"$ref": f"#/components/schemas/{func.form}"}}}}

After do that, you will be able to create a pydantic custom schema for file that has a customized schema that returns the openapi spec for file upload.

class UploadedFile:
    @classmethod
    def __get_validators__(cls):
        yield cls.validate

    @classmethod
    def validate(cls, v):
        return v
    @classmethod
    def __modify_schema__(cls, field_schema):
        field_schema["type"] = "file"
        field_schema["format"] = "binary"

from spectree.

gomeslucasm avatar gomeslucasm commented on August 25, 2024 1

Interesting, maybe I can help you, I don't have knowledge about starlette or falcon, but I can give you some ideas about the modifications that I made in the flask plugin.

from spectree.

kemingy avatar kemingy commented on August 25, 2024

Pydantic doesn't have a file type. Actually, flask will create a werkzeug.datastructures.FileStorage object. To support this, you need to provide a File type.

The problem is that cannot generate the schema because FileStorage is not a pydantic model.

I guess we need to create another model like this:

class FlaskFile(BaseModel):
    filename: str
    name: str
    content_length: int
    content_type: str
    mimetype: str
    stream: bytes

from spectree.

kemara avatar kemara commented on August 25, 2024

Thank you for your help but I was still unable to create a functioning swagger doc that can upload a file.

When I try to add it to a spectree.validate as json or header an error accurs:
Value not declarable with JSON Schema, field: name='file' type=FileStorage required=True

As I understood you we need to add FlaskFile into spectree so it can handle it. Is there any way I could help with that?

from spectree.

kemingy avatar kemingy commented on August 25, 2024

I found a solution. It may not be elegant.

from werkzeug.datastructures import FileStorage
from pydantic import BaseModel


FlaskFile = FileStorage


def file_modify_schame(cls, field_schema):
    field_schema.update(format='file-storage')


FlaskFile.__modify_schema__ = classmethod(file_modify_schame)


class Form(BaseModel):
    user: str
    file: FlaskFile

    class Config:
        arbitrary_types_allowed = True

The code above will work with this commit: 53936d4

Let me know if you have any ideas.

from spectree.

kemara avatar kemara commented on August 25, 2024

Thank you again for your help but I was still not able to make it work.
Here is the complete flask application where I tried to make it work:

from flask import Flask
from spectree import SpecTree
from werkzeug.datastructures import FileStorage
from pydantic import BaseModel

FlaskFile = FileStorage

def file_modify_schame(cls, field_schema):
    field_schema.update(format='file-storage')

FlaskFile.__modify_schema__ = classmethod(file_modify_schame)

class Form(BaseModel):
    user: str
    file: FlaskFile

    class Config:
        arbitrary_types_allowed = True

app = Flask(__name__)
api = SpecTree('flask')

@app.route('/', methods=['POST'])
@api.validate(json=Form)
def hello_world():
    return 'Hello World!'

api.register(app)
if __name__ == '__main__':
    app.run()

The swagger looks like:
Screenshot 2020-12-09 at 10 57 54

Is there anything wrong that I am doing?

from spectree.

kemingy avatar kemingy commented on August 25, 2024

Hi, I think your code is correct. But sadly swagger doesn't support the customized type of object. I think you can find the definition in swagger schemas below or redoc page (/apidoc/redoc).

from spectree.

gomeslucasm avatar gomeslucasm commented on August 25, 2024

Are there some reasons for choosing to add both request.form or request.json in the same @api.validate(json=Schema)? Instead of declaring the two different schemas?

from spectree.

yedpodtrzitko avatar yedpodtrzitko commented on August 25, 2024

closing, solved via #225

from spectree.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.