14 comments

[ 1.3 ms ] story [ 43.0 ms ] thread
What is it with these mainstay frameworks that they never adopt the mature ORM on their respective platform but instead keep growing their own, less than half-baked alternative?

We have this in django vs SQLAlchemy and Rails vs datamapper.

The arguments that I've heard were mostly that the respective ORMs either weren't around when the framework started and/or that anyone "can just plug their preferred ORM in anyways". Neither really cuts it for me. Even in java-land (yes, java!) they make more sense in that regard - everyone just uses hibernate.

Well, however other than this unrelated rant (triggered by the mention of the removal of a most basic ORM-wart...); Good work django guys. :-)

Django's ORM existed before SQLAlchemy, and ActiveRecord existed before DataMapper.
Wow, actually had an article starred on this in the trusty Reader. http://jmoiron.net/blog/about-sqlalchemy-and-djangos-orm/

Money quote for me: "SQLAlchemy is a toolkit for python programmers who want or need to use a database to write programs that do so. Django's ORM is a tool for python programmers to quickly model business-level data relationships and use a database for persistent storage. This is really an important distinction; the Django ORM interface is focused on the application's data model, whereas SQLAlchemy's interface is focused on the underlying data store."

I feel that Django's ORM is one the main reasons for its success. Yes, it's limited and simplistic compared to something like Hibernate -- but that's actually a blessing in this context. People love Django because it makes it so simple to build an application quickly. Without the built-in ORM, things like admin and generic views would be harder to implement and certainly wouldn't work anywhere nearly as nicely out of the box.
Wasn't one of the major reasons for the giant Rails 3 switchover to allow datamapper or other ORM's to be used in place of activerecord?
Don't know about the Rails world so much. But Django's "loose coupling" allows you to use a different ORM if you see fit as well. Though that's to be dosed with salt to taste... you lose some fun automagic stuff like manage.py <load/dump>data, contrib.admin, sessions

A quick stackexchange search yielded a link here http://lethain.com/entry/2008/jul/23/replacing-django-s-orm-...

It's not so much that they couldn't be used before, but the coupling was so tight that there was a high burden on the maintainers to fix things when they broke.

With the creation of a stable internal API for all of these kinds of things, DataMapper can now be just as much of a first class citizen as ActiveRecord.

I love SQLAlchemy - it's an amazing piece of software, and I use it often. So why wouldn't I argue for Django to switch?

* I love Django's ORM, too. It's far simpler, much easier to teach to new users, and results in code that "scans" better. It's only able to achieve that ease-of-use by sacrificing features -- a classic trade-off. Neither approach is more "right."

* SQLAlchemy didn't exist when we wrote Django. Yes, you've just dismissed that argument, but I can't. There are thousands -- probably tens of thousands -- of Django sites out there, and I'm not so quick to break backwards compatibility just for the new shiny.

* Finally, and most importantly, SQLAlchemy has some fundamentally different goals than Django's ORM. SQLAlchemy aims to provide an API to represent SQL in Python. Django aims to provide a persistance layer for objects. The difference between these philosophies is important: the use of a relational database is almost an implementation detail for Django, but it's SQLAlchemy's raison d'être. This isn't just academic: it means, for example, that Django's ORM will one day support non-relational databases (work here's already begun), but SQLAlchemy won't.

Your last point is by far the most important. It looks like one of the goals for Django 1.4 will be more separation between the ORM and relational databases. Alex Gaynor speaks at length about the innards of today's querysets and how he suggests it could be changed to make sense with NoSQL: http://nosql.mypopescu.com/post/904840384/django-and-nosql-d...
Completely agree about "models.ForeignKey(on_delete=<CASCADE|PROTEXT|SET_NULL|SET_DEFAULT|SET()>" - really looking forward to that, it would have saved me a bunch of time and hassle in the past.
Before django implements new features it should rework some of the crappy old stuff:

Auth is terrible, models and forms need to be more flexible. Also a lot of little things like forms myform.as_div are missing.

"Django" doesn't implement new features: people do. In this case, Ben Firshman led a group of about a dozen or more to get generic views refactored, and Carl Meyer took point on the long-requested on_delete work.

They had itches to scratch, and they scratched them.

I agree that auth's gotten long in the tooth, but not enough to be motivated to work on it. The fact that it's stayed unresolved for so long indicates perhaps that most contributors feel similarly. That means that it's going to stay as it is until someone steps up, like Ben or Carl did, and takes the lead in getting something done.

Alternatively, I'm available for consulting work and would happily take money to work on any problem you like. My rates are fairly reasonable.

The problem with auth is that it was designed before model inheritance was available, hence the crappy get_profile() hack.

A better solution (with hindsight) would be a base abstract UserBase model with a bunch of useful features (e.g. password encryption) extended by a default User model, plus a UserForeignKey field similar to the one in GAE. Therefore instead of this:

    class BlogPost(models.Model):
        author = models.ForeignKey(User)
you would have this:

    class BlogPost(models.Model):
        author = UserForeignKey()
The exact user class would be set in your settings, e.g. AUTH_USER_MODEL = "myapp.MyUser".

That would provide more interop between Django apps requiring some form of user authentication. Not sure what other implications that would have though.