pythonquarthypercorn

How to use quart-db with hypercorn?


I'm trying to use the quart-db extension to connect to a postgresql DB from a Quart app that is served by hypercorn. But I'm not understanding how to use the db connection for an app that is served by hypercorn where the app initialization and route definitions are spread across multiple files.

My simplified setup is:

App is served by running: hypercorn myapp:app

myapp.py has

import os
from app import create_app

app = create_app(os.getenv('MYAPP_CONFIG') or 'default')

app/__init__.py has

from quart import Quart
from config import config
    
def create_app(config_name):
    app = Quart(__name__)
    app.config.from_object(config[config_name])
    config[config_name].init_app(app)
    from .main import main as main_blueprint
    app.register_blueprint(main_blueprint)    
    return app

And main/__init__.py has the following:

from quart import Blueprint
import os

main = Blueprint('main', __name__)    
from .views import views

And main/views/views.py has the views where the routes are defined where I want to access the postgresql db connection.

from quart import render_template, session, redirect, url_for, current_app, request, Response, g
from quart_db import QuartDB
from .. import main

# I tried this but it didn't work
#db = QuartDB(current_app, url="postgresql://user:password@postgresfqdn:5432/mydb")


@main.route('/', methods=['GET', 'HEAD'])
async def index():
    # Do something cool with the db connection here
    return "Myapp is running!\n"

Should db = QuartDB(...) be defined in main/views/views.py, or should be be defined elsewhere and somehow imported into main/views/views.py?


Solution

  • I would place it within the create_app function in the app/__init__.py file,

    db = QuartDB()
     
    def create_app(config_name):
        app = Quart(__name__)
        db.init_app(app)
    

    You can then use the connection placed on the g global in the views,

    from quart import g
    
    @main.route('/', methods=['GET', 'HEAD'])
    async def index():
        g.execute("SELECT 1")  # Do something cool with the db connection here
        return "Myapp is running!\n"
    

    If you find you need to access the QuartDB instance (db) then I'd place db = QuartDB() in app/db.py and import it where required.