4 ms·
One of many things I love about SQLAlchemy (or could I say the data mapper pattern) is that it doesn't try to map the column of underlying schema one-to-one to
by sirn 11y ago
One of many things I love about SQLAlchemy (or could I say the data mapper pattern) is that it doesn't try to map the column of underlying schema one-to-one to the object model. This pattern allow for much more flexibility for building the object model compared to say, the active record pattern.
For example, in SQLAlchemy there is `column_property`[1] which allows me to do something like:
class User(Model):
id = Column(Integer, primary_key=True)
first_name = Column(String(50))
last_name = Column(String(50))
name = column_property(first_name + " " + last_name)
Querying this model will yield the SQL among the line of:
SELECT
user.id,
user.first_name,
user.last_name,
user.first_name || " " || user.last_name AS anon1
FROM users;
This example may not seems very useful (and of course joining a string in the database is not very exciting), but the same pattern could also be used for doing subqueries with SQLAlchemy Core[2], e.g.
User.post_count = column_property(
select([func.count()]).where(Post.user_id == User.id)
)
Which yields:
SELECT
user.first_name,
user.last_name,
(SELECT COUNT(*) AS count_1 FROM post WHERE post.user_id = user.id) AS anon_1
FROM users;
How SQLAlchemy decouple the object model from the schema and only map them after they are retrieved makes its ORM very flexible and powerful. Ability to easily building SQL is one thing, but how SQLAlchemy is designed to allow me to embrace SQL when necessary rather than trying to hide everything away from me makes me really love it.
[1]: http://docs.sqlalchemy.org/en/rel_1_0/orm/mapping_columns.html#using-column-property-for-column-level-options http://docs.sqlalchemy.org/en/rel_1_0/orm/mapping_columns.ht...
[2]: http://docs.sqlalchemy.org/en/rel_1_0/core/tutorial.html http://docs.sqlalchemy.org/en/rel_1_0/core/tutorial.html
- ajford 11y agoTIL... Thanks for this. I've been using SQLA for about 2 years for various side projects and one-offs, and I've never run across this. I've usually implemented things like this in python, which sometimes involves tedious looping and mapping and extraneous queries. Thanks!
- itsybitsycoder 11y agoIn this example, if you select a user object "Bob Smith" and then set first_name="Jim" but haven't flushed yet, will name be "Bob Smith" or "Jim Smith"? I haven't worked much with column properties but based on how unflushed relations+foreign keys work, I'm guessing it'll still be "Bob Smith"? With a normal @property it would return "Jim Smith".
- sirn 11y agoYes, in that case it would still be Bob Smith.