Showing posts with label flask. Show all posts
Showing posts with label flask. Show all posts

Tuesday, October 8, 2024

Quart Async Example

Asynchronous Programming - One of the key features of Quart is its support for asynchronous programming. Asynchronous programming allows us to handle multiple requests at the same time and provide faster response times.

from quart import Quart, render_template

app = Quart(__name__)

async def get_items():
    # Simulate a long-running task
    await asyncio.sleep(5)
    return ['item1', 'item2', 'item3']

@app.route('/items')
async def items():
    items = await get_items()
    return await render_template('items.html', items=items)

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

We define an async function called get_items that simulates a long-running task by sleeping for 5 seconds. We then define a route ('/items') that calls this async function and renders our items.html template with the list of items.

By using asynchronous programming, we can handle other requests while the get_items function is running. This allows us to provide faster response times and improve the overall performance of our web application.

In Quart, we can also use asynchronous libraries and modules to handle tasks such as database queries and network requests. Here’s an example of how to use an asynchronous database driver (aiosqlite) in Quart:

import aiosqlite

async def get_items():
    async with aiosqlite.connect('mydatabase.db') as db:
        cursor = await db.execute('SELECT * FROM items')
        rows = await cursor.fetchall()
    return [row[0] for row in rows]

We use the aiosqlite module to connect to a SQLite database and retrieve a list of items from a table called items.

Quart’s support for asynchronous programming makes it easy to build high-performance web applications in Python. In the next section, we will look at how to integrate with databases in Quart.

Integrating with Databases

Quart makes it easy to integrate with databases and store data in our web application. Here’s an example of how to use SQLite with Quart:

import sqlite3
from quart import Quart, g, jsonify, request

app = Quart(__name__)

DATABASE = 'mydatabase.db'

def get_db():
    if 'db' not in g:
        g.db = sqlite3.connect(DATABASE)
        g.db.row_factory = sqlite3.Row
    return g.db

@app.route('/api/items')
async def get_items():
    db = get_db()
    cursor = db.execute('SELECT * FROM items')
    rows = cursor.fetchall()
    items = [dict(row) for row in rows]
    return await jsonify(items)

@app.route('/api/items', methods=['POST'])
async def add_item():
    data = await request.get_json()
    db = get_db()
    db.execute('INSERT INTO items (name) VALUES (?)', [data['name']])
    db.commit()
    response_data = {'message': 'Item added successfully', 'item': data['name']}
    response = await jsonify(response_data)
    response.status_code = 201
    return response

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

In this example, we define a function called get_db that connects to our SQLite database and returns a database connection object. We also define two routes - one to retrieve a list of items from the database and one to add a new item to the database.

By using the get_db function, we can ensure that we have a database connection available for each request. We can also use the sqlite3.Row factory to return rows as dictionaries, which makes it easy to convert our database results to JSON.

In the add_item route, we use the request.get_json function to extract the data from the request body and insert it into the items table in our database.

Quart supports other databases such as PostgreSQL and MySQL, and can also integrate with ORMs such as SQLAlchemy.

Deploy a Quart web application with authentication and authorization

In many web applications, we need to add authentication and authorization to restrict access to certain parts of our application. In Quart, we can use third-party libraries such as Flask-Login and Flask-Principal to add authentication and authorization.

Example with Flask-Login in Quart:

from quart import Quart, render_template, request, redirect, url_for
from flask_login import LoginManager, UserMixin, login_required, login_user, logout_user

app = Quart(__name__)
app.secret_key = 'mysecretkey'

login_manager = LoginManager()
login_manager.init_app(app)

class User(UserMixin):
    def __init__(self, id):
        self.id = id

    def __repr__(self):
        return f'<User {self.id}>'

@login_manager.user_loader
def load_user(user_id):
    return User(user_id)

@app.route('/')
async def index():
    return await render_template('index.html')

@app.route('/login', methods=['GET', 'POST'])
async def login():
    if request.method == 'POST':
        user_id = request.form['user_id']
        user = User(user_id)
        login_user(user)
        return redirect(url_for('dashboard'))
    return await render_template('login.html')

@app.route('/dashboard')
@login_required
async def dashboard():
    return await render_template('dashboard.html')

@app.route('/logout')
@login_required
async def logout():
    logout_user()
    return redirect(url_for('index'))

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

In this example, we define a User class that inherits from UserMixin, which provides default implementations for some methods required by Flask-Login. We also define routes for the login page, dashboard page, and logout page.

By using the @login_required decorator, we can restrict access to the dashboard and logout routes to only authenticated users. We can also use the login_user and logout_user functions to handle user authentication.

In the login route, we retrieve the user ID from the request form and create a User object. We then use the login_user function to authenticate the user and redirect them to the dashboard page.

Flask-Principal is another library that provides more fine-grained control over access to resources. It allows us to define roles and permissions for users and restrict access to certain routes or resources based on those roles and permissions.

In this way, we can add authentication and authorization to our Quart web application and provide more secure access to our resources.

Deploying the Web Application

After we have developed our Quart web application, we need to deploy it to a production environment. There are many ways to deploy a Quart application, including using a web server such as Nginx or Apache, or deploying to a Platform as a Service (PaaS) provider such as Heroku or AWS Elastic Beanstalk.

One common approach to deploying a Quart application is to use the Quart-ASGI server, which is a lightweight ASGI server designed specifically for Quart. Here’s an example of how to deploy a Quart application using Quart-ASGI:

import uvicorn
from myapp import app

if __name__ == '__main__':
    uvicorn.run(app, host='0.0.0.0', port=5000)

In this example, we import the uvicorn server and our app object from our Quart application. We then call the uvicorn.run function with our app object and specify the host and port to run the server on.

By using the Quart-ASGI server, we can take advantage of Quart’s asynchronous programming features and provide a high-performance web application.

Another approach to deploying a Quart application is to use Docker. Docker allows us to package our application and its dependencies into a container, which can be easily deployed to any platform that supports Docker.

Dockerfile for a Quart application:

FROM python:3.9-alpine

WORKDIR /app

COPY requirements.txt .
RUN pip install -r requirements.txt

COPY . .

CMD ["quart", "run", "--host", "0.0.0.0"]

In this example, we use a Python 3.9 base image and install the dependencies specified in our requirements.txt file. We then copy our application code into the container and specify the command to run the Quart server.

By using Docker, we can easily deploy our Quart application to any platform that supports Docker, such as Kubernetes or AWS Elastic Beanstalk.

In conclusion, there are many ways to deploy a Quart web application, and the choice depends on factors such as performance, scalability, and ease of deployment. By using the Quart-ASGI server or Docker, we can deploy our Quart application to production and provide a high-performance, reliable web application.

source: https://pythonic.rapellys.biz

Sunday, September 1, 2024

ReplIT Video Recorder in Flask

from flask import Flask
app = Flask(__name__)
@app.route('/')
def main():
    return """
    
<!DOCTYPE html>
<html>
  <head>
    <title>recorder</title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="keywords" content="WebRTC getUserMedia MediaRecorder API">
    <link type="text/css" rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
    <style>
      button{
        margin: 10px 5px;
      }
      li{
        margin: 10px;
      }
      body{
        width: 90%;
        max-width: 960px;
        margin: 0px auto;
      }
      #btns{
        display: none;
      }
      h1{
        margin: 100px;
      }
    </style>
  </head>
  <body>
    <h1>MediaRecorder API</h1>

    <p> For now it is supported only in Firefox(v25+) and Chrome(v47+)</p>
    <div id='gUMArea'>
      <div>
      Record:
        <input type="radio" name="media" value="video" checked id='mediaVideo'>Video
        <input type="radio" name="media" value="audio">audio
      </div>
      <button class="btn btn-default"  id='gUMbtn'>Request Stream</button>
    </div>
    <div id='btns'>
      <button  class="btn btn-default" id='start'>Start</button>
      <button  class="btn btn-default" id='stop'>Stop</button>
    </div>
    <div>
      <ul  class="list-unstyled" id='ul'></ul>
    </div>
    <script src="https://code.jquery.com/jquery-2.2.0.min.js"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
    <script>
    'use strict'

let log = console.log.bind(console),
  id = val => document.getElementById(val),
  ul = id('ul'),
  gUMbtn = id('gUMbtn'),
  start = id('start'),
  stop = id('stop'),
  stream,
  recorder,
  counter=1,
  chunks,
  media;


gUMbtn.onclick = e => {
  let mv = id('mediaVideo'),
      mediaOptions = {
        video: {
          tag: 'video',
          type: 'video/webm',
          ext: '.mp4',
          gUM: {video: true, audio: true}
        },
        audio: {
          tag: 'audio',
          type: 'audio/ogg',
          ext: '.ogg',
          gUM: {audio: true}
        }
      };
  media = mv.checked ? mediaOptions.video : mediaOptions.audio;
  navigator.mediaDevices.getUserMedia(media.gUM).then(_stream => {
    stream = _stream;
    id('gUMArea').style.display = 'none';
    id('btns').style.display = 'inherit';
    start.removeAttribute('disabled');
    recorder = new MediaRecorder(stream);
    recorder.ondataavailable = e => {
      chunks.push(e.data);
      if(recorder.state == 'inactive')  makeLink();
    };
    log('got media successfully');
  }).catch(log);
}

start.onclick = e => {
  start.disabled = true;
  stop.removeAttribute('disabled');
  chunks=[];
  recorder.start();
}


stop.onclick = e => {
  stop.disabled = true;
  recorder.stop();
  start.removeAttribute('disabled');
}

function makeLink(){
  let blob = new Blob(chunks, {type: media.type })
    , url = URL.createObjectURL(blob)
    , li = document.createElement('li')
    , mt = document.createElement(media.tag)
    , hf = document.createElement('a')
  ;
  mt.controls = true;
  mt.src = url;
  hf.href = url;
  hf.download = `${counter++}${media.ext}`;
  hf.innerHTML = `donwload ${hf.download}`;
  li.appendChild(mt);
  li.appendChild(hf);
  ul.appendChild(li);
}

    </script>
  </body>
</html>

    """
app.run('0.0.0.0')

ReplIT FlaskMockUp

from flask import request, url_for
from flask_api import FlaskAPI, status, exceptions

app = FlaskAPI(__name__)

notes = {
    0: 'do the shopping',
    1: 'build the codez',
    2: 'paint the door',
}

def note_repr(key):
    return {
        'url': request.host_url.rstrip('/') + url_for('notes_detail', key=key),
        'text': notes[key]
    }


@app.route("/", methods=['GET', 'POST'])
def notes_list():
    """
    List or create notes.
    """
    if request.method == 'POST':
        note = str(request.data.get('text', ''))
        idx = max(notes.keys()) + 1
        notes[idx] = note
        return note_repr(idx), status.HTTP_201_CREATED

    # request.method == 'GET'
    return [note_repr(idx) for idx in sorted(notes.keys())]


@app.route("/<int:key>/", methods=['GET', 'PUT', 'DELETE'])
def notes_detail(key):
    """
    Retrieve, update or delete note instances.
    """
    if request.method == 'PUT':
        note = str(request.data.get('text', ''))
        notes[key] = note
        return note_repr(key)

    elif request.method == 'DELETE':
        notes.pop(key, None)
        return '', status.HTTP_204_NO_CONTENT

    # request.method == 'GET'
    if key not in notes:
        raise exceptions.NotFound()
    return note_repr(key)
    
app.run(host='0.0.0.0', port=8080)

Saturday, October 14, 2023

Add Global Jinja Variables for Quart/Flask

app = Quart(__name__, template_folder='templates', static_folder='static')
app.jinja_env.globals['emojiflags'] = emojiflags 

 or

app = Flask(__name__, template_folder='templates', static_folder='static')
app.add_template_global(name='emojiflags', f=emojiflags

Saturday, September 2, 2023

Python flask.Request Object

 flask.Request

class flask.Request(environ, populate_request=True, shallow=False)[source]

The request object used by default in Flask. Remembers the matched endpoint and view arguments.

It is what ends up as request. If you want to replace the request object used you can subclass this and set request_class to your subclass.

The request object is a Request subclass and provides all of the attributes Werkzeug defines plus a few Flask specific ones.

Methods

__init__(environ[, populate_request, shallow])
application(f) Decorate a function as responder that accepts the request as first argument.
close() Closes associated resources of this request object.
from_values(*args, **kwargs) Create a new request object based on the values provided.
get_data([cache, as_text, parse_form_data]) This reads the buffered incoming data from the client into one bytestring.
get_json([force, silent, cache]) Parses the incoming JSON request data and returns it.
make_form_data_parser() Creates the form data parser.
on_json_loading_failed(e) Called if decoding of the JSON data failed.

Attributes

accept_charsets List of charsets this client supports as CharsetAccept object.
accept_encodings List of encodings this client accepts.
accept_languages List of languages this client accepts as LanguageAccept object.
accept_mimetypes List of mimetypes this client supports as MIMEAccept object.
access_route If a forwarded header exists this is a list of all ip addresses from the client ip to the last proxy server.
args The parsed URL parameters.
authorization The Authorization object in parsed form.
base_url Like url but without the querystring See also: trusted_hosts.
blueprint The name of the current blueprint
cache_control A RequestCacheControl object for the incoming cache control headers.
charset
content_encoding The Content-Encoding entity-header field is used as a modifier to the media-type.
content_length The Content-Length entity-header field indicates the size of the entity-body in bytes or, in the case of the HEAD method, the size of the entity-body that would have been sent had the request been a GET.
content_md5 The Content-MD5 entity-header field, as defined in RFC 1864, is an MD5 digest of the entity-body for the purpose of providing an end-to-end message integrity check (MIC) of the entity-body.
content_type The Content-Type entity-header field indicates the media type of the entity-body sent to the recipient or, in the case of the HEAD method, the media type that would have been sent had the request been a GET.
cookies Read only access to the retrieved cookie values as dictionary.
data
date The Date general-header field represents the date and time at which the message was originated, having the same semantics as orig-date in RFC 822.
disable_data_descriptor
encoding_errors
endpoint The endpoint that matched the request.
files MultiDict object containing
form The form parameters.
full_path Requested path as unicode, including the query string.
headers The headers from the WSGI environ as immutable EnvironHeaders.
host Just the host including the port if available.
host_url Just the host with scheme as IRI.
if_match An object containing all the etags in the If-Match header.
if_modified_since The parsed If-Modified-Since header as datetime object.
if_none_match An object containing all the etags in the If-None-Match header.
if_range The parsed If-Range header.
if_unmodified_since The parsed If-Unmodified-Since header as datetime object.
input_stream
is_json Indicates if this request is JSON or not.
is_multiprocess boolean that is True if the application is served by
is_multithread boolean that is True if the application is served by
is_run_once boolean that is True if the application will be executed only
is_secure True if the request is secure.
is_xhr True if the request was triggered via a JavaScript XMLHttpRequest.
json If the mimetype is application/json this will contain the parsed JSON data.
max_content_length Read-only view of the MAX_CONTENT_LENGTH config key.
max_form_memory_size
max_forwards The Max-Forwards request-header field provides a mechanism with the TRACE and OPTIONS methods to limit the number of proxies or gateways that can forward the request to the next inbound server.
method The transmission method.
mimetype Like content_type, but without parameters (eg, without charset, type etc.) and always lowercase.
mimetype_params The mimetype parameters as dict.
module The name of the current module if the request was dispatched to an actual module.
path Requested path as unicode.
pragma The Pragma general-header field is used to include implementation-specific directives that might apply to any recipient along the request/response chain.
query_string The URL parameters as raw bytestring.
range The parsed Range header.
referrer The Referer[sic] request-header field allows the client to specify, for the server’s benefit, the address (URI) of the resource from which the Request-URI was obtained (the “referrer”, although the header field is misspelled).
remote_addr The remote address of the client.
remote_user If the server supports user authentication, and the script is protected, this attribute contains the username the user has authenticated as.
routing_exception If matching the URL failed, this is the exception that will be raised / was raised as part of the request handling.
scheme URL scheme (http or https).
script_root The root path of the script without the trailing slash.
stream The stream to read incoming data from.
trusted_hosts
url The reconstructed current URL as IRI.
url_charset The charset that is assumed for URLs.
url_root The full URL root (with hostname), this is the application root as IRI.
url_rule The internal URL rule that matched the request.
user_agent The current user agent.
values Combined multi dict for args and form.
view_args A dict of view arguments that matched the request.
want_form_data_parsed Returns True if the request method carries content.
https://tedboy.github.io/flask

Friday, September 1, 2023

Python Quart Parse Request + Cheatsheet

import site, os # get quart version with standard libs
sitepackagedirs = [x[0] for x in os.walk(site.getsitepackages()[1])]
print(quart.__name__, [pack for pack in sitedirs if 'quart-' in pack][0][-16:-10])

from quart import Quart, render_template, request

@app.route("/hello")
async def hello():

request.method
request.url
request.headers["X-Bob"]
request.args.get("a") # Query string e.g. example.com/hello?a=2
request.args.getlist()
request.args.to_dict())
await request.get_data() # Full raw body
(await request.form)["name"]
await request.args.getlist()
(await request.get_json())["key"]
request.cookies.get("name")

https://tedboy.github.io/flask/generated/generated/flask.Request.html

The request object is a Request subclass and provides all of the attributes Werkzeug defines plus a few Flask specific ones.

form
    A MultiDict with the parsed form data from POST or PUT requests. Please keep in mind that file uploads will not end up here, but instead in the files attribute.
args
    A MultiDict with the parsed contents of the query string. (The part in the URL after the question mark).
values
    A CombinedMultiDict with the contents of both form and args.
cookies
    A dict with the contents of all cookies transmitted with the request.
stream
    If the incoming form data was not encoded with a known mimetype the data is stored unmodified in this stream for consumption. Most of the time it is a better idea to use data which will give you that data as a string. The stream only returns the data once.
headers
    The incoming request headers as a dictionary like object.
data
    Contains the incoming request data as string in case it came with a mimetype Flask does not handle.
files
    A MultiDict with files uploaded as part of a POST or PUT request. Each file is stored as FileStorage object. It basically behaves like a standard file object you know from Python, with the difference that it also has a save() function that can store the file on the filesystem.
environ
    The underlying WSGI environment.
method
    The current request method (POST, GET etc.)

https://tedboy.github.io/flask/generated/generated/werkzeug.MultiDict.html

to_dict([flat]) Return the contents as regular dict.
getlist(key[, type]) Return the list of items for a given key.


# Requested url: http://192.168.2.100:5000/resultdic?q=Kern&sl=de&tl=ro&dic=IATE&dic=SAP
# http://192.168.2.100:5000/resultdic?q=Kern&sl=de&tl=ro&dic=all

allbidiclist: list[str] = ['Hallo.ro', 'Dict.cc', 'Linguee.com', 'IATE', 'SAP', 'Yandex']

@app.route("/resultdic", methods=["GET"])
async def resultdic():

if request.method == "GET":
searchformterm = request.args.get("q", None)
sourcelang = request.args.get("sl", None)
targetlang = request.args.get("tl", None) # get(key, default=None, type=None)
# Return the default value if the requested data doesn’t exist. If type is provided and is a callable it should convert the value, return it or raise a ValueError if that is not possible.
selecteddiclist = request.args.getlist("dic", None) # list from dic=Dict.cc&dic=SAP
if selecteddiclist: selecteddiclist = alldiclist if selecteddiclist[0] == "all" else selecteddiclist
print("request.args dict:", request.args.to_dict()) # Python dictionary

Cheatsheet

Basic App

from quart import Quart

app = Quart(__name__)

@app.route("/hello")
async def hello():
    return "Hello, World!"

if __name__ == "__main__":
    app.run(debug=True)

Routing

@app.route("/hello/<string:name>")  # example.com/hello/quart
async def hello(name):
    return f"Hello, {name}!"

Request Methods

@app.route("/get")  # GET Only by default
@app.route("/get", methods=["GET", "POST"])  # GET and POST
@app.route("/get", methods=["DELETE"])  # Just DELETE

JSON Responses

@app.route("/hello")
async def hello():
    return {"Hello": "World!"}

Template Rendering

from quart import render_template

@app.route("/hello")
async def hello():
    return await render_template("index.html")  # Required to be in templates/

Configuration

import json
import toml

app.config["VALUE"] = "something"

app.config.from_file("filename.toml", toml.load)
app.config.from_file("filename.json", json.load)

Request

from quart import request

@app.route("/hello")
async def hello():
    request.method
    request.url
    request.headers["X-Bob"]
    request.args.get("a")  # Query string e.g. example.com/hello?a=2
    await request.get_data()  # Full raw body
    (await request.form)["name"]
    (await request.get_json())["key"]
    request.cookies.get("name")

WebSocket

from quart import websocket

@app.websocket("/ws")
async def ws():
    websocket.headers
    while True:
        try:
            data = await websocket.receive()
            await websocket.send(f"Echo {data}")
        except asyncio.CancelledError:
            # Handle disconnect
            raise

Cookies

from quart import make_response

@app.route("/hello")
async def hello():
    response = await make_response("Hello")
    response.set_cookie("name", "value")
    return response

Abort

from quart import abort

@app.route("/hello")
async def hello():
    abort(409)

HTTP/2 & HTTP/3 Server Push

from quart import make_push_promise, url_for

@app.route("/hello")
async def hello():
    await make_push_promise(url_for('static', filename='css/minimal.css'))


Source: https://pgjones.gitlab.io

The docs describe the attributes available on the request object (from flask import request) during a request. In most common cases request.data will be empty because it's used as a fallback:

request.data Contains the incoming request data as string in case it came with a mimetype Flask does not handle.

  • request.args: the key/value pairs in the URL query string
  • request.form: the key/value pairs in the body, from a HTML post form, or JavaScript request that isn't JSON encoded
  • request.files: the files in the body, which Flask keeps separate from form. HTML forms must use enctype=multipart/form-data or files will not be uploaded.
  • request.values: combined args and form, preferring args if keys overlap
  • request.json: parsed JSON data. The request must have the application/json content type, or use request.get_json(force=True) to ignore the content type.

All of these are MultiDict instances (except for json). You can access values using:

  • request.form['name']: use indexing if you know the key exists
  • request.form.get('name'): use get if the key might not exist
  • request.form.getlist('name'): use getlist if the key is sent multiple times and you want a list of values. get only returns the first value.

Run in debug mode:

quart_cfg = hypercorn.Config()
quart_cfg.bind = ["0.0.0.0:8000"]
app = Quart(__name__)
...
async def main():
    await hypercorn.asyncio.serve(app,quart_cfg)

if __name__ == '__main__':
    client.loop.set_debug(True)
    client.loop.run_until_complete(main())

Run function at startup:

a background task that is started on startup,

async def schedule():
    while True:
        await asyncio.sleep(1)
        await do_work()

@app.before_serving
async def startup():
    app.add_background_task(schedule)

which will run schedule for the lifetime of the app, being cancelled at shutdown.

The ASGI lifespan specification includes the ability for awaiting coroutines before the first byte is received and after the final byte is sent, through the startup and shutdown lifespan events. This is particularly useful for creating and destroying connection pools. Quart supports this via the decorators before_serving() and after_serving(), which function like before_first_request(), and while_serving() which expects a function that returns a generator.

@app.before_serving
async def create_db_pool():
    app.db_pool = await ...
    g.something = something

@app.before_serving
async def use_g():
    g.something.do_something()

@app.while_serving
async def lifespan():
    ...  # startup
    yield
    ...  # shutdown

@app.route("/")
async def index():
    app.db_pool.execute(...)
    # g.something is not available here

@app.after_serving
async def create_db_pool():
    await app.db_pool.close()

AI response: Quart does not have a direct equivalent to Flask's @response.call_on_close. However, Quart provides a way to handle tasks in the background which can be used to achieve similar functionality.

from quart import Quart, request, jsonify  
from quart.ctx import copy_current_websocket_context  
 
app = Quart(__name__)  
 
@app.route('/')  
async def index():  
    @copy_current_websocket_context  
    async def after_request():  
        # Code to be executed after the response is sent  
        pass  
 
    app.add_background_task(after_request)  
    return jsonify({'message': 'Hello, World!'})  


In this example, the after_request function will be executed after the response is sent. The copy_current_websocket_context decorator is used to preserve the context for the function when it's run in the background. Please note that errors raised in a background task are logged but otherwise ignored allowing the app to continue - much like with request/websocket handling errors.

Source: https://stackoverflow.com

Sunday, March 12, 2023

Flask Ressources

Framework

  • Connexion - Swagger/OpenAPI First framework for Python on top of Flask with automatic endpoint validation and OAuth2 support
  • Flask-MongoRest - Restful API framework wrapped around MongoEngine
  • Eve - REST API framework powered by Flask, MongoDB and good intentions
  • Flask-Restless - A Flask extension for creating simple ReSTful APIs from SQLAlchemy models
  • Flask-RESTful - Simple framework for creating REST APIs
  • Flask-RestPlus - syntaxic sugar, helpers and automatically generated Swagger documentation.
  • Flask-Potion - RESTful API framework for Flask and SQLAlchemy
  • Zappa - Build and deploy server-less Flask applications on AWS Lambda and API Gateway

Admin interface

  • Flask-Admin - Simple and extensible administrative interface framework for Flask

Analytics

  • Flask-Analytics - Analytics snippets generator extension for the Flask framework
  • Flask-Matomo - Track requests to your Flask website with Matomo

Authentication

  • Flask-Security - Quick and simple security for Flask applications
  • Flask-Login - Flask user session management
  • Flask-User - Customizable user account management for Flask
  • Flask-HTTPAuth - Simple extension that provides Basic and Digest HTTP authentication for Flask routes
  • Flask-Praetorian - Strong, Simple, and Precise security for Flask APIs (using jwt)

Authorization

  • Authlib - Authlib is an ambitious authentication library for OAuth 1, OAuth 2, OpenID clients, servers and more.
  • Authomatic - Authomatic provides out of the box support for a number of providers using OAuth 1.0a (Twitter, Tumblr and more) and OAuth 2.0 (Facebook, Foursquare, GitHub, Google, LinkedIn, PayPal and more)
  • Flask-Pundit - Extension based on Rails' Pundit gem that provides easy way to organize access control for your models
  • Flask-Dance - OAuth consumer extension for Flask, shipped with pre-set support for Facebook, GitHub, Google, etc.

Database

Database Migrations

  • Flask-Migrate - SQLAlchemy database migrations for Flask applications using Alembic

Session

Cache

Data Validation

  • Flask-WTF - Simple integration of Flask and WTForms, including CSRF, file upload and Recaptcha integration.

Email

  • Flask-Mail - Flask-Mail adds SMTP mail sending to your Flask applications

i18n

  • flask-babel - i18n and l10n support for Flask based on Babel and pytz

Full-text searching

Rate Limiting

  • Flask-Limiter - Flask-Limiter provides rate limiting features to flask routes

Task Queue

Exception tracking

Tracing

APM

Other SDK

Frontend

  • Flask-CORS - A Flask extension for handling Cross Origin Resource Sharing (CORS), making cross-origin AJAX possible
  • flask-assets - Flask webassets integration
  • flask-s3 - Seamlessly serve your static assets of your Flask app from Amazon S3
  • Flask-SSLify - Force SSL on your Flask app
  • Flask-HTMLmin - Flask html minifier

Development (Debugging/Testing/Documentation)

Utils

  • flask-marshmallow Flask + marshmallow for beautiful APIs
  • flask-jsonrpc - A basic JSON-RPC implementation for your Flask-powered sites
  • Flask-Bcrypt - Flask-Bcrypt is a Flask extension that provides bcrypt hashing utilities for your application
  • Mixer - Mixer is application to generate instances of Django or SQLAlchemy models
  • Flask-FeatureFlags - A Flask extension that enables or disables features based on configuration
  • Flask-Reggie - Regex Converter for Flask URL Routes
  • Flask-SocketIO - Socket.IO integration for Flask applications
  • Flask-Moment - Formatting of dates and times in Flask templates using moment.js
  • Flask-Paginate - Pagination support for Flask
  • Flask-graphql - Adds GraphQL support to your Flask application

Resources

Tutorials

Courses

Books

Slides

Videos

Built with Flask

  • zmusic-ng - ZX2C4 Music provides a web interface for playing and downloading music files using metadata.
  • GuitarFan - guitar tab
  • June - python-china.org
  • Zerqu - ZERQU is a content-focused API-based platform. eg: Python-China
  • motiky
  • missing - a list service called missing
  • thenewsmeme.com
  • overholt - Example Flask application illustrating common practices
  • pypress - flask team blog
  • thepast.me
  • redispapa - another redis monitor by using flask, angular, socket.io
  • flaskblog - a simple blog system based on flask
  • cleanblog - a clean blog system based on flask and mongoengine
  • Quokka CMS - CMS made with Flask and MongoDB
  • chat - a live chat built with python (flask + gevent + apscheduler) + redis
  • chatapp - Flask and Angular.js Chat Application using Socket.io
  • Frozen-Flask - Freezes a Flask application into a set of static files
  • mcflyin - A small timeseries transformation API built on Flask and Pandas
  • Skylines - Live tracking, flight database and competition framework
  • airflow - Airflow is a system to programmatically author, schedule and monitor data pipelines.
  • timesketch - Collaborative forensics timeline analysis
  • changes - A dashboard for your code. A build system.
  • security_monkey - monitors policy changes and alerts on insecure configurations in an AWS account.
  • securedrop- an open-source whistleblower submission system that media organizations can use to securely accept documents from and communicate with anonymous sources.
  • sync_engine - IMAP/SMTP sync system with modern APIs
  • cleansweep - Volunteer & Campaign Management System
  • indico - a general-purpose event management web-based solution. It includes a full-blown conference organization workflow as well as tools for meeting management and room booking. It provides as well integration with video-conferencing solutions.
  • flaskbb - A classic Forum Software in Python using Flask.
  • [PythonBuddy] (https://github.com/ethanchewy/PythonBuddy) - Online Python Editor With Live Syntax Checking and Execution

Boilerplate

Source: https://github.com/humiaozuzu/awesome-flask