Вопрос или проблема
Немного предыстории: я довольно нов в SQLAlchemy, поэтому изучал документацию, пытаясь найти способ выполнять запросы к уже существующей базе данных MariaDB в Flask-SQLAlchemy. Это привело меня к этому: документу SQLAlchemy в Flask, который, казалось, отвечал на мой точный вопрос. Я сделал небольшой проект на основе раздела “Декларативный”, а затем изменил его для раздела “Абстракция SQL”, в результате чего получились следующие файлы и структура файлов:
- sql_abstract
-
.venv
-
app
- _init_.py
- database.py
- models.py
- routes.py
-
config.py
-
run.py
-
_init_.py
from flask import Flask
def create_app():
app = Flask(__name__)
app.config.from_object('config')
from app.routes import register_routes
register_routes(app)
return app
database.py
from sqlalchemy import create_engine, MetaData, Table
from config import conf
engine=create_engine(conf)
metadata = MetaData(bind=engine)
models.py
from sqlalchemy import Table
from app.database import metadata
basic = Table('tblBasic', metadata, autoload=True)
routes.py
from app.models import basic
def register_routes(app):
@app.route("https://stackoverflow.com/")
def index():
res= basic.select(basic.c.name == "John").execute().first()
return res
run.py
#get the app from the app folder's init.py
from app import create_app
flask_app=create_app()
if __name__ == '__main__':
flask_app.run()
Это приводит к следующей ошибке:
File "c:\...\app\database.py", line 5, in <module>
metadata = MetaData(bind=engine)
^^^^^^^^^^^^^^^^^^^^^
TypeError: MetaData.__init__() got an unexpected keyword argument 'bind'
Я в замешательстве, и потому что это код из документации, но также в документации SQLAlchemy упоминается, что Metadata “Содержит коллекцию Table
объектов, а также необязательное связывание с Engine
или Connection
.”
Я пытался импортировать специально из sqlalchemy.schema, думая, что могу импортировать другой класс с таким же именем, но это не сработало.
Я также пробовал использовать Metadata.reflect(bind=engine) как в этом примере, в результате чего строка 5 в database.py стала:
metadata = MetaData().reflect(bind=engine)
а строка 4 в models.py стала:
basic=metadata.tables["tblBasic"]
но это привело к тому, что metadata стал объектом типа NoneType.
Кто-нибудь знает, что вызывает эту ошибку и как это исправить? Я в полном замешательстве.
Ответ или решение
Ошибка TypeError: MetaData.__init__() got an unexpected keyword argument 'bind'
в SQLAlchemy может возникнуть по нескольким причинам, однако, в контексте вашего кода, проблема заключается в том, как вы инициализируете объект MetaData
.
Причины ошибки
-
Версия SQLAlchemy: В вашем коде используется параметр
bind
при инициализации объектаMetaData
, который был актуален в старых версиях SQLAlchemy. С версии 1.4 и новее, параметрbind
был удален из конструктораMetaData
. Вместо этого, необходимо использовать методы подсоединения к движку (engine) напрямую. -
Подход к работе с метаданными: В новых версиях SQLAlchemy рекомендуется использовать
MetaData
с методами для отражения структуры базы данных, напримерreflect()
, без передачи параметров конструкции.
Как исправить
Для исправления вашей ошибки, вам нужно изменить способ инициализации объекта MetaData
в файле database.py
. Вместо использования параметра bind
, выполните сравнение вашей версии SQLAlchemy с документацией и измените код на следующий:
from sqlalchemy import create_engine, MetaData
from config import conf
engine = create_engine(conf)
metadata = MetaData() # Убираем bind=engine здесь
# Далее необходимо отразить метаданные
metadata.reflect(bind=engine) # Теперь вы можете использовать этот метод
Убедитесь, что в вашем файле models.py
вы обращаетесь к таблице правильно. Измените его следующим образом:
from sqlalchemy import Table
from app.database import metadata
basic = metadata.tables["tblBasic"] # Теперь вы берете таблицу из обновленного metadata
Дополнительные Примечания
-
Проверка версии: Соответственно проверьте версию SQLAlchemy, установленную в вашем виртуальном окружении. Это можно сделать, выполнив команду:
pip show SQLAlchemy
-
Понимание изменений в API: Всегда полезно ознакомиться с историей изменений (changelog) библиотеки, чтобы понять какие изменения могут касаться того, что вы пытаетесь сделать.
Заключение
Таким образом, вам следует обновить ваш код с учетом современных стандартов SQLAlchemy. Изменения, предложенные выше, должны решить вашу проблему с TypeError
и позволяют вам правильно работать с метаданными базы данных. Убедитесь, что ваш код соответствует последним рекомендациям в документации SQLAlchemy для предотвращения подобных ошибок в будущем.