在SQLAlchemy ORM tutorial中,以下代码作为将映射到表的类的示例给出:
>>> 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
,fullname
和password
由用户在实例化类时__init__
方法设置,那么将它们声明为{{ 1}}对象(即作为类变量)?我不明白SQLAlchemy是如何以及何时能够使用这些信息的 - 它是以某种方式通过Column
继承的'Base'类传递给SQLAlchemy模块的? (我认为不可能以这种方式将信息传递给一个单元 - 通过声明一个继承自另一个类的类。)
答案 0 :(得分:20)
首先,你应该明白
class Foo(object):
bar = ['baz']
和
class Foo(object):
def __init__(self):
self.bar = ['baz']
意思是非常不同的东西,在第一种情况下,bar
是一个类属性,它对于Foo
的所有实例都是相同的,而类Foo
本身(它是一个type
的实例,而不是Foo
),但在第二个中,bar
是Foo
的每个实例的属性,并且根本与该类无关! 。如果您同时尝试两者,并且附加到第一个bar
,则更改将传播到Foo
的每个实例,但对于第二个实例,只有您追加的实例才会进行更改。< / p>
你甚至可以设置两个!,你可以这样做:
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
中有一些特殊的魔法,几乎可以肯定来自{{ 1}}。该函数返回类,该类使用元类,它可以跟踪何时定义了从sqlalchemy.ext.declarative.declarative_base()
派生的新类。在类定义结束时,甚至在创建Base
的实例之前,sqlalchemy会查看User
类以查找它需要了解的列属性。