In the SQLAlchemy ORM tutorial the following code is given as an example of a class which will be mapped to a table:
>>> 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)
If name
, fullname
and password
are set by the user in the __init__
method when the class is instantiated, what's the point of having them declared as Column
objects (i.e as class variables)? I don't understand how and when SQLAlchemy is able to use the information - is it somehow passed to the SQLAlchemy module via the 'Base' class which User
is inheriting from? (I didn't think it was possible to pass information to a unit in this way - by declaring a class which inherits from another class).
first, you should understand that
class Foo(object):
bar = ['baz']
and
class Foo(object):
def __init__(self):
self.bar = ['baz']
Mean very different things, in the first case, bar
is a class attribute, it is the same for all instances of Foo
, and the class Foo
itself (which is an instance of type
, not Foo
), with but in the second, bar
is an attribute of each instance of Foo
, and is not associated with the class at all!. If you try both, and append to the bar
, for the first, the change will propagate to every instance of Foo
, but for the second, only the instance you appended to will have that change.
You can even set both!, you could do:
class Foo(object):
bar = 'baz'
def __init__(self):
self.bar = 'quux'
And that's totally unanbigious. Foo.bar == 'baz'
, Foo().bar == 'quux'
, and you can get back to the class attribute from instances with type(Foo()).bar == 'baz'
so that means that the arguments in __init__
in the tutorial, apply to instances of User
, but the Column
definitions apply to the class
Sqlalchemy uses the class information, primarily. It uses it so that it can generate SQL which reads from and writes to the database in the proper way. Those definitions only really apply in the cases when sqlalchemy is converting instances of User
to database calls, or trying to create instances of User
when it receives rows from the database.
You should regard the class attributes as declaring the types, and the instances attributes as setting the values.
As for the matter of when sqlalchemy actually uses that information, there is a special bit of magic in Base
, which is almost certainly from sqlalchemy.ext.declarative.declarative_base()
. That function returns a class, and the class uses a metaclass which can track when new classes which derive from Base
are defined. At the end of the class definition, even before you create instances of User
, sqlalchemy looks at the User
class to find the column properties it needs to know about.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With