表'roles_users'已经为此MetaData实例定义

The*_*gon 18 python sqlalchemy

你好我想在我的视图中获取currnet_user信息

我从users.models导入包含*

然后在我的代码中返回return current_user;

@app.route('/panel')
@login_required
def access_panel():
    return current_user.email;
Run Code Online (Sandbox Code Playgroud)

一旦我运行我的服务器它说

Traceback (most recent call last):
  File "manage.py", line 6, in <module>
    from nadel import app
  File "/Users/tbd/Desktop/Projects/nadel/__init__.py", line 27, in <module>
    from users import views
  File "/Users/tbd/Desktop/Projects/nadel/users/views.py", line 5, in <module>
    from users.models import *
  File "/Users/tbd/Desktop/Projects/nadel/users/models.py", line 8, in <module>
    db.Column('role_id', db.Integer(), db.ForeignKey('role.id')))
  File "/Library/Python/2.7/site-packages/flask_sqlalchemy/__init__.py", line 67, in _make_table
    return sqlalchemy.Table(*args, **kwargs)
  File "/Library/Python/2.7/site-packages/sqlalchemy/sql/schema.py", line 398, in __new__
    "existing Table object." % key)
sqlalchemy.exc.InvalidRequestError: Table 'roles_users' is already defined for this MetaData instance.  Specify 'extend_existing=True' to redefine options and columns on an existing Table object.
Run Code Online (Sandbox Code Playgroud)

在我的模型中我有

from nadel import db
from flask.ext.security import UserMixin, RoleMixin


# Define models
roles_users = db.Table('roles_users',
        db.Column('user_id', db.Integer(), db.ForeignKey('user.id')),
        db.Column('role_id', db.Integer(), db.ForeignKey('role.id')))

class Role(db.Model, RoleMixin):

    id = db.Column(db.Integer(), primary_key=True)
    name = db.Column(db.String(80), unique=True)
    description = db.Column(db.String(255))

class User(db.Model, UserMixin):
    id = db.Column(db.Integer, primary_key=True)
    email = db.Column(db.String(255), unique=True)
    name = db.Column(db.String(255))
    password = db.Column(db.String(255))
    active = db.Column(db.Boolean())
    #confirmed_at = db.Column(db.DateTime())
    last_login_at = db.Column(db.DateTime())
    current_login_at = db.Column(db.DateTime())
    last_login_ip = db.Column(db.String(32))
    current_login_ip = db.Column(db.String(32))
    login_count = db.Column(db.Integer)

    roles = db.relationship('Role', secondary=roles_users,
                            backref=db.backref('users', lazy='dynamic'))
Run Code Online (Sandbox Code Playgroud)

直到现在我还不明白为什么我得到这个错误,如何解决它,请指导我解决问题

N. *_*est 13

当我通过复制粘贴以前的类来创建一个新类时,我遇到了这个错误。结果我忘记更改__tablename__,所以我有两个具有相同__tablename__属性的类。这导致了错误,更改属性解决了它。


Sha*_*ger 11

我有一个类似的错误。我的问题是db.Model使用相对导入导入从两个不同文件继承的类。Flask-SQLAlchemy将两个导入映射为两个不同的表定义并尝试创建两个表。我通过在两个文件中使用绝对导入路径解决了这个问题。

  • 遇到了完全相同的问题,我相对导入一次“db.Model”,一次绝对导入一次。 (4认同)

小智 10

我的名字是雅各布。我也有同样的情况。

问题是这样的:当您在同一代码中导入父表和子表时会发生这种情况。然后导入CHILD表,CHILD表将父表的结构也带入元数据中。所以你不需要再次导入 PARENT 表。

解决方案是这样的:您需要重新排列代码中导入 ORM 结构的顺序。该顺序基于父+子关系。

示例:以下会产生错误:

import CHILD_ORM
import PARENT_ORM   
Run Code Online (Sandbox Code Playgroud)

重新排列顺序如下,以防止错误:

import PARENT_ORM   
import CHILD_ORM
Run Code Online (Sandbox Code Playgroud)


Spc*_*ond 8

这取决于您要执行的操作,是否要:

  1. 删除旧的类并用新的类映射替换它?要么,
  2. 保留旧课程,然后重新启动应用程序?

在使用上面的示例的第一种情况下,请在定义类之前尝试运行以下行:

db.metadata.clear()
Run Code Online (Sandbox Code Playgroud)

原因是第一次通过定义python类来声明SQLAlchemy映射时,该类的定义将保存到元数据对象中,以防止将多个定义映射到同一表而导致冲突。

调用该clear()方法时,将清除Metadata对象保存在内存中的所有表定义,这使您可以再次声明它们。

在第二种情况下,当您刚刚重新启动应用程序时, 我将使用reflect方法编写一个测试以查看表是否已存在:

db.metadata.reflect(engine=engine)
Run Code Online (Sandbox Code Playgroud)

在哪里engine是使用创建的数据库连接create_engine(),请查看您的表是否已存在,并且仅在未定义表的情况下定义类。

  • 是否也可以仅清除特定表而不是所有表? (3认同)

Sha*_*ank 8

它晚了一年但如果有人没有在给定的答案中找到解决方案可能是这可以解决问题-

我的类有同样的问题,它是从 db.Model(flask_sqlalchemy)继承的。

我的代码看起来像这样 -

class MasterDB(db.Model):
    __tablename__ = 'masterdb'
    __table_args__ = {'schema': 'schema_any'}
    ...
    ...
Run Code Online (Sandbox Code Playgroud)

通过在类变量列表中将抽象属性指定为 True来解决它。像这样将它添加到类变量列表中,它应该可以工作 -

class MasterDB(db.Model):
    __tablename__ = 'masterdb'
    __table_args__ = {'schema': 'schema_any'}
    __abstract__ = True
Run Code Online (Sandbox Code Playgroud)


小智 6

尝试添加:

__table_args__ = {'extend_existing': True}

就在下面 __tablename__

参考: https: //docs.sqlalchemy.org/en/13/orm/extensions/declarative/table_config.html ? highlight = table_args

  • 这个解决方案可能有效,但如果有效,它很可能掩盖了其他问题 - 我建议在将其作为创可贴放在表类上之前探索其他选项。 (6认同)
  • 这个解决方案有效,但我有兴趣了解它的实际作用。 (3认同)
  • 这会修改数据库中的表还是仅修改表对象? (2认同)

Jun*_*Kim 6

TL; 博士

  • 如果您在尝试将烧瓶蓝图注册到应用程序时遇到此错误,请检查模型导入路径在导入模型的所有蓝图中是否一致

例如

  • 蓝图1: from A.B.C import Model A
  • 蓝图 2:(from .B.C import Model A这会引发错误,导入相同模型的所有蓝图的导入路径应该一致。所以应该是from A.B.C import Model A

我还没有挖掘这个问题来找出原因,但我猜 SQLAlchemy 使用其导入的命名空间管理模型,并在定义不同的命名空间但模型相同时引发错误。


小智 -1

我使用 jupyter 笔记本看到了同样的错误。我正在从存储在磁盘上的库导入 sqlalchemy 表类,并且定义中存在错误。修复错误后,我重新运行导入并看到此错误。只需重新启动 jupyter 内核,然后重新运行导入即可解决该问题。