(Full disclosure: I'm a member of Django's core team)
There's no single "best" for every application. One-size-fits-none. One of Django's strengths is in the fact that parts of the framework come off easily when they no longer serve your needs. If the ORM is no longer working for you, you can use SQLAlchemy or write raw SQL. Authentication no longer working for you? Write your own or use a 3rd party one.
Et cetera. The key aspect is that you don't need to sacrifice the entire framework when only one part of it no longer addresses your needs. Keep in mind that 99% of sites never even reach this point.
The other major strength of django is the rich ecosystem of 3rd party apps. That's a lot of code you don't need to write yourself.
That being said, Flask is popular for a reason. Django offers a lot of power, which means adding some complexity to even the simplest projects (something we're working to address with features like project templates in Django 1.4). Flask fills a niche for a framework that is easy to get up and running and addresses 90% of the things which 90% of people need for many projects.
I've heard good things about pyramid, but haven't had a chance to play yet.
I haven't had the "pleasure" of working with web2py, and I'm not knocking the effort which Massimo puts into it, but the choices made there often elicit a raised eyebrow. Ignoring my opinion for a moment, the smartest web hackers I know universally regard web2py as a fundamentally incorrect way to approach web development—but usually say so in far more colorful terms.
TL;DR
* Flask for simpler stuff
* Django for anything larger, or simple stuff that leverages a 3rd-party app you need.
* What matters is the app you ship, not the framework it was built with.
* Django developers are in super-high demand. I get cold-called frequently.
> One of Django's strengths is in the fact that parts of the framework come off easily when they no longer serve your needs. If the ORM is no longer working for you, you can use SQLAlchemy. Authentication no longer working for you? Write your own or use a 3rd party one.
Yes and no (disclaimer: I mostly use Django for my development), while parts come off easily the tools provided by the framework are "standard" and taking them off usually means not being able to take advantages of many Django features, e.g. if you replace django's ORM with SQLAlchemy, you'll have to say goodbye to the admin or to ModelForms, if you don't use Django's auth then extensions to it (django-registration &al) will have to be torn-out and/or reimplemented, ...
So while theoretically you can remove things, it's not a straightforward process and it'll likely be a lonesome road.
I think you can use SQLAlchemy in the context of Django to assist creating custom & complex SQL queries. You don't necessarily have to use SQLAlchemy and replace Django's ORM.
One of my pet peeve with Django is the reliance on settings.py. This makes it a PITA to use Django's components in apps that aren't necessarily Django apps (or web apps for that matter).
For instance Ruby on Rails got separated in components and you can now import ActiveRecord in any project, without it being a Rails project or having a Rails project structure. Ditto for their database migrations ... you don't even need to use ActiveRecord to have the migrations DSL in a project. Doing this with Django's ORM is really, really ugly, mostly because of the reliance on a Django project structure. Why can't it be configured like any other Python library, in a pythonic way? Why does it need a global "settings" module?
Another pet peeve I've got is with the definition of an app. I hate what Django means by "app". It's totally un-pythonic. First of all the definition is unclear ... is it a module declared in settings.py? Not so fast, as some functionalities (e.g. manage.py test) expect those modules to have a "models" sub-module, even if it is empty.
Why does Django need apps anyway? It only needs apps for auto-discovery of model definitions. This goes back to Django's admin, which is a cool piece of software that I love, but how about declaring somewhere the modules that represent models, instead of building an unpythonic project structure?
I'm happy to hear that along with Django 1.4 you guys are working on project templates (really, that's awesome). But please strive to make it more pythonic / decoupled.
I use both and personally if I'd have to generalize I would say Django for simpler stuff and Flask for complex stuff.
Flask is great if you're going to do a complex app. All the interface will be custom designed (so the Django admin is of no use). You have a database heavy app, SQLAlchemy is more flexible than Django ORM and allows greater SQL expression, Unit of Work etc. Jinja2 is more flexible then Django templates (and faster). Flatland is more flexible than Django forms (supports nested forms for example).
That being said, Django is also great for some large apps and just for example it's great for news sites where new types of content is added each day and the admin interface saves a ton of time. For simple apps it's also brilliant because everything that's in Django works well together and you don't need the extra features of the aforementioned libraries.
So to sum up, both great frameworks and I use both every day :)
I'd just like to comment that, having built a medium to large Flask app over the last year, I would never recommend it as a framework for non-trivial sites.
I don't even want to sum up the amount of time that Django would have solved my problem instantly, but instead I had to pull my hair out dealing with Flask's global variables, circular dependency issues, and general lack of cohesion or standards. I think it's a great micro-framework if you're writing a one-python-file personal site or blog. Anything larger than that and you're going to regret it.
I disagree. Flask's thread locals have never been a problem for me and it's not like you can escape them, most frameworks use them in some form implicitly, for example both Django and Pyramid. The circular dependency in Flask hasn't been a problem either, once I wrapped my head around how to do it properly. Lack of standards I would say is still a bit of a problem, but Blueprints helped. I wouldn't say Django has this one quite figured out either though, and in general I usually have to do some heavy customization when using 3rd party Django apps with their own views and urls.
Are you building an API and a website? If yes, use Flask for the API and consume it from a Django site.
I wouldn't advocate using Django but ditching the ORM for SQLAlchemy, nor replacing the Auth, as noted (above or below my comment) it gets messy and becomes a lonely road fast.
I would advocate moving a lot (all?) of the model into a REST API, implemented in Flask, using SQLAlchemy. But perhaps my experience isn't as wide or deep as others.
I disagree on one point there... if you're building both an API and a website, there's no reason at all to use both Flask and Django. I can't imagine that the benefits would outweigh the disadvantages of having to deal with two frameworks instead of one.
I'd also argue in favour of ditching Django's auth. It's fine if your project has very simple auth requirements, but these days very few interesting projects have simple auth requirements - plus it's much easier to extend the functionality of your own Account models than to try and hook extra stuff on to Django's.
> I can't imagine that the benefits would outweigh the disadvantages of having to deal with two frameworks instead of one.
Separation of concerns, loose coupling.
I tended to find (in the few Django projects I worked on), that models were frequently accessed outside the app that created and owned the model. The subsequent dependency diagram would be spaghetti.
We had apps for each significant feature area, and when we wanted to drop a feature it was my desire to just remove an app.
It may well have been our implementation that was the problem (poorly separated concerns across apps), but we made great strides at solving these problems by using APIs to both force the de-coupling and to increase our confidence that our mobile clients (using the API) had the same capabilities available to them as the website (because no Django dev could cheat and make a call without the API existing).
Why Flask and not just Django again? That came down to personal preference over how clean it is to handle headers correctly (Accept headers, CORS and other things were fun), layout of the code and project, simplicity of testing, etc.
Mostly it was just subjective and personal preference, once we saw that the Django projects we had tended not to follow loose coupling, we used APIs as a way to increase our own discipline. Preferring that the architecture helped ensure the way we wanted to work on (and maintain) the code.
Auth we had already externalised (into the edge of the network, implemented within Varnish, similar to Flickr's GodAuth).
That's one of the fun issues with service oriented architecture.
You either choose high-chatter and low complexity, or low-chatter and high complexity. As high-chatter is also a decrease in performance (mostly due to JSON serialisation/deserialisation and HTTP requests), we opted for low-chatter.
Resources that were a composite of other resources had their own knowledge of how they were composed, and generated their own IDs to save that knowledge. Each new composition resource got it's own Accept header identifier as a result.
Within that composition resource, there wasn't just knowledge of "I'm composed of x:17 and y:3", but also knowledge of how to search across the underlying services. This could be to call search on the underlying service if one side of the composition was dominant in applying the filter to the dataset.
Where it was trivial, a search index belonging to the composed service was used. And because this duplicates data from the underlying resources, messaging was put into the underlying service to notify the composed service of changes that affect searches.
For simplicity you can just imagine that we had some kind of table in the composed service, with ID on each row that because the ID of the composed resource, and that we could search that table, and that messaging magic kept that table in sync.
We could do all of this because we owned all of the services. If we didn't, then I imagine we would have followed a similar path to http://ql.io/
Disagree, Django Rest Framework and TastyPie make REST APIs effortless: write Django models, register them with the REST plugin, hook the plugin to your main URL structure. They're a really good example of how Django enables reuse.
Implementation-wise they both hook into the model framework and the form framework, although you can swap out those parts if your data lives elsewhere.
There's flexibility. I've gotten a lot of mileage of closely-related models inlined into a parent model to form a single resource (resource relationships annotated with full=True with TastyPie), but one isn't limited to that either; http://django-tastypie.rtfd.org/ outlines the possibilities better than a short comment could.
The parent comment was only pointing out how incredibly fast and easy it is to get started with TastyPie. The moment you decide to create an API resource that isn't a one-to-one mapping with a database table or Model, TastyPie is still able to come with you every step of the way.
Sorry, but I wouldn't give up Django-TastyPie for anything else (including Flask) for API development. Sure, I could spend a month building an API framework from scratch in Flask for a project, but why would I?
I think another major strength of Django is its documentation. The docs for Django are some of the best I've ever seen for any open source project (or even commercial software for that matter). I don't see this mentioned often when people are comparing frameworks, but it's a big part of what made me choose Django in the first place.
> I haven't had the "pleasure" of working with web2py, and I'm not knocking the effort which Massimo puts into it, but the choices made there often elicit a raised eyebrow. Ignoring my opinion for a moment, the smartest web hackers I know universally regard web2py as a fundamentally incorrect way to approach web development—but usually say so in far more colorful terms.
I've just gone over the public discussions. They could basically be summarized in two points:
jacobian&ronacher dislike web2py's inclusion of a few new "builtins" (that is, they are builtins for a web2py applications). They used extremely colorful terms ("divisive! harmful!"), but that's essentially what it boils down to: It's fine that "len", "dict", and "list" are builtins, but it's horrible that web2py introduces a few more for web2py apps ("request", "response", "session", and a few others). Well, that's not much more than a difference of opinion. They feel very strongly about it, for some reason.
ronacher also dislikes web2py's use of "exec" for some reason. Almost all of his criticism is meritless (web2py precompiles for production, and the namespaces are used as he thinks they should be). The part that isn't, about classes with destructors leaking is valid, but it's a general Python "bug" that web2py potentially amplifies if you use it -- but it is not idiomatic in either Python or Web2py.
It's rather telling that every single strong criticism of web2py you can find on the web comes from someone who has never used it, and more often than not has some vested interest in a competing framework.
Web2py is not perfect, far from it -- but it is extremely well built, very robust, has a lively and helpful community, and gets things done quickly and well. Give it a try when you have the time and feeling curious.
So web2py introduces new members to __builtins__? Coming from a general Python programmer with no "vested interest" I have to say that isn't the best of ideas. len/dict/list are builtins because they are part of the language. They can be assumed to be present in any Python program. Teaching people that these web2py objects are available globally w/o importing them is setting a false expectation. This is pretty much monkey patching even if you aren't overriding stuff. Generally a no-no in the Python community.
No, notice that "builtins" was in quotes. web2py does not actually add new members to __builtins__. Rather, web2py executes model files, controllers, and views in a pre-defined environment that includes a number of web2py API objects (though not the entire API). This includes about a dozen core objects, such as request, response, session, and cache, plus a set of HTML helpers (all derived from the same class and named after their HTML counterparts) and a set of form validators (all derived from the same class). This is all very well documented.
People like you who have never actually used web2py routinely express concern that this will somehow set up false expectations and confuse people about how Python modules and imports work, but in practice this is simply not the case. Note, web2py also includes a number of modules that require explicit importing, and applications can include their own modules as well as import standard library and third-party modules. As a result, web2py developers are perfectly comfortable with normal Python imports and do not have any false expectations.
Web2py is indeed using its "great power" responsibly.
Your reaction is very similar to the reaction people who have never used Python have when they discover Python has significant whitespace (with no vested interest against Python): "That's a horrible idea! It failed miserably for Fortran 40 years ago! That goes against everything I was taught!". Yes, it does not fit exactly with some mental model you already have. But no, it does not set up false expectations, much like Python does not set up false expectations of whitespace significance for C programmers who wrote a couple of Python programs.
Anthony already addressed the details in his reply below, but let me just add: IPython and sage essentially redo the python command line, and get nothing but praise. web2py, in some limited contexts (models and controllers) introduces a few useful names into the global namespace, and gets a ton of criticism.
Django (and just about every other framework) introduces a whole new language for templates, and no one squeaks, wheresa web2py uses plain Python as its template language with the smallest modification possible to provide that (you need to add "pass" at the end of a block, because you don't have indentation to guide you properly inside an html template; other template languages add an "endif" one way or another), and no one cares.
It is telling that all this criticism is coming from people who never use web2py, much like criticism of significant whitespace comes from people who do not use Python.
It is bigotry, disguised as a technical argument. In both cases.
I use Django daily, and it's great for a lot of stuff, but I would have to disagree with your "Django for anything larger". Maybe I'm just building things where Django isn't appropriate, but for large stuff that need to integrate with legacy stuff, I would like avoid Django in the future.
Also, getting started on a Flask application is a lot more work than Django, setting up logins, permissions, database stuff and so on takes longer compare to Django. I would pick Django for something that just needs to be up and running quickly and with an okay admin interface.
If you start picking of core bit of Django, I personally think it starts to lose part of what makes it a handy framework.
But in the end your right, the framework isn't important, it's the product. I try out frameworks every now and then and pick the one I feel comfortable and happy working with. Currently that's Flask, but previously I normally went for web.py.
If I found myself talking to someone who had used web2py, I'd be very interested in their critique, but sadly in every case so far, it's been second hand.
Going back to the original discussions about this, and discounting the unnecessarily intemperate language used, it seems to boil down to web2py's conscious design decisions being discounted as "Pythonic heresy" - fair enough if that is your PoV, but that's a long way from "a fundamentally incorrect way to approach web development".
> If I found myself talking to someone who had used web2py, I'd be very interested in their critique, but sadly in every case so far, it's been second hand.
In two years of active mailing list participation, I've never seen any actual users complain about these problems. They are hypothetical concerns that simply do not arise in real world usage.
And this is why I love the Python community. Almost every person in this thread is like "Django, but there are others".
I started on Pylons. I then used Django. So far I've been very happy with Django. I wish the ORM layer was more pluggable as well as the templating system. (I believe this is changing rapidly). But for the most part it works and it is great.
> the smartest web hackers I know universally regard web2py as a fundamentally incorrect way to approach web development
Would you care to elaborate on that? Have any of these smart web hackers used web2py for real web development? I ask because web2py has had thousands of happy users building and maintaining web applications for several years now, and in practice, no one seems to be having the kinds of problems one might expect from a "fundamentally incorrect" approach. What exactly is fundamentally incorrect?
There's no single "best" for every application. One-size-fits-none. One of Django's strengths is in the fact that parts of the framework come off easily when they no longer serve your needs. If the ORM is no longer working for you, you can use SQLAlchemy or write raw SQL. Authentication no longer working for you? Write your own or use a 3rd party one.
Et cetera. The key aspect is that you don't need to sacrifice the entire framework when only one part of it no longer addresses your needs. Keep in mind that 99% of sites never even reach this point.
The other major strength of django is the rich ecosystem of 3rd party apps. That's a lot of code you don't need to write yourself.
That being said, Flask is popular for a reason. Django offers a lot of power, which means adding some complexity to even the simplest projects (something we're working to address with features like project templates in Django 1.4). Flask fills a niche for a framework that is easy to get up and running and addresses 90% of the things which 90% of people need for many projects.
I've heard good things about pyramid, but haven't had a chance to play yet.
I haven't had the "pleasure" of working with web2py, and I'm not knocking the effort which Massimo puts into it, but the choices made there often elicit a raised eyebrow. Ignoring my opinion for a moment, the smartest web hackers I know universally regard web2py as a fundamentally incorrect way to approach web development—but usually say so in far more colorful terms.
TL;DR
* Flask for simpler stuff
* Django for anything larger, or simple stuff that leverages a 3rd-party app you need.
* What matters is the app you ship, not the framework it was built with.
* Django developers are in super-high demand. I get cold-called frequently.