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

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

  • 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,
  • 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: 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 3: 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
Lightspin AWS IAM Vulnerability Scanner

Red-Shadow Lightspin AWS IAM Vulnerability Scanner Description Scan your AWS IAM Configuration for shadow admins in AWS IAM based on misconfigured den

Lightspin 90 Dec 14, 2022
Comparing USD and GBP Exchange Rates

Currency Data Visualization Comparing USD and GBP Exchange Rates This is a bar graph comparing GBP and USD exchange rates. I chose blue for the UK bec

5 Oct 28, 2021
HM02: Visualizing Interesting Datasets

HM02: Visualizing Interesting Datasets This is a homework assignment for CSCI 40 class at Claremont McKenna College. Go to the project page to learn m

Qiaoling Chen 11 Oct 26, 2021
Learning Convolutional Neural Networks with Interactive Visualization.

CNN Explainer An interactive visualization system designed to help non-experts learn about Convolutional Neural Networks (CNNs) For more information,

Polo Club of Data Science 6.3k Jan 01, 2023
GitHubPoster - Make everything a GitHub svg poster

GitHubPoster Make everything a GitHub svg poster 支持 Strava 开心词场 扇贝 Nintendo Switch GPX 多邻国 Issue

yihong 1.3k Jan 02, 2023
Here I plotted data for the average test scores across schools and class sizes across school districts.

HW_02 Here I plotted data for the average test scores across schools and class sizes across school districts. Average Test Score by Race This graph re

7 Oct 27, 2021
Sci palettes for matplotlib/seaborn

sci palettes for matplotlib/seaborn Installation python3 -m pip install sci-palettes Usage import seaborn as sns import matplotlib.pyplot as plt impor

Qingdong Su 2 Jun 07, 2022
A TileDB backend for xarray.

TileDB-xarray This library provides a backend engine to xarray using the TileDB Storage Engine. Example usage: import xarray as xr dataset = xr.open_d

TileDB, Inc. 14 Jun 02, 2021
Realtime Viewer Mandelbrot set with Python and Taichi (cpu, opengl, cuda, vulkan, metal)

Mandelbrot-set-Realtime-Viewer- Realtime Viewer Mandelbrot set with Python and Taichi (cpu, opengl, cuda, vulkan, metal) Control: "WASD" - movement, "

22 Oct 31, 2022
The Timescale NFT Starter Kit is a step-by-step guide to get up and running with collecting, storing, analyzing and visualizing NFT data from OpenSea, using PostgreSQL and TimescaleDB.

Timescale NFT Starter Kit The Timescale NFT Starter Kit is a step-by-step guide to get up and running with collecting, storing, analyzing and visualiz

Timescale 102 Dec 24, 2022
A napari plugin for visualising and interacting with electron cryotomograms.

napari-tomoslice A napari plugin for visualising and interacting with electron cryotomograms. Installation You can install napari-tomoslice via pip: p

3 Jan 03, 2023
Typical: Fast, simple, & correct data-validation using Python 3 typing.

typical: Python's Typing Toolkit Introduction Typical is a library devoted to runtime analysis, inference, validation, and enforcement of Python types

Sean 171 Jan 02, 2023
a robust room presence solution for home automation with nearly no false negatives

Argos Room Presence This project builds a room presence solution on top of Argos. Using just a cheap raspberry pi zero w (plus an attached pi camera,

Angad Singh 46 Sep 18, 2022
Apache Superset is a Data Visualization and Data Exploration Platform

Superset A modern, enterprise-ready business intelligence web application. Why Superset? | Supported Databases | Installation and Configuration | Rele

The Apache Software Foundation 50k Jan 06, 2023
Minimalistic tool to visualize how the routes to a given target domain change over time, feat. Python 3.10 & mermaid.js

Minimalistic tool to visualize how the routes to a given target domain change over time, feat. Python 3.10 & mermaid.js

Péter Ferenc Gyarmati 1 Jan 17, 2022
NW 2022 Hackathon Project by Angelique Clara Hanzel, Aryan Sonik, Damien Fung, Ramit Brata Biswas

Spiral-Data-Visualizer NW 2022 Hackathon Project by Angelique Clara Hanzell, Aryan Sonik, Damien Fung, Ramit Brata Biswas Description This project vis

Damien Fung 2 Jan 16, 2022
Visualization of the World Religion Data dataset by Correlates of War Project.

World Religion Data Visualization Visualization of the World Religion Data dataset by Correlates of War Project. Mostly personal project to famirializ

Emile Bangma 1 Oct 15, 2022
Python package that generates hardware pinout diagrams as SVG images

PinOut A Python package that generates hardware pinout diagrams as SVG images. The package is designed to be quite flexible and works well for general

336 Dec 20, 2022
Rockstar - Makes you a Rockstar C++ Programmer in 2 minutes

Rockstar Rockstar is one amazing library, which will make you a Rockstar Programmer in just 2 minutes. In last decade, people learned C++ in 21 days.

4k Jan 05, 2023
Investment and risk technologies maintained by Fortitudo Technologies.

Fortitudo Technologies Open Source This package allows you to freely explore open-source implementations of some of our fundamental technologies under

Fortitudo Technologies 11 Dec 14, 2022