I want to use Flask[async] to query data asynchronously using the databases library. I want to query data from PostgreSQL using a connection from a connection pool. In order to create a single connection pool for my Flask application, like what's described here, I put the database connection code in its own module.
db.py
from databases import Database
from datetime import datetime
class Postgres:
@classmethod
async def create_pool(cls):
self = Postgres()
connection_url = 'postgresql+asyncpg://USER:PASSWORD@HOST:POST/DATABASE'
self.database = Database(connection_url, min_size=1, max_size=5)
if not self.database.is_connected:
await self.database.connect()
print(f'Connected to database at {datetime.now()}')
return self
main.py
from flask import Flask, render_template
from db import Postgres
import asyncio
from flask_wtf import FlaskForm
from wtforms.fields import StringField, SubmitField
from wtforms.validators import DataRequired, Length
async def create_app():
app = Flask(__name__)
app.db = await Postgres.create_pool()
return app
app = asyncio.run(create_app())
class ItemForm(FlaskForm):
item_id = StringField("Item ID:", validators=[DataRequired(), Length(7, 9)])
submit = SubmitField('Search')
async def get_item(item_id):
query = """select item_name from items where item_id = :item_id;"""
# app.db.database.is_connected --> True
async with app.db.database.transaction(): # AttributeError: 'NoneType' object has no attribute 'send'
item = await app.db.database.fetch_all(query, values={'item_id': item_id})
return item
@app.route('/', methods=['GET', 'POST'])
async def home():
form = ItemForm()
if form.validate_on_submit():
item = await get_item(form.item_id.data)
return render_template('home.html', form=form, item=item)
return render_template('home.html', form=form)
if __name__ == "__main__":
asyncio.run(app.run('0.0.0.0', port=8080, debug=True))
This prints Connected to database at 2023-07-12 14:42:46.601021
and the connected still exists before the database transaction, but I get the error:
AttributeError: 'NoneType' object has no attribute 'send'
Why do I get this error, and how can I make this work?
Edit:
I've removed the line async with app.db.database.transaction():
since transactions are for writing to the database. That leaves me with the error asyncpg.exceptions._base.InterfaceError: cannot perform operation: another operation is in progress
.
I then removed everything so I just have
# top of script
database = Databases(URL)
# inside get_item()
await database.connect()
await database.fetch_all(...)
The query runs, but there is no connection pool now...