与列“ xy”关联的外键无法...生成目标列“ None”的外键

Kam*_*r04 3 python sqlalchemy

我正在使用SQLAlchemy和SQLite创建我的第一个数据库项目。我想将两个实体连接为关系数据库的关系模型。来源如下:

class Models(Base):
   __tablename__ = "models"

   id_model = Column(Integer, primary_key=True)
   name_of_model = Column(String, nullable = False)
   price = Column(Integer, nullable = False)

   def __init__(self, name_of_model):
      self.name_of_model = name_of_model

class Cars(Base):

   __tablename__ = "cars"

   id_car = Column(Integer, primary_key=True)
   id_equipment = Column(Integer, nullable = False)  
   id_package = Column(Integer, nullable = False)

   id_model = Column(Integer, ForeignKey('Models'))
   model = relationship("Models", backref=backref('cars', order_by = id_model))
Run Code Online (Sandbox Code Playgroud)

我想建立这样的关系:https : //imgur.com/af62zli

发生的错误是:

The foreign key associated with column 'cars.id_model' could not find table 'Models' with which to generate a foreign key to target column 'None'.
Run Code Online (Sandbox Code Playgroud)

任何想法如何解决这个问题?

Sup*_*oot 5

文档

参数to ForeignKey最常见的是形式的字符串 <tablename>.<columnname>,或者是远程模式中的表或形式的“所有者” <schemaname>.<tablename>.<columnname>。它也可能是一个实际的Column对象...

在定义您的ForeignKeyon时,Cars.id_model您传递了类名('Models')的字符串形式,这不是可接受的形式。

但是,您可以使用以下选项之一成功定义外键:

ForeignKey(Models.id_model)
Run Code Online (Sandbox Code Playgroud)

这使用实际Column对象来指定外键。这种方法的缺点是,您需要在名称空间中添加该列,这会增加将模型导入模块中的复杂性(如果未在该模块中定义),并且还可能使您担心模型的实例化顺序。这就是为什么使用基于字符串的选项之一更为普遍的原因,例如:

ForeignKey('models.id_model')
Run Code Online (Sandbox Code Playgroud)

请注意,此示例不包括类名的字符串版本(不是M odels.id_model),而是包括表名的字符串版本。字符串版本意味着所需的表对象仅在需要时才解析,因此避免了处理的复杂性Column对象本身。

在这种情况下有效的另一个有趣示例:

ForeignKey('models')
Run Code Online (Sandbox Code Playgroud)

如果两个表上两个列的名称相同,则SQLAlchemy似乎从表中推断出该列。如果您更改id_model示例中任一列定义的名称,以使它们的名称不同,则该列定义将停止工作。另外,我还没有找到足够好的文档,而且它不够明确,因此不确定是否真的值得使用,是否只是出于完整性而提及,因为我发现它很有趣。ForeignKey._column_tokens()关于columnarg的可接受格式,源代码中的注释似乎比文档更明确:

    # A FK between column 'bar' and table 'foo' can be
    # specified as 'foo', 'foo.bar', 'dbo.foo.bar',
    # 'otherdb.dbo.foo.bar'. Once we have the column name and
    # the table name, treat everything else as the schema
    # name.
Run Code Online (Sandbox Code Playgroud)