组件版本:
使用原生方法查询:
db.session.execute("select * from user", bind_arguments={'bind':activity_engine}).fetchall()
报了:get_bind() got an unexpected keyword argument 'bind'异常,查看源码后发现并没有明显异常:
def execute(
self,
statement,
params=None,
execution_options=util.EMPTY_DICT,
bind_arguments=None,
_parent_execute_state=None,
_add_event=None,
**kw
):
r"""Execute a SQL expression construct.
Returns a :class:`_engine.Result` object representing
results of the statement execution.
E.g.::
from sqlalchemy import select
result = session.execute(
select(User).where(User.id == 5)
)
The API contract of :meth:`_orm.Session.execute` is similar to that
of :meth:`_future.Connection.execute`, the :term:`2.0 style` version
of :class:`_future.Connection`.
.. versionchanged:: 1.4 the :meth:`_orm.Session.execute` method is
now the primary point of ORM statement execution when using
:term:`2.0 style` ORM usage.
:param statement:
An executable statement (i.e. an :class:`.Executable` expression
such as :func:`_expression.select`).
:param params:
Optional dictionary, or list of dictionaries, containing
bound parameter values. If a single dictionary, single-row
execution occurs; if a list of dictionaries, an
"executemany" will be invoked. The keys in each dictionary
must correspond to parameter names present in the statement.
:param execution_options: optional dictionary of execution options,
which will be associated with the statement execution. This
dictionary can provide a subset of the options that are accepted
by :meth:`_engine.Connection.execution_options`, and may also
provide additional options understood only in an ORM context.
:param bind_arguments: dictionary of additional arguments to determine
the bind. May include "mapper", "bind", or other custom arguments.
Contents of this dictionary are passed to the
:meth:`.Session.get_bind` method.
:param mapper:
deprecated; use the bind_arguments dictionary
:param bind:
deprecated; use the bind_arguments dictionary
:param \**kw:
deprecated; use the bind_arguments dictionary
:return: a :class:`_engine.Result` object.
"""
statement = coercions.expect(roles.StatementRole, statement)
if kw:
util.warn_deprecated_20(
"Passing bind arguments to Session.execute() as keyword "
"arguments is deprecated and will be removed SQLAlchemy 2.0. "
"Please use the bind_arguments parameter."
)
if not bind_arguments:
bind_arguments = kw
else:
bind_arguments.update(kw)
elif not bind_arguments:
bind_arguments = {}
if (
statement._propagate_attrs.get("compile_state_plugin", None)
== "orm"
):
# note that even without "future" mode, we need
compile_state_cls = CompileState._get_plugin_class_for_plugin(
statement, "orm"
)
else:
compile_state_cls = None
execution_options = util.coerce_to_immutabledict(execution_options)
if compile_state_cls is not None:
(
statement,
execution_options,
) = compile_state_cls.orm_pre_session_exec(
self,
statement,
params,
execution_options,
bind_arguments,
_parent_execute_state is not None,
)
else:
bind_arguments.setdefault("clause", statement)
execution_options = execution_options.union(
{"future_result": True}
)
if _parent_execute_state:
events_todo = _parent_execute_state._remaining_events()
else:
events_todo = self.dispatch.do_orm_execute
if _add_event:
events_todo = list(events_todo) + [_add_event]
if events_todo:
orm_exec_state = ORMExecuteState(
self,
statement,
params,
execution_options,
bind_arguments,
compile_state_cls,
events_todo,
)
for idx, fn in enumerate(events_todo):
orm_exec_state._starting_event_idx = idx
result = fn(orm_exec_state)
if result:
return result
statement = orm_exec_state.statement
execution_options = orm_exec_state.local_execution_options
bind = self.get_bind(**bind_arguments)
...
按理说不应该报bind参数异常,后来仔细发现,实际上调用了flask-sqlalchemy中的get_bind()方法
def get_bind(self, mapper=None, clause=None):
"""Return the engine or connection for a given model or
table, using the ``__bind_key__`` if it is set.
"""
# mapper is None if someone tries to just get a connection
if mapper is not None:
try:
# SA >= 1.3
persist_selectable = mapper.persist_selectable
except AttributeError:
# SA < 1.3
persist_selectable = mapper.mapped_table
info = getattr(persist_selectable, 'info', {})
bind_key = info.get('bind_key')
if bind_key is not None:
state = get_state(self.app)
return state.db.get_engine(self.app, bind=bind_key)
return SessionBase.get_bind(self, mapper, clause)
应该是组件间版本不兼容导致,直接修改源码为:
def get_bind(self, mapper=None, clause=None, bind=None):
"""Return the engine or connection for a given model or
table, using the ``__bind_key__`` if it is set.
"""
# mapper is None if someone tries to just get a connection
if mapper is not None:
try:
# SA >= 1.3
persist_selectable = mapper.persist_selectable
except AttributeError:
# SA < 1.3
persist_selectable = mapper.mapped_table
info = getattr(persist_selectable, 'info', {})
if bind is not None:
state = get_state(self.app)
return state.db.get_engine(self.app, bind=bind)
bind_key = info.get('bind_key')
if bind_key is not None:
state = get_state(self.app)
return state.db.get_engine(self.app, bind=bind_key)
return SessionBase.get_bind(self, mapper, clause, bind)
重新运行,问题解决
或者直接从github上拉取最新代码安装:
git clone https://github.com/pallets/flask-sqlalchemy.git
python .\setup.py install