Of course, you can use whatever other libraries you want in your own code, but at the point where you are not using Django's ORM and you have left its lame template system for something like mako (or maybe genshi, especially if you are generating XML), then what is Django really giving you?
That makes it a non-starter for us (for now).
For example:
In Rails, you can say
Article.find(:all, :include => :comments)
and that will get you the articles with their comments. In Django, you can say for a in Article.objects.all():
a.comments #hits the database again! argh!
Before you say, "Django has select_related() which does the same thing as Rails!" select_related() doesn't work in any useful way. select_related() only works on the side that defines the foreign key - so you can get the single article that a comment belongs to, but you can't get the comments on an article without running another query. Yeah, that simple, basic, every ORM should support it case isn't handled. And it's maddening.Forms handling and validation is another sore spot. Some validation happens in the model, some in the form, ModelForms does somethings, but not others, editing related objects is a mess. In some ways it's shocking that it's such a mess considering how awesome the admin interface is. However, I always find myself manually dealing with forms to a point that's just annoying.
The lack of a true "if" in the templates. It's just limiting in a way that I don't find useful and I find that it makes my code less clear by nesting things in weird ways to get the desired effect.
Stagnation. Django is awesome, but sometimes it takes forever for small things to go anywhere because there's a genuine hesitance in the community to "dictators". By dictators, I mean personalities like DHH who say, "well, this way works and is elegant and we're going to go with it." On the one hand, it's what makes Django really attractive as a community. Rails attracts the know-it-all personalities. Maybe DHH and Zed do know it all, but most Rails programmers definitely don't. People in the Django community are really helpful, respectful of other's knowledge, and love learning from each other. However, it also means that even tiny features must be rehashed over and over, filed in triplicate, lost, found, stamped, checked by a committee of 8, rewritten from scratch, named new-X or X-refactor, break API compatibility, and finally get into SVN. Ok, most of that was a joke, but there are lots of little areas where it just seems like Rails is willing to move on something based on the general mood where Django wants a more formal assessment and wait period before deciding whether something is ok to be in or not. And for all people complain about DHH's one-way-to-do-it mentality and Django's more open structure, Rails isn't so closed and Django not so open.
Django's big selling points (for me) are that there's a ton of python out there that's beautiful, reliable code and the admin interface that allows you to deal with content neatly and easily. Clearly there are other selling points like MVC and ORM and whatnot, but there are many frameworks that have that. Django is a lot easier to understand (at least for me) in its implementation. Django's documentation is top notch which is amazing compared to other projects, but Rails is catching up with their guides and screencasts. Django also tends to document things like their file backend hooks better which makes creating plugin-type things easier, but again Rails (with the help of the Merb team) is going to be a ton better in this area.
You won't go wrong with Django. The only fatal flaw is really the first one and it's just unacceptable at this point in time. But it's a great set of code with a wonderful community. I don't think there's another framework I'd prefer. Maybe Rails, but nothing else.
Article.objects.all().extra(select={'comment_count': 'SELECT count(*) FROM blog_comment WHERE blog_comment.article_id = blog_article.id'})
But I can't populate a list of comments objects onto it.I've talked to Malcom about it (who wrote the QuerySet Refactor branch - or at least a substantial portion) and it's a known deficiency. Basically, the issue is two-fold. First, no one has stepped up to write the code that would make select_related() work in that fashion. Second, people want the implementation to disallow certain bad situations.
The first part is self-explanatory: select_related() should be enhanced to support that, but someone needs to write the code. The second part isn't as much, but it's more interesting.
Let's say you execute this query:
SELECT * FROM articles LEFT OUTER JOIN comments ON comments.article_id = articles.id
How many rows will you get from that? You'll get somewhere in the vicinity of the number of comments (adding a row for any article without comments). Suffice it to say, the results set grows linearly in proportion to the number of articles and comments.Now let's say we have this:
SELECT * FROM articles LEFT OUTER JOIN comments ON comments.article_id = articles.id LEFT OUTER JOIN votes ON votes.article_id = articles.id
So, we have our article with comments, but also votes now. So, let's say we want to get just one article that has 100 comments and 200 votes. How many lines will that return? In the original SQL query, we would have seen 100 lines (one for each comment) which would have been manageable. Here, we get 100 * 200 lines back. That's 20,000 rows to parse to build a single Article object!So, the Django folk aren't into letting you just hang yourself out to dry like that. There have been proposals to limit it in ways that wouldn't let you do that, but it's really just something genuinely missing and there isn't a way to do it other than running looped queries or doing something ugly.
extra() doesn't do the same thing as select_related(). I'm not saying that doing ORM over multi-valued relationships is easy or that you can't execute queries that are really bad doing them, but it still means that there isn't support for a pretty basic function.