SQLAlchemy 找不到类名

发布于 2025-01-01 08:56:21 字数 934 浏览 2 评论 0原文

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

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 建立简单关系的示例,因此如果这里有一些相当明显的错误,我深表歉意。

Simplified, I have the following class structure (in a single file):

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')

I get the following error from this:

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.

I'm not sure how Python cannot find the Item class, as even when passing the class, rather than the name as a string, I get the same error. I've been struggling to find examples of how to do simple relationships with SQLAlchemy so if there's something fairly obvious wrong here I apologise.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(11

愛上了 2025-01-08 08:56:21

事实证明,这一切都是因为我在 Pyramid 中设置 SQLAlchemy 的方式所致。本质上,您需要遵循本节并确保使用相同的 declarative_base 实例作为每个模型的基类。

我也没有将数据库引擎绑定到我的 DBSession 上,这不会打扰您,直到您尝试访问表元数据(这在您使用关系时会发生)。

This all turned out to be because of the way I've set SQLAlchemy up in Pyramid. Essentially you need to follow this section to the letter and make sure you use the same declarative_base instance as the base class for each model.

I was also not binding a database engine to my DBSession which doesn't bother you until you try to access table metadata, which happens when you use relationships.

此生挚爱伱 2025-01-08 08:56:21

如果是子包类,则在子包中的__init__.py中添加ItemAuction类。

if it's a subpackage class, add Item and Auction class to __init__.py in the subpackage.

郁金香雨 2025-01-08 08:56:21

关于导入所有 SQLAlchemy 的 SQLAlchemy 文档模型部分指出:

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

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

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

The SQLAlchemy documentation on Importing all SQLAlchemy Models states in part:

However, due to the behavior of SQLAlchemy's "declarative" configuration mode, all modules which hold active SQLAlchemy models need to be imported before those models can successfully be used. So, if you use model classes with a declarative base, you need to figure out a way to get all your model modules imported to be able to use them in your application.

Once I imported all of the models (and relationships), the error about not finding the class name was resolved.

  • Note: My application does not use Pyramid, but the same principles apply.
风和你 2025-01-08 08:56:21

我的案例

在单独的文件中定义两个模型,一个是 Parent,另一个是 Child,与一个外键相关。当尝试在 celery 中使用 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 添加导入语句code> 位于 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。因此,我们只是在加载 Child 之前导入了 Parent

Case with me

Two models defined in separate files, one is Parent and the other is Child, related with a Foreign Key. When trying to use Child object in celery, it gave

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')

Solution

Add an import statement for Parent in beginning of child.py

child.py (modified)

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')

Why this worked

The order in which models get loaded is not fixed in SQLAlchemy.
So, in my case, Child was being loaded before Parent. Hence, SQLAlchemy can't find what is Parent. So, we just imported Parent before Child gets loaded.

把昨日还给我 2025-01-08 08:56:21

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

例如,一个名为“movie-genres”的表,然后在 SQLAlchemy 关系中用作辅助表,将生成相同的错误 “name 'movie' is not Define”,因为它只会读为直到破折号。切换到下划线(而不是破折号)可以解决问题。

Also, even though this doesn't apply to the OP, for anyone landing here having gotten the same error, check to make sure that none of your table names have dashes in them.

For example, a table named "movie-genres" which is then used as a secondary in a SQLAlchemy relationship will generate the same error "name 'movie' is not defined", because it will only read as far as the dash. Switching to underscores (instead of dashes) solves the problem.

前事休说 2025-01-08 08:56:21

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

例如:

from flask_sqlalchemy import SQLAlchemy

db = SQLAlchemy()


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

I've solved the same error by inheriting a 'db.Model' instead of 'Base'... but I'm doing the flask

Eg:

from flask_sqlalchemy import SQLAlchemy

db = SQLAlchemy()


class someClass(db.Model):
    someRelation = db.relationship("otherClass")
俏︾媚 2025-01-08 08:56:21

我的解决方案

一模型文件,甚至更多(如果您需要)。

models.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 文件即可导入另一个模型

My Solution

One models file, or even further, if you need.

models.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')

Why this worked

Same Deepam answer, but with just one models.py file to import another models

不醒的梦 2025-01-08 08:56:21

我遇到了同样的问题,我通过为每个模型使用相同的基础来解决它们。

from sqlalchemy.orm import declarative_base
Base = declarative_base()

导入此底座并用于所有模型。

I had the same issue, i solved them by using the same Base for every models.

from sqlalchemy.orm import declarative_base
Base = declarative_base()

Imported this Base and used in all the models.

听不够的曲调 2025-01-08 08:56:21

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

我收到的错误:

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 脚本执行了导入父级,但不导入子级。

修复原因:

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

I had a different error, but the answers in here helped me fix it.

The error I received:

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.

My set-up is similar toDeepam's answer.

Briefly what I do different:

  • I have multiple separate .py files for each db.Model.
  • I use a construct/fill database .py file that pre-fills db.Model objects in either Multi-threading or single threading way

What caused the error:

  • Only in multi-threaded set up the error occured
  • This construct/fill .py script did import Parent, but not Child.

What fixed it:

  • Adding an import to Child fixed it.
蓝天 2025-01-08 08:56:21

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

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

I had yet another solution, but this helped clue me in. I was trying to implement versioning, from https://docs.sqlalchemy.org/en/14/orm/examples.html#versioning-objects using the "history_mapper" class.

I got this same error. All I had to do to fix it was change the order in which my models were imported.

萌辣 2025-01-08 08:56:21

使用 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')

Use back_populates for relationship mapping in both models.
Also keep in mind to import both the models in the 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')
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文