Rails is full of sloppy coding, lots of magic, coders who think that return is an keyword, and bad practices. I have no problem with ruby as a language, even if it takes flexibility a step too far, however the style of coders, and the general "I did something clever and unreadable so I'm awesome" attitude seems to permeate the ruby-verse. Also while many improvements have been made on the ruby interpreters... the performance is STILL lagging behind Python, which as a dynamic language with compiled backend elements, gives languages like Java a run for their money.
Both systems are very powerful, Django has certain batteries included that I find it strange that rails fails to do (namely a plugabble extensible flexible user authentication system) and both have their adherents.
The writer of this original piece is clearly not very up on Django development, the strong community apparently how to write well implemented MVC code. Having spent years working with a variety of frameworks, I've yet to find a place where Django stops you doing what you want (unless its a fundamentally stupid idea).
It's hard to benchmark these things with accuracy and impartiality, but there's not a significant gap between them anymore. For example (see JRuby here):
http://shootout.alioth.debian.org/u32/which-programming-lang...
I just ran an identical-technique-almost-identical-code recursive fibonacci benchmark against Python 2.6.1, Ruby 1.9.2, and JRuby 1.6.1 and got times of 17.4s, 7s, and 3.2s respectively. (Undoubtedly you could find benchmarks where Python wins, but this is an interesting test of a common algorithm nonetheless.)
Perhaps in real world tests there are places where performance can be made up, but at its core, Python isn't showing much improvement over Ruby nowadays until you start to use things like PyPy (which is, I admit, totally awesome).
Depends. It's needed for non-local returns (returning from within blocks), and it's also useful for early returns within methods.
It's not needed for the final return of a method, or a normal exit from a block (not a bad thing in my opinion, and Python's lambda do the same)
What makes you think it isn't?
https://code.djangoproject.com/wiki/RemovingTheMagic
I think your experience with Rails (and the community) may be a little out of date. Check out wycats' changes in Rails 3.0 to see where most of the cleanup happened. There's a lot less magic than there used to be.
As far as authentication and admin sections, I guess it just depends on your preferences for which pieces should be included in a framework and which users should have a choice over. Authentication is often app-specific enough that it's hard to drop in different solutions and have them act equivalently.
The admin is not the auth system, you are not forced to use it and in fact its disabled by default in every single django startup app. I've in the past done my own functionality pages, and would use Admin when it was most suitable.
Personally I haven't seen anything in Rails 3.0 that makes me think "ooh this is a killer feature" the only thing that rails had over Django was migrations, and South closed that hole up years ago.
I'm going to to reinvestigate Rails 3 soon, however my concerns with magic are related as much to the coding style as the overal magical structure. One of the reasons I understand Django so well is the well written code, the other being that it is clean and well designed as a system.
I highly recommend it.
[1] http://pragprog.com/book/jvrails/crafting-rails-applications
"The community is pretty much dead." - not from where I'm standing. I live in a tech-savvy town and there seems to be more Django devs here than Rails devs. Of course - it's not a popularity contest otherwise PHP would be the best web framework ;-)
"All my Django projects ended up being a big mess" - that used to be the case with my own code but by reading other people's code (and the Django source) I've improved hugely. Should you be blaming your tools?
"And the community in general seems to agree" - the Django community agrees that Django sucks? Or did you mean the web dev community in general? If so - can you back that up with anything more substantial?
PHP is not a web framework like Django, it's a language like Python.There are however, many good Django like PHP frameworks.
Just wanted to clarify.
Look at how it started, as personal home page template processing scripts in Perl, and you'll see it started with much more in common with a templating tool or web framework than with a formal language.
"PHP/FI was created by Rasmus Lerdorf in 1995, initially as a simple set of Perl scripts for tracking accesses to his online resume. He named this set of scripts 'Personal Home Page Tools'. As more functionality was required, Rasmus wrote a much larger C implementation, which was able to communicate with databases, and enabled users to develop simple dynamic Web applications..."
"PHP/FI, which stood for Personal Home Page / Forms Interpreter, included some of the basic functionality of PHP as we know it today. It had Perl-like variables, automatic interpretation of form variables and HTML embedded syntax."
But to your point, he also said: "I've never thought of PHP as more than a simple tool to solve problems."
It's clumsy, inflexible and restrictive.
Pretty much anything can be swapped out with custom code. Need a custom auth backend? Just write a class. Need custom session backends? Just write a class. Need to customise a certain view of an application? Just override the url. Don't like the ORM? Just use something else. Have special caching needs? Write a backend.
A look at the release notes are full of good things and following them is definitely worth it. Since 1.3 you've got class based views that make it dead easy to create RESTful views for example. There's new logging support, you can have multiple databases with different backends.
The community is pretty much dead.
It's true that there was a lot more blogging happening in the earlier days. I suspect that the community is simply busy building new things - but a look at the CheeseShop shows on any day a healthy amount of new and updated Django components. Right now there are 7 Django projects on the main page.
All my Django projects ended up being a big mess, and I had to undjango my way out of the various restrictions it placed on me.
I'm a big fan of how Django creates structure through its applications. It makes it very easy to build parts of functionality on a plug and play basis and use them across projects.
Django offers a lot of functionality and it can be difficult to pick the right ones being a newcomer. But once you get the hang around applications and repositories and start working with "advanced" Django and Python features and apps like the built in signals, Celery, Fabric, GUnicorn, etc building and deploying apps becomes a breeze.
http://groups.google.com/group/django-users?pli=1
20245 Members, 126619 Threads
Last 12 hours, 14 new threads, 27 new messages
https://code.djangoproject.com/log/django/trunk
16546 changes, last change 28 hours ago.
> ....Django projects ended up being a big mess,
Are you sure it was not the result of the team you worked with, and not Django itself?
Everything else is hand wavy, but if you would bother to explain "clumsy, inflexible and restrictive" technically, I would be glad to respond technically.
I don't think that you can compare ANY Python framework (or any framework in any language) with Ruby on Rails. If you write Ruby, use RoR. If you write Python, don't use RoR.
Also, for anyone recommending something like Tornado, please stop. It's NOT THE SAME THING and completely off topic. If you want something micro for a small concise project use Flask.
Bottle has far fewer features than Django. It's hard to believe that Django is tripping you up if you aren't using its advanced features. You're welcome to discard the Django ORM, auth, models, and even have middleware return requests before it gets to django's router in some places.
I've had similar sentiments before, but ultimately I realized that I would have to fight with this kind of frustration no matter what tools I picked. The details would have been different, but my immaturity as a programmer would have been the same.
As time goes on I get better at substituting custom functionality if a framework doesn't do what I want. This can mean custom css, overriding templates, subclassing, or just placing my own objects in place of inbuilt functionality.
Finally, for a counter-example - not sure why convore split up and slowed down, but they were absolutely crushing it with Django when they first started. They were having Django handle some requests and a more low level server handle other requests (can't remember if it was Tornado or Twisted). There are countless other counter-examples.
However, when I've seen a Django project that's a "huge mess" that's largely due to the incompetence of the developer. A more "rails-y" framework probably suits such developers, as it gives them less leeway to screw up.
Following the herd means that there's a better chance that someone will have already solved any given problem you encounter and released documentation or a drop-in implementation.
I like the idea of Django/Bottle/etc. because I use Python for a lot of my non-web stuff. But RoR has a bigger and more active population. Unless there's something specific to your situation which changes this equation, you'll save yourself time and effort if you go with the more mainstream option.
And I actively reached out too, went to the IRC room, went to the forums, read the mailing list. And it feels dead, most blog posts with tutorials are years old and obsolete, there most of the applications we've tried to incorporate use deprecated methods. Its a real pain in the ass.
Not to mention the applications are all over the place, just look at this list https://code.djangoproject.com/wiki/DjangoResources#Djangoap... it has lots of components but most of the "suggested" are not on there? Even worse is that most of those links are to dead projects with no activity.
I would go with Flask, Bottle, or tornado and if you need an ORM go with sqlalchemy or Mongo.
/rant sorry its been a hard few months.
And remember some projects have little activity because they were born perfect :)
I think Django is a lot easier to get started with, but RoR is much more thought out.
OP should also read:
http://www.scribd.com/doc/37113340/Why-Django-Sucks-and-How-...
Which summarizes some of the problems I had with it. Getting components to work was always a custom job; a stark difference compared with the ease of getting Rails components to work.
It's a typical scenario really. On the surface it gives you a great framework for creating a website that works in a certain way but if you deviate from that you tend to find yourself in trouble.
In our case it was mostly the admin section that created the issues. I'm sure that if you know the framework well enough there are ways around the inflexibility but the fact of the matter is, the Django admin is heavily based on configuration. Where you have configuration you have limitations.
Things may have changed (it was about a year ago when I last worked with it) but at the time I struggled with simple things like; customising the auth system, easy debugging / error handling, clean outgoing email switching between dev / live, the templating system, etc. I seem to recall spending most of my time ripping code from the core framework into my views.py and tweaking it so I could get the behaviour the client was asking for.
As I say, it's been a while since I worked with it and I'm sure people have solutions to the issues I encountered but if you're planning on going off piste at all it's probably not for you.
The admin is amazingly malleable. Almost everything can be overridden and replaced. There's plenty of nice debugging/logging solutions (Werkzeug+Django Extensions being my favourite). Email switching between dev/producution is trivial (unless I'm misunderstanding you).
There ARE some clunky parts to customizing auth - mainly around extending the User model - but it's not that terrible.
Regarding the email stuff, my criteria for a framework is that I'd like it to send real emails on live and fake ones on dev. That is, email everything to me on dev along with a little header showing who the email was going to etc. Invaluable for testing.
settings.py is a mess. Even Simon's written a post bashing it (http://simonwillison.net/2009/may/19/djng/). I cringe a little starting up a project and having to dive into the settings.py file.
In some ways, Django tries to be flexible, but it's clumsy. For example, you can have your templates in your app directories. So, you have /path/to/project/posts/templates and /path/to/project/people/templates. However, you can't just put your templates in there because Django doesn't namespace them. Like, if I do {% extends "people/base.html" %} it will look in both those template directories for a people folder. It won't be like, "oh, I should look in /path/to/project/people/templates/base.html". I have to put the template in /path/to/project/people/templates/people/base.html. That's clumsy.
urls.py is another flexible/clumsy thing (IMO). Django wants me to write a regexp for the simple cases. It's kludgy to do r'^people/(?P<id>\d+)/?$' just to have a URL with an ID in it. And other frameworks have been able to offer the power of regexps for the case where you want them while making the common cases a lot easier.
Django caches certain things and if you try to change it at runtime, well, it doesn't change.
Django's reusable apps aren't that reusable. They were a lot more reusable than Rails' apps, but the Rails team has worked on that a lot - especially with 3.1 and how each app can have its own assets (images/css/js) all namespaced and neat and tidy. There isn't as much utility there as advertised. Like, if I want to use a Django "reusable" app, I often have to manage images/css/js manually, figure out where to put them, etc. This is one of those interesting ones. Like, I have my /var/projects/cool_project directory, but if I put the reusable app under that directory, then I need to have both /var/projects/ and /var/projects/cool_project in my pythonpath which feels wrong. It also feels wrong to put it directly in the projects dir since it isn't a project on its own.
Django doesn't really have init hooks. Like, you can stick random code into the models.py files for installed apps and they'll be loaded when the app is initialized and so you could set things then and, well, it's python so the __init__.py files should get loaded. However, no one seems to talk about it. Granted, almost no one in the Rails community talks about init files, but it seems a tad more common. I mean, it's Python and so clearly one can write Python, but while Django is extensively documented for what I'll call "blessed features", I wish there was a little more talk about making alterations at startup.
I never really warmed to Django's forms. They're fine, but they don't feel good. I hesitate to say this one because my argument is "they feel clumsy" and I'm sure many agree with that and many disagree with that.
Here's one that recently got resolved: nearly everyone had written their own wrapper around render_to_response so that they wouldn't have to do render_to_response('tpl_name.html', {}, context_instance=RequestContext(request)). In Django 1.3 they added the awesome render(request, 'tpl_name.html', {}). It's not even a big thing, but it felt so clumsy before to have to set a kwarg with such a long object name.
Rails has really settled on that Gemfile and you can use pip/virtualenv and requirements.txt, but it doesn't seem to be as much of a thing. Like, it isn't always about what can be done as much as what is done sometimes. Plus, the Gemfile makes the app require the libraries. I'd have to also add them to settings.py or somewhere else. And I'd potentially have to add it to INSTALLED_APPS and TEMPLATE_CONTEXT_PROCESSORS and MIDDLEWARE_CLASSES since you can't just install an app and have it work in those places without naming it specifically in settings.py
Here's a counter example. Let's say that no one agreed on what the main content block would be called in base templates - or that base templates would be "base.html". It would make templates from reusable apps useless since they might be {% extends "home.dj" %} or {% extends "layout.tpl" %}. They could have {% block main_content %}. It does matter what people do in practice sometimes.
Really? No migrations? I have to resort to a third-party project? I should have the SQL sent out to my terminal, go into my database, figure out the deltas and apply the SQL? While I'm on database stuff, would it kill Django to specify InnoDB and UTF-8 for MySQL when creating tables? I get it, most of them use PostgreSQL and I like PostgreSQL, but I'm not always using it and it's a sensible default to go with InnoDB and UTF-8 unless told otherwise - and loads of people don't know or forget to set that as the MySQL default.
Now, I could also write one of these about Rails if I wanted to. Anything that has worth will have plenty of warts. It's the nature of creation. I wouldn't write this unless I cared a lot about Django. I enjoy using it. But there will always be things I'm not fond of in it (or in Rails, or anything else - even if I created it).
For myself, the thing I don't like most about Django is the "well, we didn't think of it/need it and there's a third party project so, well, I guess we're not going to go there" situation that I feel sometimes. Now, I wanted to stress that this is a feeling more than something objectively accurate. Migrations are one of those things. User authentication, an admin section, a basic CMS, sitemaps, lorem ipsum, textile, markdown, restructured text, a list of US states, a comments framework, etc. all have made their way into Django. Now, those are some useful things. I don't need all of them on every project, but batteries are nice (even if they're those D batteries and I don't have a device that uses them). However, migrations are a tad fundamental. Likewise, it was many years before the messaging framework worked for non-logged-in users (like Rails' flash). Yes, many people had put out a little package that one could use, but (without something awesome like a Gemfile) it takes more than a little setup. I mean, it isn't arduous, but it isn't free. And the point of frameworks is what they do for you for free. Heck, someone posted on django-developers a couple months back about prepared statements (http://groups.google.com/group/django-developers/browse_thre...). If you've seen Aaron Patterson's presentation on Rails and prepared statements (http://www.youtube.com/watch?v=kWOAHIpmLAI), you can see the benefits of them. Prepared statements are in Rails 3.1. The message on django-developers seemed to get a very luke-warm response because Django has kinda decided that they don't want to deal with connection pooling - after all, there are already third party libraries for that (even if they aren't so integrated and require more user setup and work). So, the fact that Django doesn't want to deal with connection pooling means that the great speedup that could be had from prepared statements won't happen. And yes, I could put the patches on myself and when Django makes new releases re-apply the patches (and figure out if anything broke) and deal with potential edge cases where the patch wasn't right, etc. and set up a connection pooler and get my prepared statements and the speedup that comes with them. But that's kinda kludgy and feels restrictive. And for a framework that likes PostgreSQL, they're missing out on a large speed bump by not using the query planner effectively.
Again, I could make a list about Rails or any sufficiently large project (it's hard to criticize web.py or something since the retort would simply be "it isn't meant to do that"). This doesn't mean that Django is bad or that I dislike Django - it's quite the opposite. Personally, I don't care about things I don't like. People are free to do as they like. However, when there's something that I'm 95% "wow, that's awesome", the 5% that I'm like, "omg, this is crap" bothers me. I'm not sure if you were looking for a response to "what's so clumsy, restrictive, etc. that one shuldn't use it". If that was your question, well, I think people should use Django (and Rails). But just because something is good, doesn't mean that it doesn't have clumsy pieces that will annoy you.
My pet hate is contrib.auth - the models used feel seriously out of date and the whole get_profile() thing feels inefficient and hacky. Almost every client I work with does not want usernames but email login these days and I have to use the same damn workarounds each time. I get the feeling there were some bad decisions made early on in the project - maybe to work around the lack of model inheritance back then - and they've stuck, but still somehow need to be defended.
And yes, for crying out loud, South needs to be part of Django itself. This "we shouldn't have opinions" is a crock. Everyone who needs migrations uses South. When we don't have South but we have a highly opinionated - and practically useless - comments app, that argument doesn't hold water.
Like yourself, though, most of the time Django does what I need, I can make it work, and love 90% of it - the ORM, forms, middleware etc "fit my brain" and work nicely. But the framework still needs a lot of work and some serious wart removal.
"I often have to manage images/css/js manually, figure out where to put them, etc"
This has (yay!) been solved in 1.3 with the inclusion of the staticfiles app. I now just put my app-specific static stuff in static/ and then run manage.py collectstatic and all is well in the world :)
I'd completely missed it. Thanks!
It's a trivial thing to add, but its lack really hurts sometimes.
That one I completely disagree with, especially considering the idea of reusable applications.
While the repetition of 'people' does feel redundant at first glance, it means a second application can have its own `people/base.html` template which will be used instead of the one originally provided by `people`, and without needing any magical manipulation of paths/namespaces in the template loader. The path within the templates folder is completely independent from the path outside of it. And I think that's a fine behavior for the app_directories and the eggs loaders.
Furthermore, note that you could write your own template loader based on these which will do the namespace munging for you. How is that "Django tries to be flexible, but it's clumsy"?
FYI, I think the South authors are the ones preventing South being part of Django, not the Django maintainers.
I don't think either "side" (if there is such a thing as "sides" here -- South's lead developer has a commit bit on Django) wants to just transplant South into Django directly. The plan, which got hashed out secretly behind closed doors in a shadowy back room (on our public mailing list), is to work the low-level support for migration-ish stuff -- APIs for DB manipulation, etc. -- into Django, but not officially "bless" any particular high-level implementation.
Django is a Python framework. It has some nice features of Python like explicitness over implicitness rather than depending on a lot of magic. But in no way I feel it is a clumsy, inflexible or restrictive.
I like Tornado. In the overview (http://www.tornadoweb.org/documentation/overview.html), it gives you - auth (using OpenID), secure cookies, XSRF protection, templates, localization, UI modules (really basic, compared to generic views), running in prodution with Nginx, and aync programming. It doesn't have much database stuff (just a wrapper around MySQL), but you can use SQLAlchemy, or some other ORM.
Only the auth stuff feels over-engineered, because it uses async programming to call a general interface for Facebook OAuth, OpenID, Twitter OAuth, and so it's a bit of a dog's breakfast.
The "great documentation" is not and has never been the django book. It's the official documentation on the website.
> but the competitors have caught up
Uh... no it has not. Even in the Python sphere, where Sphinx and Django have led to drastic improvements in documentary quality. One of the few projects which could lay claim to that would be Pocoo's/Armin's (Flask, Werkzeug, Jinja) and in my experience the API still feels much more like APIDoc than the craft I feel when I read Django's docs.
As to Rails, it's still a joke. The first documentation link on the rails website is this: http://api.rubyonrails.org/
> But I personally dislike generic views. They just feel a little like magic, and a little over-engineered. They might be good for larger projects, but using them from the start feels like premature overengineering.
That sounds very strange, especially for the older non-class-based generic views: they provide very simple behavior and usually end up replaced over time as it's not possible to customize them sufficiently (a major reason why class-based generic views were introduced).
I have to say I'm not sold on the class-based generic views, they feel far more complex than the old ones (because they are) and the documentation does not help and does not remove that feeling of complexity.
It comes down to personal preference. To me Django was much easier, more flexible, and "funner" to work in.
If I have to use third party middleware or apps to deal with inadequacies of a framework, that's a pretty big alarm that something bigger is wrong.
I saw bottle just this past week on HN and I'm itching to give it a shot.
Everyone's app is different, and so Django is rightly agnostic as to how your settings are stored, and which are loaded.
As for the scope of the problem: dealing with multiple development settings is Section 1, Page 1 of professional programming. It's a solved and trivial problem. This isn't like coding your own ORM or templating language.
It's not trivial. In rails, it's trivial. The framework has knowledge of these separate states of applications. Deploying a serious, hardened service on top of Django is an order of magnitude more complicated than something like Rails.
Schema migrations are yes, a "solved" problem, if by "solved" you mean a third party application that isn't baked into the framework.
Having built a service that hosts Django apps, I can tell you that serious, hardened, services are not as trivial as you think to build with Django. There are countless headaches, and at this point it makes sense to use Rails over Django if you care about making your life easy.
I'm not saying Django isn't without its advantages, but those advantages tend to pale in comparison to some of the problems when you scale past 10 users of a trivial app like a blog.
> Deploying a serious, hardened service on top of Django is an order of magnitude more complicated than something like Rails.
That's funny. How so? I just start gunicorn, point nginx at it, and I'm ready to go. Of course, you could just as easily do it 500 other ways that might make sense to you more.
> Schema migrations are yes, a "solved" problem, if by "solved" you mean a third party application that isn't baked into the framework.
This is absolutely the most absurd thing you've said so far. South handles migrations very well, the code of of excellent quality, and I'm always thrilled to see incremental improvements come down the pipe when they're ready. I don't have to wait for a new Django release.
> Having built a service that hosts Django apps, I can tell you that serious, hardened, services are not as trivial as you think to build with Django. There are countless headaches, and at this point it makes sense to use Rails over Django if you care about making your life easy.
Completely unsupported drivel. We run two separate PCI compliant websites with well over 10k uniques a day per, and have had a pretty easy time of securing both. Django bakes in XSS and a lot of other protection with little to no effort. SQL injection attacks become all but impossible if you don't do anything goofy.
> I'm not saying Django isn't without its advantages, but those advantages tend to pale in comparison to some of the problems when you scale past 10 users of a trivial app like a blog.
Work we do for client spans in the many thousands of users. Django bears the load well, has kept ourselves and our clients safe for over four years now, and lets us develop and deliver quickly.
I'm sure you can do the same for RoR, but why dump on Django when you clearly don't have a firm grasp on it and/or Python?
PCI 4 is far different from PCI 1.
But I'm using Django DESPITE the fact that I have to use south. Contrast this with Rails, which FORCES you to use migrations (last I checked).
Third part != Lower quality. In this case, it means being able to make incremental improvements outside of the Django release schedule. So while Rails bakes it in and forces a release schedule on migrations, South isn't encumbered by this, and is more agile.
I'm not saying Django completely sucks -- I'm saying that in certain ways, it gets more and more complicated, rather than staying simple as you grow or build projects that need to scale.
Disqus is a clear outlier here, so I could be wrong. It just seems that every time I encounter a problem, someone says "It's easy to hack Django to fix this!" and that's the problem. I don't want to hack it -- I want it to work like that in the first place.
Pylons was AWESOME. I need to give Pyramid a try, I've heard great things.
I'm also certainly not badmouthing the contributors, I'm criticizing the framework's design. Which is something that's really hard to change after years of momentum.
Development and production settings is trivial with Django, so if you had problems with this, then I don't know what more I can say.
Lastly, there is a world of difference between developing a Django app and developing an company that deploys Django apps. There are some design decisions that were made in the beginning that makes the former easier and the latter more difficult. I think you're conflating the two.
In any case, I'm done with this thread.
I come to think that the Django team must have the Guido's time machine. If you need something, take a good look, the solution might be under your feet.
IMO, even though pylons 1.0 is now frozen, it is still one of the most flexible frameworks out there.
But truly, for beginners, it's top notch. Great teaching tool.
Hey everyone, can we get a top comment on this thread that is something other than nonsensical flamebait, please?
this ain't gonna work that way. if you know python, you will always find your way out by looking at the django code (there lie the best examples of how to write django.)
and if you have web development experience, you will recognize the time you've wasted on boilerplate stuff django gives you for free.
'nuf said.
maxklein, it seems u lack descent programming skills, since my experience with django is completely different. Most of the time the problem is with who codes, not the framework or tool.
Django (and Rails) both came from a time when the RDBMS ruled so they were built around an ORM and are very ORM centric. People are moving away from using a relational database and onto using Mongo or a graph database as the primary datastore.
Graphs are a much more elegant way of storing relational data, and so I prefer a framework that isn't so tied to the RDBMS. Now I use Flask as my Web framework and Bulbflow (http://bulbflow.com) to connect to the Neo4j graph database.
If you want to work in ruby, go for ror. If you want to work in python, go for a micro framework like Bottle.
I made the mistake of investing a lot of my time in Django. It was not worth it in the end. All my Django projects ended up being a big mess, and I had to undjango my way out of the various restrictions it placed on me.
And the community in general seems to agree - there is not much different in the django ecosystem, comparing 2 years ago to now.
My advice, go for Ruby On Rails or Bottle. Leave Django alone.