9

SQLAlchemy ORM 教程中,以下代码作为将映射到表的类的示例给出:

>>> from sqlalchemy import Column, Integer, String
>>> class User(Base):
...     __tablename__ = 'users'
...
...     id = Column(Integer, primary_key=True)
...     name = Column(String)
...     fullname = Column(String)
...     password = Column(String)
...
...     def __init__(self, name, fullname, password):
...         self.name = name
...         self.fullname = fullname
...         self.password = password
...
...     def __repr__(self):
...        return "<User('%s','%s', '%s')>" % (self.name, self.fullname, self.password)

如果name,fullnamepassword由用户在__init__实例化类时在方法中设置,那么将它们声明为Column对象(即作为类变量)有什么意义?我不明白 SQLAlchemy 如何以及何时能够使用这些信息 - 它是否通过User继承自的“Base”类以某种方式传递给 SQLAlchemy 模块?(我认为不可能以这种方式将信息传递给一个单元——通过声明一个从另一个类继承的类)。

4

1 回答 1

37

首先,你应该明白

class Foo(object):
    bar = ['baz']

class Foo(object):
    def __init__(self):   
        self.bar = ['baz']

意味着非常不同的东西,在第一种情况下,bar是类属性,对于 的所有实例都是相同的Foo,而类Foo本身(它是 的实例type,不是Foo),但在第二种情况下,bar是每个实例的属性的Foo,并且根本与类无关!。如果您同时尝试并附加到bar,对于第一个,更改将传播到 的每个实例Foo,但对于第二个,只有您附加到的实例才会具有该更改。

你甚至可以同时设置!,你可以这样做:

class Foo(object):
    bar = 'baz'

    def __init__(self):   
        self.bar = 'quux'

这是完全没有争议的。 Foo.bar == 'baz', Foo().bar == 'quux', 并且您可以从实例返回类属性type(Foo()).bar == 'baz'

所以这意味着__init__教程中的参数适用于 的实例User,但Column定义适用于类

Sqlalchemy 主要使用信息。它使用它,以便它可以生成以正确方式读取和写入数据库的 SQL。这些定义仅在 sqlalchemy 将实例转换User为数据库调用或尝试创建User从数据库接收行时的实例时才真正适用。

您应该将类​​属性视为声明类型,将实例属性视为设置值

至于sqlalchemy何时真正使用该信息的问题,其中有一个特殊的魔法Base,几乎可以肯定是来自sqlalchemy.ext.declarative.declarative_base(). 该函数返回一个,并且该类使用一个元类,该元类可以跟踪何时定义了派生自Base的新类。在类定义的最后,甚至在创建 的实例之前User,sqlalchemy 就会查看User类以查找它需要了解的列属性。

于 2013-10-08T21:23:33.653 回答