SQLAlchemy 找不到类名

问题描述 投票:0回答:10

简化后,我有以下类结构(在单个文件中):

Base = declarative_base()

class Item(Base):
    __tablename__ = 'item'
    id = Column(BigInteger, primary_key=True)
    # ... skip other attrs ...

 class Auction(Base):
     __tablename__ = 'auction'
     id = Column(BigInteger, primary_key=True)
     # ... skipped ...
     item_id = Column('item', BigInteger, ForeignKey('item.id'))

     item = relationship('Item', backref='auctions')

我从中得到以下错误:

sqlalchemy.exc.InvalidRequestError
InvalidRequestError: When initializing mapper Mapper|Auction|auction, expression
    'Item' failed to locate a name ("name 'Item' is not defined"). If this is a
    class name, consider adding this relationship() to the Auction class after
    both dependent classes have been defined.

我不确定Python如何找不到Item类,因为即使传递类而不是字符串形式的名称,我也会得到相同的错误。我一直在努力寻找如何与 SQLAlchemy 建立简单关系的示例,因此如果这里有一些相当明显的错误,我深表歉意。

python sqlalchemy pyramid relationships
10个回答
47
投票

这一切都是因为我在 Pyramid 中设置 SQLAlchemy 的方式所致。本质上,您需要严格遵循本节,并确保使用相同的

declarative_base
实例作为每个模型的基类。

我也没有将数据库引擎绑定到我的

DBSession
,这不会打扰您,直到您尝试访问表元数据(这在您使用关系时会发生)。


26
投票

如果是子包类,则将

Item
Auction
类添加到子包中的
__init__.py


22
投票

SQLAlchemy 文档中关于 导入所有 SQLAlchemy 模型的部分内容:

但是,由于 SQLAlchemy 的“声明式”配置模式的行为,需要先导入所有包含活动 SQLAlchemy 模型的模块,然后才能成功使用这些模型。因此,如果您使用具有声明性基础的模型类,您需要找到一种方法来导入所有模型模块,以便能够在您的应用程序中使用它们。

导入所有模型(和关系)后,有关找不到类名的错误就解决了。

  • 注意:我的应用程序不使用 Pyramid,但适用相同的原则。

12
投票

我的案例

在单独的文件中定义两个模型,一个是

Parent
,另一个是
Child
,与外键相关。当尝试在芹菜中使用
Child
对象时,它给出了

sqlalchemy.exc.InvalidRequestError: When initializing mapper Mapper|Child|child, expression 'Parent' failed to locate a name ("name 'Parent' is not defined"). If this is a class name, consider adding this relationship() to the <class 'app.models.child'>

parent.py

from app.models import *


class Parent(Base):
    __tablename__ = 'parent'

    id = Column(BigInteger, primary_key=True, autoincrement=True)
    name = Column(String(60), nullable=False, unique=True)
    number = Column(String(45), nullable=False)

child.py

from app.models import *


class Child(Base):
    __tablename__ = 'child'

    id = Column(BigInteger, primary_key=True, autoincrement=True)
    parent_id = Column(ForeignKey('parent.id'), nullable=False)
    name = Column(String(60), nullable=False)

    parent = relationship('Parent')

解决方案

Parent
 的开头添加 
child.py

的导入语句

child.py(已修改)

from app.models import *
from app.models.parent import Parent  # import Parent in child.py


class Child(Base):
    __tablename__ = 'child'

    id = Column(BigInteger, primary_key=True, autoincrement=True)
    parent_id = Column(ForeignKey('parent.id'), nullable=False)
    name = Column(String(60), nullable=False)

    parent = relationship('Parent')

为什么这有效

SQLAlchemy 中模型加载的顺序不固定。
因此,就我而言,

Child
Parent
之前加载。因此,SQLAlchemy 无法找到
Parent
是什么。因此,我们只是在加载
Parent
之前导入了
Child


5
投票

我通过继承“db.Model”而不是“Base”解决了同样的错误......但我正在做烧瓶

例如:

from flask_sqlalchemy import SQLAlchemy

db = SQLAlchemy()


class someClass(db.Model):
    someRelation = db.relationship("otherClass")

4
投票

此外,即使这不适用于OP,对于任何登陆此处并遇到相同错误的人,请检查以确保您的表名中没有破折号。

例如,名为“movie-genres”的表在 SQLAlchemy 关系中用作辅助表将生成相同的错误

"name 'movie' is not defined"
,因为它只会读取破折号。切换到下划线(而不是破折号)可以解决问题。


1
投票

我的解决方案

一个模型文件,如果需要,甚至更多。

模型.py

from sqlalchemy import Boolean, BigInteger, Column, DateTime, Float, ForeignKey, BigInteger, Integer, String
from sqlalchemy.orm import relationship
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()

from .parent import Parent 
from .child import Child 

parent.py

from sqlalchemy import Boolean, BigInteger, Column, DateTime, Float, ForeignKey, BigInteger, Integer, String
from sqlalchemy.orm import relationship
from sqlalchemy.ext.declarative import declarative_base

#Base = declarative_base()

class Parent(Base):
    __tablename__ = 'parent'

    id = Column(BigInteger, primary_key=True, autoincrement=True)
    name = Column(String(60), nullable=False, unique=True)
    number = Column(String(45), nullable=False)

child.py

from sqlalchemy import Boolean, BigInteger, Column, DateTime, Float, ForeignKey, BigInteger, Integer, String
from sqlalchemy.orm import relationship
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()

class Child(Base):
    __tablename__ = 'child'

    id = Column(BigInteger, primary_key=True, autoincrement=True)
    parent_id = Column(ForeignKey('parent.id'), nullable=False)
    name = Column(String(60), nullable=False)

    parent = relationship('Parent')

为什么这有效

相同的 Deepam 答案,但只需一个 models.py 文件即可导入另一个模型


0
投票

我有一个不同的错误,但这里的答案帮助我解决了它。

我收到的错误:

sqlalchemy.exc.InvalidRequestError: When initializing mapper mapped class Parent->parents, expression 'Child' failed to locate a name ('Child'). If this is a class name, consider adding this relationship() to the <class 'parent.Parent'> class after both dependent classes have been defined.

我的设置与Deepam的答案类似

简单介绍一下我所做的不同之处:

  • 每个 db.Model 有多个单独的 .py 文件。
  • 我使用构造/填充数据库 .py 文件,以多线程或单线程方式预填充 db.Model 对象

导致错误的原因:

  • 仅在多线程设置时出现错误
  • 这个构造/填充 .py 脚本确实导入了 Parent,但没有导入 Child。

修复了什么:

  • 向 Child 添加导入修复了该问题。

0
投票

我还有另一个解决方案,但这帮助我找到了线索。我试图使用“https://docs.sqlalchemy.org/en/14/orm/examples.html#versioning-objects”来实现版本控制History_mapper”类。

我也遇到了同样的错误。要解决这个问题,我所要做的就是更改模型导入的顺序。


-1
投票
使用 back_populates 在两个模型中进行关系映射。 另请记住将两个模型导入

models/__init__.py


Base = declarative_base() class Item(Base): __tablename__ = 'item' id = Column(BigInteger, primary_key=True) # ... skip other attrs ... auctions = relationship('Auction', back_populates='item') class Auction(Base): __tablename__ = 'auction' id = Column(BigInteger, primary_key=True) # ... skipped ... item_id = Column('item', BigInteger, ForeignKey('item.id')) item = relationship('Item', back_populates='auctions')
    
© www.soinside.com 2019 - 2024. All rights reserved.