Code/Example
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
If I run print(Base)
then I get result:
<class 'sqlalchemy.ext.declarative.api.Base'>
(Ie Base
is a class created by the function declarative_base
).
If I run print(Base.metadata)
then I get
Metadata(bind=engine(postgres//:user:password@host/database))
But exactly how does print(Base.metadata)
even run if Base
is a class and metadata
is an object?
How are the two connected?
I could understand if metadata was a class attribute but from what I understand it is not so how does this work?
Is there something in python syntax that I have missed?
Looking in metadata code:
from sqlalchemy import MetaData
metadata = MetaData()
What is here the definition of metadata
and MetaData
? Are they both objects? Is MetaData()
a function or something else?
According to SQLAlchemy documentation MetaData
is:
a container object that keeps together many different features of a database (or multiple databases) being described.
But if it is an object so then how can it be run as something similar to a function: Metadata()
?
Base
and metadata
connected if one is a class and the other is an object?Base.metadata
) be run?metadata
and MetaData
and what is the MetaData()
definition? You are overthinking this. In Python everything is an object . Classes, functions, instances, numbers, strings, lists, dictionaries, modules, ..., everything .
The SQLAlchemy objects you are looking at are no different, there really is nothing special about these.
Yes, the declarative_base()
function returns a new class object, one you assigned to the name Base
. That class has attributes, and one of those attributes is named metadata
. All Python classes have attributes, they can point to any object you like:
class Foo:
def __init__(self, name):
self.name = name
def print(self):
print(f"Hello, {self.name}!")
class Bar:
spam = Foo("World")
The above class Bar
has an attribute spam
that is an instance of the class Foo
. You can call methods on it:
>>> Bar.spam.print()
Hello, World!
Note that Bar
is still a class, and Bar.spam
is an instance of the Foo
class:
>>> Bar
<class '__main__.Bar'>
>>> Bar.spam
<__main__.Foo object at 0x10d43c650>
>>> type(Bar.spam)
<class '__main__.Foo'>
Because Bar
is just another object, you can also pass it around, put it in a list, or return it from a function. declarative_base()
constructed a class object for you, with attributes, and returned it to the caller.
Similarly, Base.metadata
is just an instance of the MetaData
class:
>>> type(Base.metadata)
<class 'sqlalchemy.sql.schema.MetaData'>
and so is your metadata = MetaData()
object.
Note that if you only run Base = declarative_base()
and nothing else, the MetaData
instance is not actually showing any database connection information:
>>> Base.metadata
MetaData(bind=None)
That's because you didn't actually connect the metadata to a database session. Once you start connecting a database with an engine and start using the models you define by subclassing Base
, the metadata object at some point will need to know more about the specifics of the database (such as what kind of SQL dialect is supported) and it'll be bound by SQLAlchemy.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.