Это решение, вероятно, далеко от совершенства, и оно на самом деле не СУХОЕ.Я бы приветствовал комментарии или другие ответы, основанные на этом.
Чтобы реализовать поддержку psycopg2
, вам, вероятно, нужно взглянуть на пул соединений .Существует также хорошее руководство о том, как реализовать это с Flask.
Основная идея - сначала создать пул соединений.Вы хотите, чтобы это было установлено при инициализации приложения фляги (это может быть в интерпретаторе python или через рабочий gunicorn, которых может быть несколько - в этом случае каждый рабочий имеет свой собственный пул соединений).Я решил сохранить возвращенный пул в конфигурации:
from flask import Flask, g, jsonify
import psycopg2
from psycopg2 import pool
app = Flask(__name__)
app.config['postgreSQL_pool'] = psycopg2.pool.SimpleConnectionPool(1, 20,
user = "postgres",
password = "very_secret",
host = "127.0.0.1",
port = "5432",
database = "postgres")
Обратите внимание, что первые два аргумента SimpleConnectionPool
- это соединения min
& max
.Это число подключений к вашему серверу базы данных, между 1
и 20
в данном случае.
Далее определите функцию get_db
:
def get_db():
if 'db' not in g:
g.db = app.config['postgreSQL_pool'].getconn()
return g.db
SimpleConnectionPool.getconn()
используемый здесь метод просто возвращает соединение из пула, который мы присваиваем g.db
и возвращаем.Это означает, что когда мы вызываем get_db()
в любом месте кода, он возвращает то же соединение или создает соединение, если оно отсутствует.Нет необходимости в before.context
декораторе.
Определите свою функцию разрыва:
@app.teardown_appcontext
def close_conn(e):
db = g.pop('db', None)
if db is not None:
app.config['postgreSQL_pool'].putconn(db)
Она запускается, когда контекст приложения разрушается, и использует SimpleConnectionPool.putconn()
, чтобы убрать соединение.
Наконец, определите маршрут:
@app.route('/')
def index():
db = get_db()
cursor = db.cursor()
cursor.execute("select 1;")
result = cursor.fetchall()
print (result)
cursor.close()
return jsonify(result)
Этот код работает для меня, проверенный на запуск postgres в контейнере Docker.Несколько вещей, которые, вероятно, следует улучшить:
Это представление не очень СУХОЕ.Возможно, вы могли бы переместить часть этого в функцию get_db
, чтобы она возвращала курсор.(!!!)
Когда выйдет интерпретатор Python, вы также должны найти способ закрыть соединение с app.config['postgreSQL_pool'].closeall
Хотя провереноБыл бы неплох какой-то способ мониторинга пула, чтобы вы могли наблюдать за соединениями пул / дБ под нагрузкой и убедиться, что пул ведет себя как положено.
(!!!) В другой стране документация sqlalchemy.scoped_session
объясняет больше вещей, связанных с этим, с некоторой теорией о том, как ее «сеансы» работают в отношении запросов.Они реализовали его таким образом, что вы можете вызвать Session.query('SELECT 1')
, и он создаст сеанс, если он еще не существует.
РЕДАКТИРОВАТЬ : Вот gist с шаблоном фабрики вашего приложения и примером использования в комментарии.