Reputation: 101
I am having problems understanding the benefit of the usage of declarative classes in SQLAlchemy.
As I understand the ORM is a way to apply the concept of database tables to the class system of OOP. However I don't understand why the table class doesn't already satisfy this requirement.
So to form my question via an example:
What is the benefit of using this:
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
from sqlalchemy import Column, Integer, String
class User(Base):
__tablename__ = 'users'
id = Column(Integer, primary_key=True)
name = Column(String(16))
fullname = Column(String(60))
nickname = Column(String(50))
Instead of this:
from sqlalchemy import *
metadata = MetaData()
user = Table('users', metadata,
Column('id', Integer, primary_key=True),
Column('name', String(16)),
Column('fullname ', String(60)),
Column('nickname ', String(50))
)
The latter one is already a class representation, isn't it? Why are we building another class over the already existing table class? What's the benefit?
Upvotes: 1
Views: 2185
Reputation: 790
You can say DeclarativeBase
is anther layer on top of Table
that has those Benefits:
1 - Simplicity and Readability
Declarative Mapping combines table definitions and class behavior into one place, reducing boilerplate code.
Example (Declarative Base):
class User(Base):
__tablename__ = 'users'
id = Column(Integer, primary_key=True)
username = Column(String, unique=True)
email = Column(String, unique=True)
Classical Mapping Equivalent:
users_table = Table(
'users', metadata,
Column('id', Integer, primary_key=True),
Column('username', String, unique=True),
Column('email', String, unique=True)
)
class User:
pass
mapper(User, users_table)
Declarative Example:
class Post(Base):
__tablename__ = 'posts'
id = Column(Integer, primary_key=True)
user_id = Column(Integer, ForeignKey('users.id'))
user = relationship('User', back_populates='posts')
Classical Mapping Equivalent:
posts_table = Table(
'posts', metadata,
Column('id', Integer, primary_key=True),
Column('user_id', Integer, ForeignKey('users.id'))
)
mapper(Post, posts_table, properties={
'user': relationship(User, back_populates='posts')
})
3- Extensibility Declarative Base allows easy extension through mixins and custom attributes.
class TimestampMixin:
created_at = Column(DateTime, default=datetime.utcnow)
updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
class User(Base, TimestampMixin):
__tablename__ = 'users'
id = Column(Integer, primary_key=True)
username = Column(String, unique=True)
Upvotes: 0
Reputation: 51
I have the same question recently, you can refer to SQLAlchemy doc.
Some examples in the documentation still use the classical approach, but note that the classical as well as Declarative approaches are fully interchangeable.
I think the benefit of using Declarative Mapping is that,
Upvotes: 3