flask extension for integration with the awesome pydantic package

Overview

Flask-Pydantic

Actions Status PyPI Language grade: Python License Code style

Flask extension for integration of the awesome pydantic package with Flask.

Installation

python3 -m pip install Flask-Pydantic

Basics

URL query and body parameters

validate decorator validates query and body request parameters and makes them accessible two ways:

  1. Using validate arguments, via flask's request variable
parameter type request attribute name
query query_params
body body_params
  1. Using the decorated function argument parameters type hints

URL path parameter

If you use annotated path URL path parameters as follows

@app.route("/users/<user_id>", methods=["GET"])
@validate()
def get_user(user_id: str):
    pass

flask_pydantic will parse and validate user_id variable in the same manner as for body and query parameters.


Additional validate arguments

  • Success response status code can be modified via on_success_status parameter of validate decorator.
  • response_many parameter set to True enables serialization of multiple models (route function should therefore return iterable of models).
  • request_body_many parameter set to False analogically enables serialization of multiple models inside of the root level of request body. If the request body doesn't contain an array of objects 400 response is returned,
  • get_json_params - parameters to be passed to flask.Request.get_json function
  • If validation fails, 400 response is returned with failure explanation.

For more details see in-code docstring or example app.

Usage

Example 1: Query parameters only

Simply use validate decorator on route function.

Be aware that @app.route decorator must precede @validate (i. e. @validate must be closer to the function declaration).

from typing import Optional
from flask import Flask, request
from pydantic import BaseModel

from flask_pydantic import validate

app = Flask("flask_pydantic_app")

class QueryModel(BaseModel):
  age: int

class ResponseModel(BaseModel):
  id: int
  age: int
  name: str
  nickname: Optional[str]

# Example 1: query parameters only
@app.route("/", methods=["GET"])
@validate()
def get(query: QueryModel):
  age = query.age
  return ResponseModel(
    age=age,
    id=0, name="abc", nickname="123"
    )
See the full example app here
  • age query parameter is a required int
    • curl --location --request GET 'http://127.0.0.1:5000/'
    • if none is provided the response contains:
      {
        "validation_error": {
          "query_params": [
            {
              "loc": ["age"],
              "msg": "field required",
              "type": "value_error.missing"
            }
          ]
        }
      }
    • for incompatible type (e. g. string /?age=not_a_number)
    • curl --location --request GET 'http://127.0.0.1:5000/?age=abc'
      {
        "validation_error": {
          "query_params": [
            {
              "loc": ["age"],
              "msg": "value is not a valid integer",
              "type": "type_error.integer"
            }
          ]
        }
      }
  • likewise for body parameters
  • example call with valid parameters: curl --location --request GET 'http://127.0.0.1:5000/?age=20'

-> {"id": 0, "age": 20, "name": "abc", "nickname": "123"}

Example 2: URL path parameter

@app.route("/character/<character_id>/", methods=["GET"])
@validate()
def get_character(character_id: int):
    characters = [
        ResponseModel(id=1, age=95, name="Geralt", nickname="White Wolf"),
        ResponseModel(id=2, age=45, name="Triss Merigold", nickname="sorceress"),
        ResponseModel(id=3, age=42, name="Julian Alfred Pankratz", nickname="Jaskier"),
        ResponseModel(id=4, age=101, name="Yennefer", nickname="Yenn"),
    ]
    try:
        return characters[character_id]
    except IndexError:
        return {"error": "Not found"}, 400

Example 3: Request body only

class RequestBodyModel(BaseModel):
  name: str
  nickname: Optional[str]

# Example2: request body only
@app.route("/", methods=["POST"])
@validate()
def post(body: RequestBodyModel): 
  name = body.name
  nickname = body.nickname
  return ResponseModel(
    name=name, nickname=nickname,id=0, age=1000
    )
See the full example app here

Example 4: BOTH query paramaters and request body

# Example 3: both query paramters and request body
@app.route("/both", methods=["POST"])
@validate()
def get_and_post(body: RequestBodyModel,query: QueryModel):
  name = body.name # From request body
  nickname = body.nickname # From request body
  age = query.age # from query parameters
  return ResponseModel(
    age=age, name=name, nickname=nickname,
    id=0
  )
See the full example app here

Modify response status code

The default success status code is 200. It can be modified in two ways

  • in return statement
# necessary imports, app and models definition
...

@app.route("/", methods=["POST"])
@validate(body=BodyModel, query=QueryModel)
def post():
    return ResponseModel(
            id=id_,
            age=request.query_params.age,
            name=request.body_params.name,
            nickname=request.body_params.nickname,
        ), 201
  • in validate decorator
@app.route("/", methods=["POST"])
@validate(body=BodyModel, query=QueryModel, on_success_status=201)
def post():
    ...

Status code in case of validation error can be modified using FLASK_PYDANTIC_VALIDATION_ERROR_STATUS_CODE flask configuration variable.

Using the decorated function kwargs

Instead of passing body and query to validate, it is possible to directly defined them by using type hinting in the decorated function.

# necessary imports, app and models definition
...

@app.route("/", methods=["POST"])
@validate()
def post(body: BodyModel, query: QueryModel):
    return ResponseModel(
            id=id_,
            age=query.age,
            name=body.name,
            nickname=body.nickname,
        )

This way, the parsed data will be directly available in body and query. Furthermore, your IDE will be able to correctly type them.

Model aliases

Pydantic's alias feature is natively supported for query and body models. To use aliases in response modify response model

def modify_key(text: str) -> str:
    # do whatever you want with model keys
    return text


class MyModel(BaseModel):
    ...
    class Config:
        alias_generator = modify_key
        allow_population_by_field_name = True

and set response_by_alias=True in validate decorator

@app.route(...)
@validate(response_by_alias=True)
def my_route():
    ...
    return MyModel(...)

Example app

For more complete examples see example application.

Configuration

The behaviour can be configured using flask's application config FLASK_PYDANTIC_VALIDATION_ERROR_STATUS_CODE - response status code after validation error (defaults to 400)

Contributing

Feature requests and pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.

  • clone repository
    git clone https://github.com/bauerji/flask_pydantic.git
    cd flask_pydantic
  • create virtual environment and activate it
    python3 -m venv venv
    source venv/bin/activate
  • install development requirements
    python3 -m pip install -r requirements/test.pip
  • checkout new branch and make your desired changes (don't forget to update tests)
    git checkout -b <your_branch_name>
  • run tests
    python3 -m pytest
  • if tests fails on Black tests, make sure You have your code compliant with style of Black formatter
  • push your changes and create a pull request to master branch

TODOs:

  • header request parameters
  • cookie request parameters
Comments
  • Flask Get Request validate failed

    Flask Get Request validate failed

    from pydantic import BaseModel
    from typing import List
    class Query(BaseModel):
        query: str
        
    @test_bp.route("/test_route")
    @validate(query=Query)
    def test_route(query:Query):
        return {}
    

    my code is very simple, but when i send 'http://127.0.0.1:8800/test_route?query=1',I will receive

    {
      "validation_error": {
        "query_params": [
          {
            "loc": [
              "query"
            ], 
            "msg": "str type expected", 
            "type": "type_error.str"
          }
        ], 
      }
    }
    

    I try add more detail in core.py

    try:
                        q = query_model(**query_params)
                    except ValidationError as ve:
                        err["query_params"] = ve.errors()
                        err["value"] = query_params
    

    I will get

    "value": {
          "query": [
            "1"
          ]
        }
    

    So I'm very doubt why query becomes list rather than str.

    My python requrement is

    python3.6
    pydantic==1.7.3
    flask-pydantic-spec==0.1.3
    Flask==1.1.2
    dataclasses==0.8
    

    Looking forward to a reply!

    opened by CharmingZhou 10
  • match flask pattern to return extra headers

    match flask pattern to return extra headers

    Technically Flask allows you to return from a route with a tuple of 3 items with the last item being a dictionary of headers. The docs mention it here: https://flask.palletsprojects.com/en/1.1.x/quickstart/#about-responses This adjusts the behavior of the validate decorator to allow this as well. Matches the behavior in: https://github.com/pallets/flask/blob/64213fc0214c1044fa2c9e60d0e2683e75d125c0/src/flask/app.py#L1644-L1646

    opened by cardoe 9
  • Dealing with Query Param Arrays

    Dealing with Query Param Arrays

    Another question - how would I go about validating query param arrays?

    For example I have code like this:

    response = test_client.get("/api/v1/services", query_string={"ids[]": ["5f03539f9472e7f1a153797d"]})
    
    assert response.status_code == 200
    
    @services_bp.route("", methods=["GET"], strict_slashes=False)
    @validate(query=GetObjectIds)
    def get_services():
        """
        Retrieves list of all services
        """
        data = request.args.getlist("ids[]")
    
        if not data:
            services = service_db.all_services()
        else:
            services = service_db.get_services([x for x in data])
    
        if len(services) > 0:
            return jsonify([service.dict() for service in services])
        else:
            return jsonify(error="No services found with requested ids"), 404
    

    I'd like to be able to have a model that says "validate that the get query correctly contains an id of lists."

    opened by jhoover4 8
  • Model.json() vs jsonify

    Model.json() vs jsonify

    Hello,

    Thanks for the app! We were beginning to play around with it and wondering if the returned json could be wrapped in jsonify or if there is an advantage to not to. We have our jsonify set just right to play nice with Mongo, etc., so we wanted to make sure we didn't lose any of its advantages.

    Thanks!

    opened by jhoover4 5
  • allow custom error responses to be generated

    allow custom error responses to be generated

    By defining a new config value that flask_pydantic looks for (FLASK_PYDANTIC_VALIDATION_ERROR_RAISE), we can support raising an exception when we have a validation error. If that is set and the exception is raised, by default, Flask will respond with a 500 error. However, by coupling that feature with Flask.register_error_handler, the user can catch the thrown exception and return whatever custom error response the user wishes. Fixes https://github.com/bauerji/flask-pydantic/issues/45.

    opened by jcreekmore 4
  • Add kwargs parsing

    Add kwargs parsing

    This PR is implementing solution 2 of #12.

    @bauerji like I said in the issue I already implemented a solution, so this is the PR.

    I am, of course, still open to discuss the different solutions !

    opened by adriencaccia 4
  • Overriding http return stats on exception

    Overriding http return stats on exception

    I notice that you can update the returned status on success, but can you do the same thing on error? We typically use 422s instead of 400s for malformed requests.

    Thanks!

    opened by jhoover4 4
  • ignore return-type annotations

    ignore return-type annotations

    This fixes an issue where any function with return-type annotations will get processed through parse_obj_as, and inevitably throw a validation exception, which will be returned as a very confusing error message where the "loc" property is "return".

    opened by laanak08 3
  • Request change: the example in the main README.md file is not clear

    Request change: the example in the main README.md file is not clear

    Before I start, I really thank you so much for this package.


    I request to make a change: The example at the README.md file in the main page of the package is not clear. At first, I thought that the package was not working correctly. I kept working, and sending requests till finally worked after about 15 minutes of trying.


    For this reason: The example is very advanced, and for someone who wanna learn the package for the first time, the learning curve of the example is very hard to learn. This is dangerous for someone who wants to learn about the package for the first time.


    So I would like to solve this problem by doing this. Create 3 separate endpoints:

    1. To read the GET request only, and above it the pydantic class of it.
    2. To read the JSON request body only, and above it the pydantic class of it.
    3. To read both the JSON request and the GET request together, using the old pydantic classes.

    If God willed, I can make this change. I will make these changes, If you give the permission. Thank you!

    opened by OmarThinks 3
  • Validation for Array of Models fails

    Validation for Array of Models fails

    from typing import List
    from flask_pydantic import validate
    
    api = Blueprint("lineage-collector", __name__)
    
    class EntityPayload(BaseModel):
        attributes: dict
        typeName: str
    
    class EntityPayloadBulk(BaseModel):
        __root__:  List[EntityPayload]
    
    @api.route('/entity/bulk', methods=["POST"])
    @validate()
    def entity_bulk(body: EntityPayloadBulk):
        return "Hello World"
    
    

    Call to this endpoint returns the following error:

    ` File "/usr/local/lib/python3.9/site-packages/flask_pydantic/core.py", line 158, in wrapper b = body_model(**body_params) TypeError: api.routes.EntityPayloadBulk() argument after ** must be a mapping, not list

    During handling of the above exception, another exception occurred:

    Traceback (most recent call last): File "/usr/local/lib/python3.9/site-packages/flask/app.py", line 2464, in call return self.wsgi_app(environ, start_response) File "/usr/local/lib/python3.9/site-packages/flask/app.py", line 2450, in wsgi_app response = self.handle_exception(e) File "/usr/local/lib/python3.9/site-packages/flask/app.py", line 1867, in handle_exception reraise(exc_type, exc_value, tb) File "/usr/local/lib/python3.9/site-packages/flask/_compat.py", line 39, in reraise raise value File "/usr/local/lib/python3.9/site-packages/flask/app.py", line 2447, in wsgi_app response = self.full_dispatch_request() File "/usr/local/lib/python3.9/site-packages/flask/app.py", line 1952, in full_dispatch_request rv = self.handle_user_exception(e) File "/usr/local/lib/python3.9/site-packages/flask/app.py", line 1821, in handle_user_exception reraise(exc_type, exc_value, tb) File "/usr/local/lib/python3.9/site-packages/flask/_compat.py", line 39, in reraise raise value File "/usr/local/lib/python3.9/site-packages/flask/app.py", line 1950, in full_dispatch_request rv = self.dispatch_request() File "/usr/local/lib/python3.9/site-packages/flask/app.py", line 1936, in dispatch_request return self.view_functionsrule.endpoint File "/usr/local/lib/python3.9/site-packages/flask_pydantic/core.py", line 164, in wrapper raise JsonBodyParsingError() flask_pydantic.exceptions.JsonBodyParsingError`

    opened by ckwojai 3
  • Is there a way to convert key casing in responses?

    Is there a way to convert key casing in responses?

    I'd like to have my Pydantic models defined in snake_case but have the API return JSON with camelCase fields.

    In FastAPI, I can do the following:

    def to_camel(string: str):
        # returns "string" converted to camelCase
    
    class MyModel(BaseModel):
        foo_bar: str
    
        class Config:
            alias_generator = to_camel
            allow_population_by_field_name = True
    

    And the resulting JSON will be {"fooBar": "x"}. This is similar to the way it's described in the Pydantic docs.

    This doesn't work with flask-pydantic. Is there any way to achieve similar behaviour?

    opened by eboddington 3
  • Aliased list query parameters do not work

    Aliased list query parameters do not work

    flask-pydantic==0.10.0
    flask==2.1.2
    

    Steps to reproduce

    1. Define a query model with an aliased list field.
    class QueryModel(BaseModel):
        order_by: Optional[
            List[Literal["created", "name"]]
        ] = Field(..., alias="order-by")
    
        class Config:
            allow_population_by_field_name = True
    
    1. Set this as query: QueryModel in your request handler function signature.
    2. Send a request with ?order-by=name

    Expected result

    • The request should be considered valid.
    • query.order_by should be a list ['name'].

    Actual result

    {
      "validation_error": {
        "query_params": [
          {
            "loc": [
              "order-by"
            ], 
            "msg": "value is not a valid list", 
            "type": "type_error.list"
          }
        ]
      }
    }
    

    In short:

    • Aliased query params work.
    • List query params work (e.g. ?order_by=name&order_by=created gives you list with these values).
    • Aliased list query params do not work.
    opened by janibonnevier 0
  • Why doesn't the `make_json_response` function have a default value for the `by_alias` argument?

    Why doesn't the `make_json_response` function have a default value for the `by_alias` argument?

    def make_json_response(
        content: Union[BaseModel, Iterable[BaseModel]],
        status_code: int,
        by_alias: bool,
        exclude_none: bool = False,
        many: bool = False,
    ) -> Response:
        ...
            js = content.json(exclude_none=exclude_none, by_alias=by_alias)
        ...
    

    The content.json method has a default value for the by_alias argument.

    opened by NiKuma0 0
  • Error if validation error contains enum.Enum

    Error if validation error contains enum.Enum

    This error is occurring for me when the body of an endpoint receives a pydantic.BaseModel that contains a field of type Enum and the validation fail, the error message returned is a JSON serialization error instead of a ValidationError.

    Example validation that fail correctly:

    from flask import Flask
    from flask_pydantic import validate
    from pydantic import BaseModel, validator
    
    app = Flask(__name__)
    
    
    class RequestBody(BaseModel):
        format: str
    
    
    
    @app.route("/", methods=["POST"])
    @validate()
    def export(body: RequestBody):
        print(body.format)
        return f"{body.format}"
    
    
    if __name__ == '__main__':
        app.config["TESTING"] = True
        client = app.test_client()
    
        valid_data = {"format": "csv"}
        invalid_data = {"format": [123,123]}
    
        valid_response = client.post("/", json=valid_data)
        print(valid_response.json)
    
        invalid_response = client.post("/", json=invalid_data)
        print(invalid_response.json)
    
    

    response:

    csv
    None
    {'validation_error': {'body_params': [{'loc': ['format'], 'msg': 'str type expected', 'type': 'type_error.str'}]}}
    

    the response details why the validation fails

    Example validation that fails with a JSON serialization error because of an Enum:

    from enum import Enum
    
    from flask import Flask
    from flask_pydantic import validate
    from pydantic import BaseModel
    
    app = Flask(__name__)
    
    
    class Formats(Enum):
        CSV = "csv"
        HTML = "html"
    
    
    class RequestBody(BaseModel):
        format: Formats = Formats.CSV
    
    
    @app.route("/", methods=["POST"])
    @validate()
    def export(body: RequestBody):
        return f"{body.format}"
    
    
    if __name__ == '__main__':
        app.config["TESTING"] = True
        client = app.test_client()
    
        valid_data = {"format": "csv"}
        invalid_data = {"format": "notcsv"}
    
        valid_response = client.post("/", json=valid_data)
        print(valid_response.json)
        invalid_response = client.post("/", json=invalid_data)
        print(invalid_response.json)
    
    

    response (with stack trace):

    Traceback (most recent call last):
      File "/Users/bruno/Developer/flask_pydantic_error/main.py", line 34, in <module>
        invalid_response = client.post("/", json=invalid_data)
      File "/Users/bruno/Developer/flask_pydantic_error/venv/lib/python3.10/site-packages/werkzeug/test.py", line 1140, in post
        return self.open(*args, **kw)
      File "/Users/bruno/Developer/flask_pydantic_error/venv/lib/python3.10/site-packages/flask/testing.py", line 217, in open
        return super().open(
      File "/Users/bruno/Developer/flask_pydantic_error/venv/lib/python3.10/site-packages/werkzeug/test.py", line 1089, in open
        response = self.run_wsgi_app(request.environ, buffered=buffered)
      File "/Users/bruno/Developer/flask_pydantic_error/venv/lib/python3.10/site-packages/werkzeug/test.py", line 956, in run_wsgi_app
        rv = run_wsgi_app(self.application, environ, buffered=buffered)
      File "/Users/bruno/Developer/flask_pydantic_error/venv/lib/python3.10/site-packages/werkzeug/test.py", line 1237, in run_wsgi_app
        app_rv = app(environ, start_response)
      File "/Users/bruno/Developer/flask_pydantic_error/venv/lib/python3.10/site-packages/flask/app.py", line 2091, in __call__
        return self.wsgi_app(environ, start_response)
      File "/Users/bruno/Developer/flask_pydantic_error/venv/lib/python3.10/site-packages/flask/app.py", line 2076, in wsgi_app
        response = self.handle_exception(e)
      File "/Users/bruno/Developer/flask_pydantic_error/venv/lib/python3.10/site-packages/flask/app.py", line 2073, in wsgi_app
        response = self.full_dispatch_request()
      File "/Users/bruno/Developer/flask_pydantic_error/venv/lib/python3.10/site-packages/flask/app.py", line 1519, in full_dispatch_request
        rv = self.handle_user_exception(e)
      File "/Users/bruno/Developer/flask_pydantic_error/venv/lib/python3.10/site-packages/flask/app.py", line 1517, in full_dispatch_request
        rv = self.dispatch_request()
      File "/Users/bruno/Developer/flask_pydantic_error/venv/lib/python3.10/site-packages/flask/app.py", line 1503, in dispatch_request
        return self.ensure_sync(self.view_functions[rule.endpoint])(**req.view_args)
      File "/Users/bruno/Developer/flask_pydantic_error/venv/lib/python3.10/site-packages/flask_pydantic/core.py", line 212, in wrapper
        return make_response(jsonify({"validation_error": err}), status_code)
      File "/Users/bruno/Developer/flask_pydantic_error/venv/lib/python3.10/site-packages/flask/json/__init__.py", line 302, in jsonify
        f"{dumps(data, indent=indent, separators=separators)}\n",
      File "/Users/bruno/Developer/flask_pydantic_error/venv/lib/python3.10/site-packages/flask/json/__init__.py", line 132, in dumps
        return _json.dumps(obj, **kwargs)
      File "/Users/bruno/.pyenv/versions/3.10.3/lib/python3.10/json/__init__.py", line 238, in dumps
        **kw).encode(obj)
      File "/Users/bruno/.pyenv/versions/3.10.3/lib/python3.10/json/encoder.py", line 199, in encode
        chunks = self.iterencode(o, _one_shot=True)
      File "/Users/bruno/.pyenv/versions/3.10.3/lib/python3.10/json/encoder.py", line 257, in iterencode
        return _iterencode(o, 0)
      File "/Users/bruno/Developer/flask_pydantic_error/venv/lib/python3.10/site-packages/flask/json/__init__.py", line 51, in default
        return super().default(o)
      File "/Users/bruno/.pyenv/versions/3.10.3/lib/python3.10/json/encoder.py", line 179, in default
        raise TypeError(f'Object of type {o.__class__.__name__} '
    TypeError: Object of type Formats is not JSON serializable
    None
    

    When I was expecting an response of type:

    csv
    None
    {'validation_error': {'body_params': [{'ctx': {'enum_values': ['csv', 'html']}, 'loc': ['format'], 'msg': "value is not a valid enumeration member; permitted: 'csv', 'html'", 'type': 'type_error.enum'}]}}
    

    It seems like the flask's JSONEncoder is used instead of std json. If I modify flask.json.JSONEncoder's default method in order to add:

    if isinstance(o, Enum):
        return o.value
    

    the program functions as expected.

    opened by bruno-robert 2
  • how to use flask getlist mothed

    how to use flask getlist mothed

    if my query string is

    http://url?a[]=1&a[]=2&a[]=3
    

    i want the get the a value is a = [1, 2, 3]

    can i use the query: useModel realize it ?

    class useModel(BaseModel):
        a: List = Field([]) 
    

    is not working

    opened by fainle 0
  • Question: partially populated nested object with required fields

    Question: partially populated nested object with required fields

    Hey all,

    I am trying to understand if the behavior I am seeing is expected, a bug or misconfiguration of my setup.

    The following code uses. Flask-Pydantic = "~=0.9.0"

    There's an endpoint that expects the following simple payload. The address is expected to be fully populated (all fields are required).

    class Address(BaseModel):
        street: str
        city: str
        region: str
        zipcode: str
    
    class Payload(BaseModel):
        username: str
        address: Optional[Address] = None
    
        @root_validator
        def validate_address(cls, values):
            # address is missing from values for partially populated address fields
            if "address" not in values or not values["address"]:
                raise ValueError(f"Full address is required")
            return values
    
    

    This works nicely for fully populated address and when the address is missing in the request (set to None by default).

    However, when I send a partially-populated Address, the field address is missing from the payload :

    Request payload :

    {
    "username": "foo",
    "address": {
                "zipcode": "10001",
            },
        }
    

    flask body:

    { 'username': 'foo' }
    

    Is that expected that when a pydantic object fails to create, it will be dropped ?

    opened by jakubczaplicki 0
Owner
null
Flask-Bcrypt is a Flask extension that provides bcrypt hashing utilities for your application.

Flask-Bcrypt Flask-Bcrypt is a Flask extension that provides bcrypt hashing utilities for your application. Due to the recent increased prevelance of

Max Countryman 282 Feb 11, 2021
flask-apispec MIT flask-apispec (🥉24 · ⭐ 520) - Build and document REST APIs with Flask and apispec. MIT

flask-apispec flask-apispec is a lightweight tool for building REST APIs in Flask. flask-apispec uses webargs for request parsing, marshmallow for res

Joshua Carp 617 Dec 30, 2022
Flask Sitemapper is a small Python 3 package that generates XML sitemaps for Flask applications.

Flask Sitemapper Flask Sitemapper is a small Python 3 package that generates XML sitemaps for Flask applications. This allows you to create a nice and

null 6 Jan 6, 2023
Socket.IO integration for Flask applications.

Flask-SocketIO Socket.IO integration for Flask applications. Installation You can install this package as usual with pip: pip install flask-socketio

Miguel Grinberg 4.9k Jan 2, 2023
Socket.IO integration for Flask applications.

Flask-SocketIO Socket.IO integration for Flask applications. Installation You can install this package as usual with pip: pip install flask-socketio

Miguel Grinberg 4.1k Feb 17, 2021
Flask webassets integration.

Integrates the webassets library with Flask, adding support for merging, minifying and compiling CSS and Javascript files. Documentation: https://flas

Michael Elsdörfer 433 Dec 29, 2022
MongoEngine flask extension with WTF model forms support

Flask-MongoEngine Info: MongoEngine for Flask web applications. Repository: https://github.com/MongoEngine/flask-mongoengine About Flask-MongoEngine i

MongoEngine 815 Jan 3, 2023
A caching extension for Flask

Flask-Caching Adds easy cache support to Flask. This is a fork of the Flask-Cache extension. Flask-Caching also includes the cache module from werkzeu

Peter Justin 774 Jan 2, 2023
Rate Limiting extension for Flask

Flask-Limiter Flask-Limiter provides rate limiting features to flask routes. It has support for a configurable backend for storage with current implem

Ali-Akber Saifee 922 Jan 8, 2023
SeaSurf is a Flask extension for preventing cross-site request forgery (CSRF).

Flask-SeaSurf SeaSurf is a Flask extension for preventing cross-site request forgery (CSRF). CSRF vulnerabilities have been found in large and popular

Max Countryman 183 Dec 28, 2022
A flask extension using pyexcel to read, manipulate and write data in different excel formats: csv, ods, xls, xlsx and xlsm.

Flask-Excel - Let you focus on data, instead of file formats Support the project If your company has embedded pyexcel and its components into a revenu

null 247 Dec 27, 2022
A Flask extension that enables or disables features based on configuration.

Flask FeatureFlags This is a Flask extension that adds feature flagging to your applications. This lets you turn parts of your site on or off based on

Rachel Greenfield 131 Sep 26, 2022
A Flask extension that enables or disables features based on configuration.

Flask FeatureFlags This is a Flask extension that adds feature flagging to your applications. This lets you turn parts of your site on or off based on

Rachel Greenfield 124 Jan 22, 2021
A Flask extension that enables or disables features based on configuration.

Flask FeatureFlags This is a Flask extension that adds feature flagging to your applications. This lets you turn parts of your site on or off based on

Rachel Greenfield 131 Sep 26, 2022
An extension to add support of Plugin in Flask.

An extension to add support of Plugin in Flask.

Doge Gui 31 May 19, 2022
Flask-Rebar combines flask, marshmallow, and swagger for robust REST services.

Flask-Rebar Flask-Rebar combines flask, marshmallow, and swagger for robust REST services. Features Request and Response Validation - Flask-Rebar reli

PlanGrid 223 Dec 19, 2022
Flask-Starter is a boilerplate starter template designed to help you quickstart your Flask web application development.

Flask-Starter Flask-Starter is a boilerplate starter template designed to help you quickstart your Flask web application development. It has all the r

Kundan Singh 259 Dec 26, 2022
Brandnew-flask is a CLI tool used to generate a powerful and mordern flask-app that supports the production environment.

Brandnew-flask is still in the initial stage and needs to be updated and improved continuously. Everyone is welcome to maintain and improve this CLI.

brandonye 4 Jul 17, 2022
Flask Project Template A full feature Flask project template.

Flask Project Template A full feature Flask project template. See also Python-Project-Template for a lean, low dependency Python app. HOW TO USE THIS

Bruno Rocha 96 Dec 23, 2022