miguelgrinberg / apifairy Goto Github PK
View Code? Open in Web Editor NEWA minimalistic API framework built on top of Flask, Marshmallow and friends.
License: MIT License
A minimalistic API framework built on top of Flask, Marshmallow and friends.
License: MIT License
Hey Miguel, do you have something in the oven for disabling validation?
There are some cases (mostly for responses) where you don't want that overhead in production
Miguel,
This is a much needed library! Thanks for sharing this.
I just have a quick question. How would we get the extension to pickup two parameters in a route like this:
@bp.route("/<int:id>/<int:version>", methods=["GET"])
When I elect to use the Swagger UI in my configuration, and select "Try it out" in Swagger, the Swagger UI only asks for the version value. (So there is no way that I'm aware of to enter the id from the Swagger UI).
This isn't so much about the Swagger UI, I'm more just wondering how we make the extension recognize both parameters. Should we use the @arguments decorator? Or is there a way for the extension to "just know" that there are two parameters in the route/endpoint?
Thanks!
The api must include an entity or json that contains an explanation to the error situation. For example, a 400 because a field is missing or a 400 because a tuple with the same value of a field already exists, etc. Is it possible to configure the other_responses decorator for it?
Hey Miguel! Thanks for this extensions. I have a question, how would I manage multiple API versions? I'm using a blueprint for each version of my API (don't know if it's the best approach), how can I get a the docs for each version?
I don't think I could love this package any more, thank you so so much!
I'm just stuck on trying to return a failure response. I've got the authentication, request body, and success responses working fine. I just can't find in the docs exactly how I'm supposed to respond an error response (like 400, 401, etc). I was trying to follow this walkthrough to see how I can return a non-success response by making a post request to create a duplicate Thing
, but I am getting the following error:
RuntimeError: The @response decorator cannot handle Response objects.
Here is my route:
@things.route('/create', methods=['POST'])
@authenticate(auth)
@body(NewThingSchema(unknown=ma.EXCLUDE))
@response(ThingSchema, status_code=201, description='Created a thing.')
@other_responses({400: "thing name already exists"})
def create_thing(args):
db = Session()
thing_name = args.get('thing_name')
existing = db.query(Thing).filter_by(thing_name=thing_name).first()
if existing:
resp = {"err": "thing by that name already exists."}
db.close()
abort(400)
...
I could return a ThingSchema
instead of abort
so it would align with the regular @response
, but I want to return error code with it since it's not a successful creation. I just can't figure out how to send back a response that is in the @other_responses
.
How can I return a different response from the success one? Ideally one with a message.
How would you document file upload using APIFairy ?
I'm using Flask and something like:
file = request.files['file']
Would you put the file content in a JSON and use @body
?
I'm using the following for auth:
basic_auth = HTTPBasicAuth()
token_auth = HTTPTokenAuth('Bearer')
multi_auth = MultiAuth(basic_auth, token_auth)
Then when using authenticate:
@authenticate(multi_auth)
I get the following error:
192.168.223.1 - - [30/Jun/2021 20:53:01] "GET /apispec.json HTTP/1.1" 500 -
Traceback (most recent call last):
File "/home/spacekbnueve/.local/share/virtualenvs/project-X5mbx1aO/lib/python3.6/site-packages/flask/app.py", line 2088, in __call__
return self.wsgi_app(environ, start_response)
File "/home/spacekbnueve/.local/share/virtualenvs/project-X5mbx1aO/lib/python3.6/site-packages/flask/app.py", line 2073, in wsgi_app
response = self.handle_exception(e)
File "/home/spacekbnueve/.local/share/virtualenvs/project-X5mbx1aO/lib/python3.6/site-packages/flask/app.py", line 2070, in wsgi_app
response = self.full_dispatch_request()
File "/home/spacekbnueve/.local/share/virtualenvs/project-X5mbx1aO/lib/python3.6/site-packages/flask/app.py", line 1515, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/home/spacekbnueve/.local/share/virtualenvs/project-X5mbx1aO/lib/python3.6/site-packages/flask/app.py", line 1513, in full_dispatch_request
rv = self.dispatch_request()
File "/home/spacekbnueve/.local/share/virtualenvs/project-X5mbx1aO/lib/python3.6/site-packages/flask/app.py", line 1499, in dispatch_request
return self.ensure_sync(self.view_functions[rule.endpoint])(**req.view_args)
File "/home/spacekbnueve/.local/share/virtualenvs/project-X5mbx1aO/lib/python3.6/site-packages/apifairy/core.py", line 51, in json
return dumps(self.apispec), 200, \
File "/home/spacekbnueve/.local/share/virtualenvs/project-X5mbx1aO/lib/python3.6/site-packages/apifairy/core.py", line 82, in apispec
self._apispec = self._generate_apispec().to_dict()
File "/home/spacekbnueve/.local/share/virtualenvs/project-X5mbx1aO/lib/python3.6/site-packages/apifairy/core.py", line 162, in _generate_apispec
raise RuntimeError('Unknown authentication scheme')
RuntimeError: Unknown authentication scheme
Am I doing something wrong or multi auth is not supported ?
How to declare Schema in separate file? As well as using blueprints?
While rendering some long descriptions I could see some additional spaces which is not stripped down (If we are following default indentation in docstring). So I forked and tried instead these lines
something like:
if len(docs) > 1:
operation['description'] = '\n'.join([''.join(docstr).strip() for docstr in docs[1:]])
Then it works fine. Can you please check that out? I am not making PR because there might be a better way to solve this issue.
The documentation does say:
The decorator performs the serialization of the returned object or dictionary to JSON through the schema’s jsonify() method.
Looking at theMicroblog API
project however it seems to work in a different way?
Is it correct to say that the implementation of the jsonify
method is not always required and if not how does it work?
Interesting when doing a flask-sqlalchemy
query.all()
and if the jsonify
method is not implemented it returns {}
but if using query.first()
then it serializes just fine (and also applies the @post_dump
decorator just fine).
How would one go about doing the same for a schema with a nested schema (list). It is possible without implement the jsonify
method?
ref: #32
Why does code 204 appear in Responses (docs) when it has not been declared as @other_response?
Code:
@campaigns_blueprint.route('/api/campaign', methods=['POST'])
@body(CampaignsSchema)
@other_responses({201: 'Campaign was added!', 400: 'Invalid request.'})
def add_campaig(campaign):
"""
Create a campaign
This endpoint create a campaign.
"""
post_data = request.get_json()
response_object = {
'status': 'fail',
'message': 'Invalid payload.'
}
name = post_data.get('name')
description = post_data.get('description')
fund = post_data.get('fund')
try:
campaign = Campaigns.query.filter_by(name=name).first()
if not campaign:
db.session.add(
Campaigns(name=name, description=description, fund=fund))
db.session.commit()
response_object['status'] = 'success'
response_object['message'] = 'Campaign was added!'
return response_object, 201
else:
response_object['message'] = 'Sorry. That campaign name already exists.'
return response_object, 400
except exc.IntegrityError as e:
db.session.rollback()
return response_object, 400
My API endpoint returns users so I used @response
with the user schema.
Now in case of error I would also like to return something like:
{
"error": {
"message": "Lorem ipsum",
"type": "foobar"
}
}
Obviously that does not match the user schema and my endpoint returns {}
when an error happens.
What would be the best way to achieve what I want to do ?
Thanks for your help.
I'm using mongodb and I created a custom marschmallow field to serialize and deserialize mongodb ids which are ObjectId.
Basically they get serialize to string when returned by the API.
However in the documentation they appear as type null:
Would you know what I should do so that the shown type is string ?
Below the code for the custom field:
class ObjectId(fields.Field):
'''
Used to serialize and deserialize mongodb ObjectId with marshmallow
'''
def _deserialize(self, value, attr, data, **kwargs):
try:
return bson.ObjectId(value)
except Exception:
raise ValidationError("invalid ObjectId `%s`" % value)
def _serialize(self, value, attr, obj, **kwargs):
if value is None:
return ''
return str(value)
in the @other_responses
decorator i can only specify string description but not the whole response body, that is only supported for the primary response.
Would be nice if i could also specify the other responses more closely so the user knows what data to expect even on failure.
I installed apifairy using pip
and wrote a simple flask app. Afterwards, when i put a get request in localhost/docs
it throws an error
raise TemplateNotFound(template)
when i looked in apifary source folder inside virtualenv (for me it's venv/lib/python3.7/site-packages/apifairy
)
i couldn't find templates
folder in there
to solve this error i manually have to download templates folder from github and placed it in there it works fine
Is it possible to use both documentation format (swagger_ui and redoc) at the same time? How do I do it?
I would like to have them both in different ports of course.
Hello, not sure Im asking this correctly. Is it possible to disable or hide the "SCHEMAS" section of the docs? I want to keep only the Endpoints.
when APIFAIRY_APISPEC_PATH
is set to None
the UI can not render as it needs to have apifairy.json
endpoint defined.
the error is as:
[...]
File "[...]/apifairy/templates/apifairy/redoc.html", line 17, in top-level template code
<redoc spec-url="{{ url_for('apifairy.json') }}"></redoc>
[...]
werkzeug.routing.BuildError: Could not build url for endpoint 'apifairy.json'. Did you mean 'apifairy.docs' instead?
could be easily fixed by checking whether the API spec endpoint is enabled or not.
This is a requirement we had in our team where we have a different set of responses (thus multiple schemas) for a given endpoint. I tried marshmallow-oneofschema but that does not seem to work. Any thoughts on this?
Hi Miguel, I am working on a project and I decided to use APIFairy for documentation. Every time i make changes to the application while running the application with gunicorn, the changes are not reflect for the APIFairy_title and version in the config file. My compose file configuration;
build: .
command: gunicorn --bind 0.0.0.0:5000 --access-logfile - --reload "run:app"
ports:
- "5000:5000"
restart: always
env_file:
- .env.dev
volumes:
- .:/usr/src/app
depends_on:
- db
- celery```
My config file;
`
# apifairy documentation
APIFAIRY_TITLE = 'User Service API'
APIFAIRY_VERSION = '1.0'
`
Whenever I run it without using gunicorn, the changes are reflected in the doc on web browser.
Is this possible at all?
I want to add a comment with explicit instructions for the query params, along with, possibly, extra information for each individual parameter.
Thoughts:
OpenAPI 3 specs have:
description
field for the Parameter Object
which could house the comments for each parameter. It does, however, say it should be brief.Operation Object
has a "description" field which could hold the overall description of the params. Currently you are only populating the "summary" field. It the specs it says:A verbose explanation of the operation behavior. [CommonMark syntax](https://spec.commonmark.org/) MAY be used for rich text representation.
as i'm sure you know - I found this information all here.
Issue #23 does say it was implemented using blueprints. However it does not say how to fix (if required) the default generated documentation.
Assuming we have two blueprints (V1
and V2
) is there a way, on the documentation of the API not to name the endpoint with the version prefix eg endpoint_1
instead of v2_endpoint_1
?
I need you help If I can.
I am working on a project for api.
I am using apifairy for your reference.
It is very good and simple.
The company wants me to display a data in a format
return Response({
'result': plants_schema.dump(plants.items),
'pagination':{
'count':plants.total,
'pages':plants.pages,
'page':plants.page,
# 'per_page':plants.per_page,
# 'has_next':plants.has_next,
# 'has_prev':plants.has_prev,
},
'message':"Plants retrieved successfully!"
}), status=200)
I now can't to add pagination to my schema
{
"arrival_date": "2022-09-17 20:36Z",
"id": 1,
"location": "cairo",
"name": "honda",
"package": "yes",
"price": 50.0,
"quantity": 12,
"status": "active",
"total_quantity": 40,
"type": "seeds"
},
I tried to follow your pagination decorator in microblog api
but I am in a trouble.
It is a high level and I can't understand well. and I am using sqlalchemy model
If I could ask, If there a simple way for me I could use to solve this problem.
sorry for some unclarifications.
Originally posted by @Muhammad-Nasr in #49 (comment)
How would you go about implementing pagination links for an endpoint?
Let's say I have this endpoint: /api/users
from apifairy import arguments
class PaginationSchema(ma.Schema):
page = ma.Int(missing=1)
per_page = ma.Int(missing=10)
class UserSchema(ma.Schema):
id = ma.Int()
username = ma.Str(required=True)
email = ma.Str(required=True)
@app.route('/api/users/')
@arguments(PaginationSchema)
@response(UserSchema(many=True))
def get_users(pagination, id):
page = pagination['page']
per_page = pagination['per_page']
return User.query.paginate(page, per_page, False).items
My goal is to have pagination links in my response, something like this:
'_links': {
'next': '/api/users?page=3,
'prev': '/api/users?page=1
}
Hi,
I notice that when I use @body(MyObjSchema)
, and then use the schema generated by APIFairy to generate a python client, I'm getting definitions like: def my_operation(request_body=Optional[MyObj] = None)
instead of my intended my_operation(request_body=MyObj)
.
The OpenAPI 3 Request Body Object has an optional parameter, required
, which defaults to false.
APIFairy doesn't set this parameter, hence the extra qualifier.
Here is the code that generates the Request Body Object:
if view_func._spec.get('body'):
operation['requestBody'] = {
'content': {
'application/json': {
'schema': view_func._spec['body'],
}
}
}
Would it be possible to add an option to the body decorator to feed through to this part of the API generator?
i would love to expose the API documentation out, but only for authenticated users.
currently hacked it around like this
import apifairy as apifairy_module
template_folder = os.path.join(os.path.dirname(apifairy_module.__file__), 'templates')
apifairy_bp = Blueprint('apifairy', 'apifairy', template_folder=template_folder)
@apifairy_bp.route('/docs/api.json', endpoint='json') # dont actually care about json, just need the endpoint
@login_required
def apifairy_docs():
return dumps(apifairy.apispec), 200, {'Content-Type': 'application/json'}
@apifairy_bp.route('/docs/api', endpoint='docs')
@login_required
def apifairy_docs():
# noinspection PyUnresolvedReferences
return render_template(f'apifairy/{apifairy.ui}.html', title=apifairy.title, version=apifairy.version)
app.register_blueprint(apifairy_bp)
it would be nice, if the render functions json
and doc
from APIFairy.create_app
were exposed (even as underscore functions) so they could be used from the outside to add the required authentication, caching and so on.
I would like to add login to the apifairy.docs
so that only allowed/logged on users can access the documentation for my API.
I had tried adding @login_required on
@app.route('/')
@login_required
def index():
return redirect(url_for('apifairy.docs'))
but this couldn't find the set url on the login.login_view = "dev_auth.login"
What could be a better away to achive this as this is my first major API project and can't seem to find a work around
Hey @miguelgrinberg great work on this lib I'm a big fan
I'm fast scaffolding an API and I think it would be useful if the body decorator could return just the request.data
like:
@controller.post("/create/<string:UUID>")
@body()
@response(some_schema)
@other_responses(
{400: "dashboard creation failed", 404: "dashboard template not found"}
)
def create_uuid(json_body,UUID)
bla bla
bla bla
I think It would be useful not only for fast scaffolding but for writing test tests also
of course I could be getting body the old way in the function but I will need to change the function footprint when adding @Body(schema) decorator
Thanks in advance!
I've also made a sort of minimalistic API framework using Flask, Marshmallow, and OpenAPI, thought you might be interested: https://github.com/alexmojaki/instant_api
As the @response decorator can`t aceept response objects, how can I create a route thats uses the set_cookie() function, and also has the @response decorator?
@api.route("/foo")
@response(BarSchema)
def foo(bar):
data = bar.get("foo")
token = "123"
response = jsonify(data)
response.set_cookie(
"fooToken",
token,
secure=False,
httponly=True,
samesite="Strict",
path="/api/foo/tokens",
)
return response
This code return error:
The @response decorator cannot handle Response objects.
After uploading an apispec
file generated through APIFairy
to Stoplight
it does warn that the info
block is missing the contact
object.
Looking at the OpenAPI (Swagger) spec such block is not mandatory.
Even minding this is not mandatory, would this something of added value to be added to config variables of APIFairy
?
And if yes, would termsOfService
and license
also be adding value?
As this is really my requirement, I'm happy to do a PR with that update.
The servers
property in the docs seems to be generated from the request here. When the docs are served behind a load balancer wherein SSL is terminated, the live url is rendered as http://
which may not be supported depending on the deployment.
Options seem to be:
http://
to https://
based on some config, etcThis may be a feature request but I wanted to verify my reasoning first.
Is there anything missing or incorrect here?
I want to document the Response body in the API documentation of the view function but I can not use the Response decorator since the response is already parsed and using the Response decorator raises the following exception.
RuntimeError: The @response decorator cannot handle Response objects.
To solve the issue, I modified the Response decorator, and instead of raising an Exception when a Response object is encountered, I returned the object.
@wraps(f)
def _response(*args, **kwargs):
rv = f(*args, **kwargs)
if isinstance(rv, Response): # pragma: no cover
#raise RuntimeError(
#'The @response decorator cannot handle Response objects.')
return rv # Returning the response object instead of raising an Exception
This works fine now but is there any better way to do this?
A decorator to add file uploads and forms to swagger documention will be a great to have feature.
Hi,
When I use the @response(UserResponseSchema)
decorator I get the error 'UserResponse' object has no attribute 'jsonify'
.
Am I creating the Schema wrong or is APIFairy looking for a jsonify
which isn't there?
I've tried creating Schemas using just the Marshmallow package and without marshmallow_dataclass but it still doesn't work.
I've created a similar example project (shown below) to the one here response decorator
test_users.py:67 (test_should_get_users_as_snake_case)
client = <FlaskClient <Flask 'src.app'>>
def test_should_get_users_as_snake_case(client):
# act
> response = client.get('/api/users/1?isSnakeCase=true')
test_users.py:70:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
../../venv/lib/python3.9/site-packages/werkzeug/test.py:1127: in get
return self.open(*args, **kw)
../../venv/lib/python3.9/site-packages/flask/testing.py:216: in open
return super().open( # type: ignore
../../venv/lib/python3.9/site-packages/werkzeug/test.py:1072: in open
response = self.run_wsgi_app(request.environ, buffered=buffered)
../../venv/lib/python3.9/site-packages/werkzeug/test.py:943: in run_wsgi_app
rv = run_wsgi_app(self.application, environ, buffered=buffered)
../../venv/lib/python3.9/site-packages/werkzeug/test.py:1229: in run_wsgi_app
app_rv = app(environ, start_response)
../../venv/lib/python3.9/site-packages/flask/app.py:2088: in __call__
return self.wsgi_app(environ, start_response)
../../venv/lib/python3.9/site-packages/flask/app.py:2073: in wsgi_app
response = self.handle_exception(e)
../../venv/lib/python3.9/site-packages/flask/app.py:2070: in wsgi_app
response = self.full_dispatch_request()
../../venv/lib/python3.9/site-packages/flask/app.py:1515: in full_dispatch_request
rv = self.handle_user_exception(e)
../../venv/lib/python3.9/site-packages/flask/app.py:1513: in full_dispatch_request
rv = self.dispatch_request()
../../venv/lib/python3.9/site-packages/flask/app.py:1499: in dispatch_request
return self.ensure_sync(self.view_functions[rule.endpoint])(**req.view_args)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
args = (), kwargs = {'id': 1}, rv = (<Response 47 bytes [200 OK]>, 200)
@wraps(f)
def _response(*args, **kwargs):
rv = f(*args, **kwargs)
if isinstance(rv, Response): # pragma: no cover
raise RuntimeError(
'The @response decorator cannot handle Response objects.')
if isinstance(rv, tuple):
> json = schema.jsonify(rv[0])
E AttributeError: 'UserResponse' object has no attribute 'jsonify'
../../venv/lib/python3.9/site-packages/apifairy/decorators.py:77: AttributeErro
routes/users.py
from http import HTTPStatus
from flask import Blueprint, jsonify
from flask import request
from apifairy import body, response, other_responses, arguments
from src.config import DefaultConfig
from src.requests.user import CreateUserRequestSchema, CreateUserRequest, GetUserRequest, GetUserRequestSchema
from src.responses.user import UserResponseSchema
from src.dtos.user import UserDto
from src.services import queue_client
from src.services.pascal_to_snake_serializer import JSONSerializer as ToSnakeJson
from src.services.snake_to_pascal_serializer import JSONSerializer as ToPascalJson
@users_api.route('users/<int:id>', methods=['GET'])
@response(UserResponseSchema, HTTPStatus.OK.value, "Get Users")
@arguments(GetUserRequestSchema())
def get_all_users(get_user_request: GetUserRequest, id: int):
if request.method == 'GET':
user = UserDto(user_name=DefaultConfig.DEFAULT_USERNAME)
if get_user_request.isSnakeCase:
return jsonify(user), 200
serialized = ToPascalJson.serialize(user)
return jsonify(serialized), 200
responses/users.py
from dataclasses import field, dataclass
from typing import List
import marshmallow_dataclass
from marshmallow import Schema
@dataclass
class UserResponse:
UserName: str
UserResponseSchema = marshmallow_dataclass.class_schema(UserResponse, base_schema=Schema)
services/snake_to_pascal_serializer.py
from dataclasses_serialization.serializer_base import noop_serialization, noop_deserialization, dict_serialization, \
dict_deserialization, list_deserialization, Serializer
def snake_to_pascal_case(obj):
parts = iter(obj.split("_"))
return "".join(i.title() for i in parts)
def snake_to_pascal_case_list_map(obj):
obj_dict = obj.__dict__
key = next(iter(obj_dict))
parts = iter(key.split('_'))
new_key = "".join(i.title() for i in parts)
return {new_key: obj_dict.get(key)}
JSONSerializer = Serializer(
serialization_functions={
dict: lambda dct: dict_serialization(dct, key_serialization_func=snake_to_pascal_case,
value_serialization_func=JSONSerializer.serialize),
list: lambda lst: list(map(snake_to_pascal_case_list_map, lst)),
(str, int, float, bool, type(None)): noop_serialization
},
deserialization_functions={
dict: lambda cls, dct: dict_deserialization(cls, dct, key_deserialization_func=JSONSerializer.deserialize,
value_deserialization_func=JSONSerializer.deserialize),
list: lambda cls, lst: list_deserialization(cls, lst, deserialization_func=JSONSerializer.deserialize),
(str, int, float, bool, type(None)): noop_deserialization
}
)
Actual:
Current implementation only works with basic auth and the decorator authentication specifically uses flask_httpauth.
Expected:
The authentication decorator should provide option to use jwt token validation
For routes to be protected in my application, I created a middleware and added it to my app.
$ app = Flask(__name__)
$ ...
$ app.wsgi_app = AuthMiddleware(app.wsgi_app)
$ ...
However, this way it is not documented in the API that needs to be authenticated. For this I need to put the @authenticate(handler)
notation in each route, but will I have to pass the handler to verify the token, in each route. Is there no way to use my middleware, without having to check each route?
I see in APIFairy another variant of SQLAlchemy is being used; Alchemical. How do I set Flask Session to use Alchemical DB with APIFairy since Flask Session has already predifined SESSION_TYPEs which are:
null: NullSessionInterface (default)
redis: RedisSessionInterface
memcached: MemcachedSessionInterface
filesystem: FileSystemSessionInterface
mongodb: MongoDBSessionInterface
sqlalchemy: SqlAlchemySessionInterface
Hi Miguel,
basically the title.
The workariund of using @auth.login_required
from Flask-HTTPAuth is fine, but it doesn't appear in the API documentation.
Thanks,
Horia
Hi @miguelgrinberg I see in the core file there's support for multiple Server URLs or if I am mistaken with this line
# servers
servers = [{'url': request.url_root}]
How do I set the second URL for instance if I want to set a sandbox and live server URL.
Hi Miguel, I am working on a project and I decided to use APIFairy for documentation. Here is an example.
I have this schema for input and output for my endpoint and I use arguments
decorator to describe input and output:
class MyModel(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String())
class MySchema(ma.SQLAlchemySchema):
class Meta:
model = MyModel
load_instance = True
include_fk = True
id = ma.auto_field()
title = ma.auto_field()
And I define my endpoint:
@bp.route("/index", methods=["POST"])
@arguments(MySchema, location="form")
@response(MySchema)
def index(x):
print(x)
return x
After I run server, apifairy.docs
works as usually but I don't see input describe for Request.
I don't know how to config it, please help me!
Screenshot for @arguments(MySchema, location="form")
(No describe for Request, works fine with location="query"
)
Hi @miguelgrinberg ,
Do we support documenting headers? I looked at the documentation but could not find the information.
APIFairy will create multiple endpoints if multiple methods are given. What is the best way to document the multiple methods?
Is APIFairy database agnostic? Or does it need to be used with Alchemical or (Flask-)SQLAlchemy?
Thanks
Some your code isn't support for the new android version i.e., Android 11 & 12 .I'm unable to use your codes in this new versions .
I'm not understanding what is happening. I created a folder for each module, I have two modules that have one to one relationship. The problem is that in the documentation APIFairy is putting more than one schema for the User and for the Project.
What is User1 and Project1 ?
I have only these classes: class UserSchema(ma.SQLAlchemySchema)
and class ProjecSchema(ma.SQLAlchemySchema)
UserSchema have this:
from app.modules.project.schema import ProjecSchema
...
default_project = ma.Nested(
ProjecSchema(only=("id", "tfs_id", "tfs_description")), many=False
)
If we want the docs
blueprint
secure behind a login / password (for a private/non-public API), other than a total override of the core.py
init_app
is there a better way to override that blueprint and add a decorator to it?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.