flask-restx
repository·master·Indexed 24 days ago
https://github.com/python-restx/flask-restxA community-driven extension for Flask providing a fully featured framework for fast and easy REST API development. It includes built-in Swagger documentation support and core abstractions such as Api, Namespace, and Resource. Key features include data modeling with flask_restx.Model, request parsing via reqparse, and data serialization using marshal and marshal_with.
What's inside flask-restx
- Flask-RESTX is an extension for Flask designed to facilitate the rapid development of REST APIs. It promotes best practices with minimal configuration and provides a suite of decorators and tools to describe your API. A key feature is the automatic exposure of API documentation using Swagger.
Core components: Api, Namespace, and Resource
masterFlask-RESTX is built around three primary core abstractions:
Api: The main entry point used to initialize the extension with a Flask application. It manages the Swagger documentation and global configurations.Namespace: Used to group related routes and resources together. Namespaces allow for modular API design and prefixing routes.Resource: The base class for defining API endpoints. You implement methods likeget(),post(),put(), anddelete()within aResourceclass to handle specific HTTP verbs.
Understand documentation cascading
masterFlask-RESTX follows a specific precedence order for documentation:
- Method documentation takes highest precedence.
- Inherited documentation (from a class) takes precedence over parent documentation.
- Class documentation is applied to all methods unless overridden.
You can also provide method-specific documentation from a class decorator using the
get,post, etc., keys in@api.doc().# Class documentation is overridden by method-specific documentation @api.route('/my-resource/<id>', endpoint='my-resource') @api.param('id', 'Class-wide description') class MyResource(Resource): @api.param('id', 'An ID') def get(self, id): return {} # Providing method-specific documentation via class decorator @api.route('/my-resource/<id>', endpoint='my-resource') @api.params('id', 'Class-wide description') @api.doc(get={'params': {'id': 'An ID'}}) class MyResource(Resource): def get(self, id): return {}Control response output with Response Marshalling
masterFlask-RESTX uses the
fieldsmodule to control which data is rendered in your API responses. This allows you to use any object (ORM models, custom classes, etc.) while filtering and formatting the output to avoid exposing internal data structures.To apply marshalling to a resource method, use the
@api.marshal_with(model)decorator. You can also use anenvelopekeyword argument to wrap the resulting output in a specific key.If you need to return specific HTTP status codes alongside your marshalled data, you can use the
marshal(data, model)function manually instead of the decorator.from flask_restx import Resource, fields model = api.model('Model', { 'name': fields.String, 'address': fields.String, 'date_updated': fields.DateTime(dt_format='rfc822'), }) @api.route('/todo') class Todo(Resource): @api.marshal_with(model, envelope='resource') def get(self, **kwargs): return db_get_todo() # Returns data wrapped in {'resource': ...}Use RequestParser for input validation
masterThe
reqparsemodule provides aRequestParserclass, modeled afterargparse, to provide uniform access to variables on theflask.requestobject.Note: The request parsing interface is slated for removal in version 2.0. It is recommended to migrate to other packages like
marshmallowfor input/output handling. However, it will be maintained until 2.0.By default:
- Arguments are not required.
- Arguments not defined in the parser are ignored.
- Missing arguments default to
None. - The default type is
str(unicode string).
from flask_restx import reqparse parser = reqparse.RequestParser() parser.add_argument('rate', type=int, help='Rate cannot be converted') parser.add_argument('name') args = parser.parse_args()Automatically document models with Namespace methods
masterModels created using
Namespace.model,Namespace.clone, orNamespace.inheritare automatically included in your Swagger specifications. Usingapi.inheritallows you to create child models that inherit properties from a parent, which is represented in Swagger using theallOfkeyword and adiscriminator.parent = api.model('Parent', { 'name': fields.String, 'class': fields.String(discriminator=True) }) child = api.inherit('Child', parent, { 'extra': fields.String })Use Resources for routing
masterResources are the main building blocks of Flask-RESTX. They are built on top of Flask pluggable views. You can define multiple HTTP methods in a single resource class and use path variables in the route.
from flask import Flask, request from flask_restx import Resource, Api app = Flask(__name__) api = Api(app) todos = {} @api.route('/<string:todo_id>') class TodoSimple(Resource): def get(self, todo_id): return {todo_id: todos[todo_id]} def put(self, todo_id): todos[todo_id] = request.form['data'] return {todo_id: todos[todo_id]}How logging works in Flask-RESTX
masterFlask-RESTX extends Flask's logging by providing every
ApiandNamespaceinstance with its own standard Pythonlogging.Loggerinstance. This allows you to separate logging on a per-namespace basis, enabling fine-grained configuration for different parts of your API.By default, these namespace-specific loggers inherit their configuration (such as log levels and handlers) from the main Flask application object logger (
app.logger).import logging import flask from flask_restx import Api, Resource app = flask.Flask(__name__) api = Api(app) ns1 = api.namespace('api/v1') @ns1.route('/resource') class MyResource(Resource): def get(self): ns1.logger.info("message from ns1") return {"status": "ok"}Implement polymorphism with api.inherit
masterTo handle polymorphism in a way that is compatible with Swagger, use the
Model.inheritmethod. This allows you to extend a parent model and define a discriminator field.When using
api.inherit, both the parent and the child are registered in the Swagger models definitions. The field marked withdiscriminator=Truewill be populated with the serialized model name if that property does not already exist in the serialized object.Example:
parent = api.model('Parent', { 'name': fields.String, 'class': fields.String(discriminator=True) }) child = api.inherit('Child', parent, { 'extra': fields.String })You can also use
fields.Polymorphto specify a mapping between Python classes and their corresponding field specifications.Handle Werkzeug HTTPExceptions
masterFlask-RESTX automatically serializes WerkzeugHTTPExceptionobjects using theirdescriptionattribute. You can provide a custom message by passing it to the exception constructor. To include additional fields in the JSON response, attach adataattribute to the exception instance before raising it.Organize large APIs using Namespaces
masterFor large-scale applications, instead of defining everything in a single
Apiobject, useNamespaceto split your API into reusable, logical modules. Each namespace module contains its own models and resources. You then aggregate these namespaces into a centralApiobject usingapi.add_namespace().Key benefits:
- Decoupling: Namespaces can be defined independently of the main API.
- Custom Routing: You can define custom URL prefixes for each namespace when registering them with the main API, rather than hardcoding them in the
Namespacedeclaration.
from flask_restx import Namespace, Resource, fields # 1. Define a Namespace api = Namespace('cats', description='Cats related operations') cat = api.model('Cat', { 'id': fields.String(required=True, description='The cat identifier'), 'name': fields.String(required=True, description='The cat name'), }) # 2. Define Resources within that Namespace @api.route('/') class CatList(Resource): @api.marshal_list_with(cat) def get(self): return [{'id': 'felix', 'name': 'Felix'}] # 3. Aggregate in your main API entry point from flask_restx import Api from .namespace1 import api as ns1 api = Api(title='My Title', version='1.0') api.add_namespace(ns1, path='/prefix/of/ns1')Use fields masks for partial object fetching
masterFlask-RESTX supports partial object fetching (fields masking) by allowing clients to request only specific fields via a custom HTTP header. This reduces payload size by filtering the response to only include the requested data.
By default, the header used is
X-Fields. You can change this header name by setting theRESTX_MASK_HEADERparameter.