Вопрос или проблема
Я новичок в разработке на Flask, и я потратил много часов на разработку своего приложения, но не могу связать свою базу данных с приложением.
Я продолжаю получать эту ошибку:
AttributeError
AttributeError: объект ‘NoneType’ не имеет атрибута ‘getconn’
Я инициализировал пул соединений, который создается успешно, но когда я пытаюсь выполнить запрос к базе данных, я получаю эту ошибку. Я тестировал запрос к своей базе данных из командной строки без проблем и проверял статус своего экземпляра RDS, который был “доступен”.
Это мой маршрут входа:
@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
username = request.form['username']
password = request.form['password']
authenticated, user_to_login = authenticate_user(username, password)
if authenticated:
login_user(user_to_login)
# Перенаправление в зависимости от роли
if user_to_login.role == 'admin':
return redirect(url_for('adminPage'))
elif user_to_login.role == 'client':
return redirect(url_for('Clientpage'))
elif user_to_login.role == 'manager':
return redirect(url_for('managerPage'))
else:
return render_template('login.html')
else:
return render_template('login.html', error="Неверное имя пользователя или пароль")
return render_template('login.html')
Вот как я инициализирую пул соединений:
def init_db(targetDbName):
global connection_pool
db_credentials = get_secret() # протестированная функция, которая извлекает правильные значения
USERNAME = db_credentials['username']
PASSWORD = db_credentials['password']
HOST = 'localhost' # так как я в разработке
PORT = db_credentials['port']
connection_pool = psycopg2.pool.SimpleConnectionPool(
minconn=1,
maxconn=10,
user=USERNAME,
password=PASSWORD,
host=HOST,
port=PORT,
database=targetDbName # имя правильное
)
И, наконец, функция аутентификации, используемая в логике входа:
def authenticate_user(username, password):
try:
conn = connection_pool.getconn()
cursor = conn.cursor()
select_query = """
SELECT id, password, role FROM users WHERE username = %s
"""
cursor.execute(select_query, (username,))
user = cursor.fetchone()
if user:
id, db_password_hash, db_role = user
if check_password_hash(db_password_hash, password):
print("Успех.")
print(id)
print(db_role)
user_to_login = User(id, username, db_role)
return True, user_to_login
else:
print("Неверный пароль.")
return False, None
else:
print("Пользователь не найден.")
return False, None
except Exception as e:
print(f"Ошибка: {e}")
return False, None
finally:
cursor.close()
conn.close()`
ПРИМЕЧАНИЕ: Я также пытался инициализировать conn и cursor как None, но в этом случае я получаю ошибку, так как они равны None.
Спасибо заранее за вашу помощь!
Код, похоже, правильный. Может быть, вы вызываете функцию authenticate_user до инициализации базы данных?
Также я бы добавил блок try-except при создании соединения с базой данных.
try:
connection_pool = psycopg2.pool.SimpleConnectionPool(
minconn=1,
maxconn=10,
user=USERNAME,
password=PASSWORD,
host=HOST,
port=PORT,
database=targetDbName
)
# Соединение будет успешно создано.
# Если нет, произойдет переход к ошибке (и она скажет вам, что не так).
except psycopg2.Error as e:
print(f"Ошибка при создании пула соединений: {e}")
Ответ или решение
Ошибка AttributeError: 'NoneType' object has no attribute 'getconn'
в вашем Flask-приложении указывает на то, что переменная connection_pool
, в которой вы храните пул соединений, не инициализирована. Давайте подробно рассмотрим возможные причины этой проблемы и предложим решение.
Проблема и её Причины
-
Неинициализированный Пул Соединений: Переменная
connection_pool
, которая используется в функцииauthenticate_user
, возможно, не была инициализирована до её вызова. Если инициализация пула соединений в функцииinit_db
еще не была выполнена,connection_pool
будет иметь значениеNone
. -
Порядок Выполнения: Возможно, вы вызываете
authenticate_user
до того, как вызвалиinit_db
. Необходимо убедиться, что инициализация происходит перед любыми запросами к базе данных. -
Проблемы с Соединением: Если соединение с вашей базой данных (например, Amazon RDS или другой сервер PostgreSQL) не удается установить, может возникнуть ошибка в момент создания пула, но этот момент не будет очевиден, если не добавите обработку исключений при инициализации.
Рекомендации по Решению
-
Инициализация Пула Соединений: Убедитесь, что метод
init_db
вызывается при запуске приложения, и выполнен до того, как вы будете пытаться получить доступ кconnection_pool
. Вы можете сделать это в блоке конфигурации вашего приложения, например, в основном файле Flask:if __name__ == '__main__': init_db('your_database_name') # Убедитесь, что имя вашей базы данных указано правильно app.run()
-
Обработка Исключений: Добавьте блок
try-except
при создании пула, чтобы убедиться, что он был создан успешно. Это помогает выявить потенциальные проблемы при подключении к базе данных:try: connection_pool = psycopg2.pool.SimpleConnectionPool( minconn=1, maxconn=10, user=USERNAME, password=PASSWORD, host=HOST, port=PORT, database=targetDbName ) if connection_pool is None: raise Exception("Не удалось создать пул соединений") except psycopg2.Error as e: print(f"Ошибка при создании пула соединений: {e}")
-
Логирование: Используйте логирование для отслеживания состояния вашего пула и возможных ошибок. Это может помочь вам понять, где именно возникает проблема:
import logging logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) def init_db(targetDbName): global connection_pool try: # ваш код инициализации пула logger.info("Пул соединений успешно создан") except Exception as e: logger.error(f"Ошибка инициализации базы данных: {e}")
Заключение
Следуя приведенным выше рекомендациям, вы сможете более эффективно справляться с error AttributeError: 'NoneType' object has no attribute 'getconn'
. Важно всегда инициализировать все необходимые переменные и ресурсы перед их использованием, а также реализовать обработку исключений, чтобы быстро выявлять и отслеживать проблемы. Проверяйте порядок вызовов функций и следите за состоянием пула соединений, чтобы избежать подобных ошибок в будущем.