Die*_*ira 18 python postgresql sqlalchemy python-2.7
我有SQL Alchemy的问题,在尝试创建数据库时,我得到:
"sqlalchemy.exc.NoReferencedTableError:与列'estate_agent.person_id'关联的外键无法找到用于生成目标列'id'的外键的表'person'"
元数据:
db = create_engine('postgresql+psycopg2:...//')
meta = MetaData()
meta.bind = db
Run Code Online (Sandbox Code Playgroud)
人员表:
tbl_person = Table(
'person', meta,
Column('id', Integer, Sequence('seq_person_id'), primary_key=True),
Column('name', String(100), unique=True, nullable = False),
Column('password', String(40), nullable = False),
Column('person_type_id', Integer, ForeignKey("person_type.id"), nullable = False),
Column('register_date', DateTime, default = datetime.now),
Column('pendencies', String(200)),
Column('active', Boolean, default = True),
schema = 'public')
Run Code Online (Sandbox Code Playgroud)
错误表:
tbl_estate_agent = Table(
'estate_agent', meta,
Column('person_id', Integer, ForeignKey("person.id"), primary_key = True),
Column('prize_range_id', Integer, ForeignKey("prize_range.id"), nullable = False),
schema = 'public')
Run Code Online (Sandbox Code Playgroud)
普通表(通常创建fk)
tbl_person_agent = Table(
'person_agent', meta,
Column('person_id', Integer, ForeignKey("person.id"), primary_key = True),
Column('prize_range_id', Integer, ForeignKey("prize_range.id"), nullable = False),
schema = 'public')
Run Code Online (Sandbox Code Playgroud)
创作电话:
meta.create_all(checkfirst=True)
Run Code Online (Sandbox Code Playgroud)
完整的错误日志:
回溯(最近一次调用最后一次):文件"database_client.py",第159行,在meta.create_all(checkfirst = True)文件"/usr/local/lib/python2.7/dist-packages/sqlalchemy/sql/schema. py",第3404行,在create_all tables = tables中)文件"/usr/local/lib/python2.7/dist-packages/sqlalchemy/engine/base.py",第1616行,在_run_visitor中conn._run_visitor(visitorcallable,element ,**kwargs)文件"/usr/local/lib/python2.7/dist-packages/sqlalchemy/engine/base.py",第1245行,在_run_visitor**kwargs).traverse_single(element)文件"/ usr/local/lib/python2.7/dist-packages/sqlalchemy/sql/visitors.py",第120行,在traverse_single中返回meth(obj,**kw)文件"/usr/local/lib/python2.7/dist- packages/sqlalchemy/sql/ddl.py",第699行,in visit_metadata collection = [t for sort in sort(tables)File"/usr/local/lib/python2.7/dist-packages/sqlalchemy/sql/ddl.py",第862行,在sort_tables {'foreign_key':visit_foreign_key })文件"/usr/local/lib/python2.7/dist-packages/sqlalchemy/sql/visitors.py",第256行,在遍历返回traverse_using(iterate(obj,opts),obj,visitor)文件"/ usr/local/lib/python2.7/dist-packages/sqlalchemy/sql/visitors.py",第247行,在traverse_using meth(target)文件中"/usr/local/lib/python2.7/dist-packages/sqlalchemy /sql/ddl.py",第853行,在visit_foreign_key中parent_table = fkey.column.table文件"/usr/local/lib/python2.7/dist-packages/sqlalchemy/util/langhelpers.py",第725行,在在/ sort {'foreign_key':visit_foreign_key})文件"/usr/local/lib/python2.7 dist-packages/sqlalchemy/sql/visitors.py",第256行,在遍历返回traverse_using(iterate(obj,opts),obj,visitor)文件"/usr/local/lib/python2.7/dist-packages/sqlalchemy /sql/visitors.py",第247行,在traverse_using meth(target)文件"/usr/local/lib/python2.7/dist-packages/sqlalchemy/sql/ddl.py",第853行,在visit_foreign_key中parent_table = fkey.column.table文件"/usr/local/lib/python2.7/dist-packages/sqlalchemy/util/langhelpers.py",第725行,in在/ sort {'foreign_key':visit_foreign_key})文件"/usr/local/lib/python2.7 dist-packages/sqlalchemy/sql/visitors.py",第256行,在遍历返回traverse_using(iterate(obj,opts),obj,visitor)文件"/usr/local/lib/python2.7/dist-packages/sqlalchemy /sql/visitors.py",第247行,在traverse_using meth(target)文件"/usr/local/lib/python2.7/dist-packages/sqlalchemy/sql/ddl.py",第853行,在visit_foreign_key中parent_table = fkey.column.table文件"/usr/local/lib/python2.7/dist-packages/sqlalchemy/util/langhelpers.py",第725行,in/usr/local/lib/python2.7/dist-packages/sqlalchemy/sql/visitors.py",第256行,在遍历返回traverse_using(iterate(obj,opts),obj,visitor)文件"/ usr/local/lib/python2.7/dist-packages/sqlalchemy/sql/visitors.py",第247行,在traverse_using meth(target)文件中"/usr/local/lib/python2.7/dist-packages/sqlalchemy/sql/ddl .py",第853行,在visit_foreign_key中parent_table = fkey.column.table文件"/usr/local/lib/python2.7/dist-packages/sqlalchemy/util/langhelpers.py",第725行,在/usr/local/lib/python2.7/dist-packages/sqlalchemy/sql/visitors.py",第256行,在遍历返回traverse_using(iterate(obj,opts),obj,visitor)文件"/ usr/local/lib/python2.7/dist-packages/sqlalchemy/sql/visitors.py",第247行,在traverse_using meth(target)文件中"/usr/local/lib/python2.7/dist-packages/sqlalchemy/sql/ddl .py",第853行,在visit_foreign_key中parent_table = fkey.column.table文件"/usr/local/lib/python2.7/dist-packages/sqlalchemy/util/langhelpers.py",第725行,在/usr/local/lib/python2.7/dist-packages/sqlalchemy/sql/ddl.py",第853行,在visit_foreign_key中parent_table = fkey.column.table文件"/usr/local/lib/python2.7/dist -packages/sqlalchemy/util/langhelpers.py",第725行,in/usr/local/lib/python2.7/dist-packages/sqlalchemy/sql/ddl.py",第853行,在visit_foreign_key中parent_table = fkey.column.table文件"/usr/local/lib/python2.7/dist -packages/sqlalchemy/util/langhelpers.py",第725行,in得到 obj.dict [self.name ] = result = self.fget(obj)文件"/usr/local/lib/python2.7/dist-packages/sqlalchemy/sql/schema.py",第1720行,在列tablekey中)sqlalchemy.exc.NoReferencedTableError:与列'estate_agent.person_id'相关联的外键无法找到用于生成外键以定位列'id'的表'person'
Mat*_*sen 21
解决方案是用实际列替换字符串:
Column('person_id', Integer, ForeignKey(tbl_person.c.id), primary_key=True)
Run Code Online (Sandbox Code Playgroud)
swi*_*mer 12
尽管投票最高的答案解决了问题,但用对象替换字符串会迫使您按特定顺序定义表(对于非常大的数据库来说,这可能很重要)。来自SQLAlchemy 文档:
使用字符串的优点是,[不同表]之间的 in-python 链接仅在第一次需要时才会解析,因此表对象可以轻松地分布在多个模块中并以任何顺序定义。
您可以通过将架构传递到ForeignKey
. 例如,不要这样做:
tbl_estate_agent = Table(
'estate_agent', meta,
Column('person_id', Integer, ForeignKey("person.id"), primary_key = True),
Column('prize_range_id', Integer, ForeignKey("prize_range.id"), nullable = False),
schema = 'public')
Run Code Online (Sandbox Code Playgroud)
一个人可以做:
tbl_estate_agent = Table(
'estate_agent', meta,
Column('person_id', Integer, ForeignKey("public.person.id"), primary_key = True),
Column('prize_range_id', Integer, ForeignKey("public.prize_range.id"), nullable = False),
schema = 'public')
Run Code Online (Sandbox Code Playgroud)
通过在我的parent
表中添加以下行解决了我的问题.在声明的情况下:
children = relationship("Child")
Run Code Online (Sandbox Code Playgroud)
否则:SQLAlchemy - Classic Mapper
也试着看看这里(SO)也许有帮助.
小智 7
这个异常是因为MetaData实例中没有父表的记录,需要在DB中检索该表。调用MetaData类的reflect函数获取DB上所有存在的表。应该这样使用
def upgrade(migrate_engine):
meta.bind = migrate_engine
meta.reflect() # <------ Obtain all tables here.
aggregate_metadata.create()
aggregate_hosts.create()
Run Code Online (Sandbox Code Playgroud)
一个表与另一个具有关联外键的表位于不同的文件中。这种情况下sqlalchemy建表时会找不到对应的表,如下图:
sqlalchemy.exc.NoReferencedTableError:与列“aggregate_metadata.aggregate_id”关联的外键找不到用于生成目标列“id”外键的表“aggregates”
例如:
# File 002_Add_aggregates_table.py
# ========================================
...
meta = MetaData()
aggregates = Table('aggregates', meta,
...
Column('id', Integer, primary_key=True, nullable=False),
mysql_engine='InnoDB',
mysql_charset='utf8'
)
def upgrade(migrate_engine):
meta.bind = migrate_engine
aggregates.create()
Run Code Online (Sandbox Code Playgroud)
# File 003_Add_aggregate_metadata_hosts.py
# ========================================
...
meta = MetaData()
aggregate_metadata = Table('aggregate_metadata', meta,
...
Column('aggregate_id', Integer, ForeignKey('aggregates.id'), # <------ ForeignKey
nullable=False),
mysql_engine='InnoDB',
mysql_charset='utf8'
)
def upgrade(migrate_engine):
meta.bind = migrate_engine
aggregate_metadata.create()
Run Code Online (Sandbox Code Playgroud)
让我们定位到抛出异常的位置
File "/opt/xxx/.local/lib/python3.6/site-packages/sqlalchemy/util/langhelpers.py", line 1113, in __get__
obj.__dict__[self.__name__] = result = self.fget(obj)
File "/opt/xxx/.local/lib/python3.6/site-packages/sqlalchemy/sql/schema.py", line 2394, in column
tablekey,
sqlalchemy.exc.NoReferencedTableError: Foreign key associated with column 'aggregate_metadata.aggregate_id' could not find table 'aggregates' with which to generate a foreign key to target column 'id'
Run Code Online (Sandbox Code Playgroud)
我们可以找到对应的代码并进行调试:
# File: sqlalchemy/sql/schema.py
2358 def column(self):
...
2371
2372 if isinstance(self._colspec, util.string_types):
2373
2374 parenttable, tablekey, colname = self._resolve_col_tokens()
# =========> BeginDebug
2375 raise Exception(
2376 'imgrass->\n'
2377 ' - parenttable: %s\n'
2378 ' - parenttable.metadata: %s\n'
2379 ' - tablekey: %s\n'
2380 ' - colname: %s' % (
2381 parenttable,
2382 parenttable.metadata,
2383 tablekey,
2384 colname
2385 )
2386 )
# =========> EndDebug
2387
2388 if tablekey not in parenttable.metadata:
2389 raise exc.NoReferencedTableError(
2390 "Foreign key associated with column '%s' could not find "
2391 "table '%s' with which to generate a "
2392 "foreign key to target column '%s'"
2393 % (self.parent, tablekey, colname),
2394 tablekey,
2395 )
Run Code Online (Sandbox Code Playgroud)
然后我们可以得到以下异常:
Exception: imgrass->
- parenttable: aggregate_metadata
- parenttable.metadata: MetaData(bind=Engine(mysql+pymysql://imgrass:***@172.17.0.1/demo))
- tablekey: aggregates
- colname: id
Run Code Online (Sandbox Code Playgroud)
因此,parenttable.metadata是类MetaData的实例,tablekey是表名。我们可以合理地猜测表聚合应该包含在类MetaData的实例中。考虑到该表的定义在另一个文件中,并且MetaData实例具有DB(bind=xxx)的连接方式,所以MetaData类中应该有一个函数来获取DB中的所有表。
在MetaData中,我们可以找到这个函数
File "/opt/xxx/.local/lib/python3.6/site-packages/sqlalchemy/util/langhelpers.py", line 1113, in __get__
obj.__dict__[self.__name__] = result = self.fget(obj)
File "/opt/xxx/.local/lib/python3.6/site-packages/sqlalchemy/sql/schema.py", line 2394, in column
tablekey,
sqlalchemy.exc.NoReferencedTableError: Foreign key associated with column 'aggregate_metadata.aggregate_id' could not find table 'aggregates' with which to generate a foreign key to target column 'id'
Run Code Online (Sandbox Code Playgroud)
从它的描述中,我们可以猜测它的功能,让我们将它应用到我的脚本中:
# File: sqlalchemy/sql/schema.py
2358 def column(self):
...
2371
2372 if isinstance(self._colspec, util.string_types):
2373
2374 parenttable, tablekey, colname = self._resolve_col_tokens()
# =========> BeginDebug
2375 raise Exception(
2376 'imgrass->\n'
2377 ' - parenttable: %s\n'
2378 ' - parenttable.metadata: %s\n'
2379 ' - tablekey: %s\n'
2380 ' - colname: %s' % (
2381 parenttable,
2382 parenttable.metadata,
2383 tablekey,
2384 colname
2385 )
2386 )
# =========> EndDebug
2387
2388 if tablekey not in parenttable.metadata:
2389 raise exc.NoReferencedTableError(
2390 "Foreign key associated with column '%s' could not find "
2391 "table '%s' with which to generate a "
2392 "foreign key to target column '%s'"
2393 % (self.parent, tablekey, colname),
2394 tablekey,
2395 )
Run Code Online (Sandbox Code Playgroud)
没关系!
归档时间: |
|
查看次数: |
19196 次 |
最近记录: |