Подключение тг бота на aiogram3 к Postgres БД в отдельном файле, используя asyncpg
У меня есть телеграм бот, он организован как проект, структурирован по папкам. Раньше я использовал библиотеку psycopg2 для работы с бд, но, насколько я понимаю, она не очень хорошо работает в ассинхронных ботах, поэтому перехожу на asyncpg.
Сложность в том, что я хочу организовать подключение к бд в отдельном файле. Мне нужно, чтобы при старте бота создавалось подключение к базе данных и conn, а дальше я мог импортировать этот conn в любой другой файл проекта и использовать его для запросов к бд. Я написал следующий код, и хотел бы посоветоваться с вами, насколько это оптимальное и рабочее решение?
файл postgres_db.py:
import asyncpg
import os
class DatabaseConnection:
_conn = None
@classmethod
async def connect(cls):
if cls._conn is None:
try:
cls._conn = await asyncpg.connect(os.environ.get('DATABASE_URL'))
print('Data base connected OK!')
except Exception as e:
print(f"Unable to connect to the database: {e}")
@classmethod
async def get_conn(cls):
if cls._conn is None:
await cls.connect()
return cls._conn
открытие соединения с бд, main.py:
import asyncio
from data_base.postgres_db import DatabaseConnection
from handlers.echo import echo_router
from create_bot import bot, dp
dp.include_router(echo_router)
async def main():
print("Бот вышел в онлайн!")
await DatabaseConnection.connect()
await bot.delete_webhook(drop_pending_updates=True)
await dp.start_polling(bot)
asyncio.run(main())
Пример, как я импортирую conn в хендлерах:
from aiogram import Router, types
from aiogram.filters import CommandStart
from data_base.postgres_db import DatabaseConnection
echo_router = Router()
@echo_router.message(CommandStart())
async def show_statistic(message: types.Message):
conn = await DatabaseConnection.get_conn()
await conn.execute('SELECT COUNT(*) FROM statistic')
count_start = await conn.fetchval('SELECT COUNT(*) FROM statistic')
await message.answer(f'Число пользователей, нажавших /start: {count_start}')
@echo_router.message()
async def echo_message(message: types.Message):
await message.answer(message.text)