Hacker News new | comments | show | ask | jobs | submit login
Why Django Sucks (speakerdeck.com)
271 points by kenneth_reitz 1750 days ago | hide | past | web | 194 comments | favorite

Problem: Django has features. These features, horrors, reuse each other's capabilities.

Solution: Use something that has no features.

I'm not sure myself how sarcastic I'm being, to be honest. There's some truth in there too (or I wouldn't have posted this). But of course your microframework doesn't have any dependency issues. Rip all those things out of Django and it wouldn't have any dependencies either. Put them all into Flask and it will inevitably have to choose between either having the same problem, or leaving vast swathes of functionality on the table because of the refusal to let the components work together so they stay separate.

Rails and Java EE demonstrate that dependencies on specific implementations are not required to build a framework that offers features.

In Rails, you can rip out ActiveRecord and replace it by an entirely different ORM like DataMapper. There is no real default authentication support, but you can easily plug it in. The list goes on and on: they've done a decent job (I would say 'great', but there are still some improvements needed to make it 'great') at decoupling the various components of Rails and making it easy for users to mix and match.

You need a dependency to offer a certain feature, but not necessarily the default dependency. They have internal API's that decouple the lot. That is exactly what this presentation argues Django doesn't have, but should have.

Now I don't know anything about Django, so I can't judge whether the argument has a factual basis. If you tell me it is wrong, because you can easily replace the persistence or authentication layer of Django, then I have no choice but to believe you. However, the argument is logically consistent and the viability of the alternative it proposes is backed up by plenty of real world examples.

Django is a single python package but is really fairly modular. You can readily use anything in lieu of it's ORM (e.g SQLAlchemy), anything for template rendering (e.g jinja), you're absolutely not forced to use the provided auth component (it's not even enabled by default) nor the admin (but the admin of course only works with django models).

Don't take my word for it, all of this is actually written in multiple places in the docs, tutorials and/or Django site, I can't remember. Here's an excerpt that exemplifies Django's philosophy (from [0]):

> Each view is responsible for doing one of two things: Returning an HttpResponse object containing the content for the requested page, or raising an exception such as Http404. The rest is up to you.

> Your view can read records from a database, or not. It can use a template system such as Django's -- or a third-party Python template system -- or not. It can generate a PDF file, output XML, create a ZIP file on the fly, anything you want, using whatever Python libraries you want.

> All Django wants is that HttpResponse. Or an exception.

> Because it's convenient, let's use Django's own database API, which we covered in Tutorial 1.

Indeed, Django components are incredibly convenient to use, and readily included, and officially supported. But they're completely optional.

[0] https://docs.djangoproject.com/en/1.4/intro/tutorial03/#writ...)

"but the admin of course only work with django models"

I think you missed the point. In Rails, ActiveSupport does a whole lot of automatic magic with ActiveRecord. But it is not limited to ActiveRecord, as most of that functionality is factored out into ActiveModel - implement those interfaces and your link helpers and whatnot will happily support nonAR models. I use this quite often to represent things that doesn't reside in a database.

Well, most of the time. There are a few things out there that are not migrated to ActiveModel yet that really should be (the model side of datehelpers in forms comes to mind).

The point I was making was with regard to the article, which goes down on Django because it would supposedly not be barebones enough. I was expliciting that although one does an apparently monolithic (easy_install|pip install) django, one can readily use only the project+url+view part and have something as barebones as Flask in which you could use other components. Additionally you could readily use only Django templates or the Django ORM, and use e.g Flask for the view part (or no view part at all if you're not doing web stuff)

As for the comparison with Rails, faking models is the same in Django, as both leverage duck-typing features of their underlying language. In Django, a model is just a class, and many things are just queried via introspection. Many parts just query model_instance.pk. Additionally populating Model.meta and you even get yourself some deeper model introspection features. To me the true important part of ActiveRecord, ActiveModel and ActiveSupport is rather that you have a set of modules that you can readily include/extend into your fake models to inject complete model behavior, and that is something Django lacks.

You name the example of link helpers, and interestingly this is an example of the difference of philosophy between Rails and Django (see [0]). Django parts are coupled more loosely than Rails parts, a possible rationale being that creating coupling between two distant parts such as URLs and models could enforce constraints on each, thus reducing their potential to independently shine and coercing possible alternatives of each to the provided model. Another example: with Django you explicitly create a request object (whether directly constructed or encapsulated into a helper method) to be returned by the view function while Rails does magic for you in the controller.

Interestingly you bring the problem of forms and this is again an area where Rails and Django differ. Rails wants both form and data to be handled by a single model, whereas Django separates form models and data models. The rationale here is that they are two different problems and that they ought to be solved by two different components (yet they share a great deal of similarity, and code).

FWIW I worked extensively with both (although my current job is in a Ruby shop, I worked with Django at my previous job and since I'm more of a Python guy I keep myself up to date on that front too), and am in no way saying that one is better than the other. Choose what works for you.

[0] http://stackoverflow.com/questions/61451/does-django-have-ht...

> dependencies on specific implementations are not required to build a framework that offers features

I think this is incorrect. You can't offer features without implementations; The feature will never be completely agnostic of its implementation. When you get a really strong shift in the possible implementations (for example: websockets or even long polling, vs rpc) then the feature (for example: dynamic UI), if re-implemented, starts exposing very different semantics and secondary features.

To sum it up: if you implement a thousand ORMs based on SQL db's then they're all going to look the same, implement one thing based on a NoSQL database and you suddenly see how the "feature" of "storing data" suddenly becomes something different from what could be anticipated by the people who designed the original "feature" back in the SQL era.

Let's not lie to ourselves and pretend that features are some wondrous thing poised in thin air above their implementations.

Agree - This paradigm plays out in every development effort I've ever been apart of...

1) Project starts out relatively agnostic and casts a very wide net

2) Features start to mature and while you are servicing one use case, you are somewhat unknowingly making your product unsuited to certain different future use cases that may or may not arise.

Thats just how design decisions work. Django has made design decisions to cater to a certain set of needs and they have obviously been quite successful. I don't even use Django but I can tell it doesn't "suck" just by how many people have told me it has fit their use cases quite well.

I actually wouldn't be surprised if X years down the road Flask becomes much less agnostic as its community consolidates and matures.

Spoelski has a great rant about frameworks and the concept of abstractions ad nauseam: http://discuss.joelonsoftware.com/default.asp?joel.3.219431.

In a way, frameworks are inherently stupid, but who's to decide where between assembly language and x layer abstraction people should work in?

I think people who criticize Django have yet to make up their minds about what a framework is all about, and what, if anything, it's for. They just hold on to their utopian idea of what their framework should be.

Django was created for practical purposes by people who used it in publishing. I think that's a great foundation for a framework - for some people - and piling on it is just a stupid bandwagon.


EDIT: I found a better way to put this: the author doesn't have a problem with Django; he has a problem with the concept of frameworks.

> he has a problem with the concept of frameworks

I'd say it's more of a problem with frameworks as they exist today. I'd like to see a movement to REST API service frameworks with some level of cooperation to get compatibility for standard client libraries.

Everything then gets built around services: from static site generation to single-page apps, third-party developer APIs to admin interfaces. Then you'd have flexibility to replace any piece of the architecture, whether to get better to performance from a service or to use the latest JS single-page app framework.

Jeff Bezos recognized this 10 years ago:


His Big Mandate went something along these lines:

1) All teams will henceforth expose their data and functionality through service interfaces.

2) Teams must communicate with each other through these interfaces.

3) There will be no other form of interprocess communication allowed: no direct linking, no direct reads of another team's data store, no shared-memory model, no back-doors whatsoever. The only communication allowed is via service interface calls over the network.

4) It doesn't matter what technology they use. HTTP, Corba, Pubsub, custom protocols -- doesn't matter. Bezos doesn't care.

5) All service interfaces, without exception, must be designed from the ground up to be externalizable. That is to say, the team must plan and design to be able to expose the interface to developers in the outside world. No exceptions.

6) Anyone who doesn't do this will be fired.

7) Thank you; have a nice day!

I remember when people thought Bezos was mad for doing this.

Now it has meant that Amazon can transition internal infrastructure into external AWS infrastructure and charge for it.

It really is genius and wouldn't surprise me if this becomes the future of how enterprise companies develop software.

Check out LinkJS. That's the project goal.


The problem is not frameworks; the problem is object oriented programming. Simply put, OOP lends itself to kitchen-sink frameworks because it is the only way to really share code in OOP. We write these large hierarchy of objects and then, because we have to carefully maintain state, we mark most of it as private, or sealed. Then we give precise instructions on how to consume and use the code, and even more precise instructions on how to extend it.

Well that's strange because Django didn't use much OO either when I used it in the past, only for the ORM.

You must have been using a different framework called "Django" than I did.

Have you used Django much? Some classes you run into frequently (besides Model):

* Form * HttpResponse * All middleware * Template * Etc, it's all classes except if you write function based views

Also this is Python, so you can poke the internals however you like :)

You can, but that doesn't mean you should. It's brittle. If your app or library breaks because a minor update to a dependency changed those internals completely, you can't say you weren't warned.

Who's piling on Django? It has flaws and weaknesses just like anything. It is a huge codebase that tries to be everything for everyone, and it succeeds about being almost everything for almost everyone, which is great.

But it can be very difficult to do relatively simple things with Django sometimes, mostly in the admin pages. Admittedly, this is a pain point people bring on themselves by trying to do too much there, but it's a big red swollen example of how too much interleaving and complexity make it painful or impossible to reason about what's happening.

This got a lot better in 1.4: TemplateResponse and the list filter API meant some gnarly code removal on my biggest customized admin project.

That said, I also chose to implement many of my admin changes at a higher level: templates which use jQuery, etc. and interact with the REST API for e.g. complex object creation are much easier than the crazy form / widget hacks I used to try.

Yeah agreed, I just started writing js apps with backbone and dropping them into wherever in the amdin

I'm about +10 on that approach: customize the admin until you hit a difficult point, then stop trying to hammer screws.

But the only tool I HAVE is a hammer!

I have no problem with criticism of Django, but to write a presentation called "Why Django Sucks" is bombastic, misguided link bait - replete with rage comics and whatnot.

It's just not constructive for the discussion, interesting as it may be.

'replete' with a few Reddit-style comics, of which exactly one could be argued is a Rage comic (though it actually isn't).

It's a long-standing tradition for DjangoCon to have a "Why Django Sucks" presentation. And a healthy one IMHO.

Actually yeah. Great point. I think Django rules for publishing, or building sites where your general technical competition might be Wordpress.

It's frankly an awkward fit for loads of web applications. It seems to me (note: Django guy, not RoR guy) that the Rails stuff has adapted much better to applications that fall well outside of the blog/publishing sphere... but maybe that's a false impression.

I disagree, you can write anything in Django.

I'm currently writing a control panel for libvirt and it's a pleasure to use Django, so many features mean I can concentrate on the problem at hand and not on reinventing the wheel.

Joel didn't write that article.

> I think people who criticize Django have yet to make up their minds about what a framework is all about, and what, if anything, it's for. They just hold on to their utopian idea of what their framework should be.

No, they have a different idea of what a framework should do or not do. Doesn't mean they have some utopian idea just because it's not Django.

It's difficult to refute this line of thinking, except in practice.

In practice, I think large frameworks are eventually pretty terrible. It's too easy to compromise your business needs in small ways because the framework offers you something close-enough. Whether those compromises come in the form of over-coupling (which they always do with these frameworks), or in other ways like compromised URL design, query performance, or authorization plumbing.

Great at first, but in my experience a project run long enough in one of these ecosystems tends to outgrow it.

Being faced from the beginning with more of a blank sheet of paper and open ecosystem of solutions to choose from (or build) tends to make you more aware of the trade-offs, and how well the solution you're implementing fits your business needs. Costs more up front, but you're less likely to grow a hate-tumor during years 3-6.

I've been writing web apps for a long time and for many different companies of different sizes. I've never, ever, seen a homegrown setup that was in better shape than the average rails app after a few years. Maybe your experience is different.

Amen. I've seen quite a few projects that start out by rerolling the ORM, routing and templating, then grind to a halt under the weight of all the bugs before getting any significant features out the door.

In Python, you wouldn't reroll your own ORM, routing and templating - you'd use SQLAlchemy, Werkzeug, Jinja2/Mako/whatever.

I wouldn't, and I'm sure you wouldn't... but there are people who do.

Case in point: OpenERP. Serious business software doing serious business things, so of course they can't use any of those other toy ORMs, they have to spend 5000 lines of code writing their own: http://bazaar.launchpad.net/~openerp/openobject-server/trunk...

Hey, it might not be so great, but at least they have tests for all of that code: http://bazaar.launchpad.net/~openerp/openobject-server/trunk...


I know of other projects in a similar state, but they're smaller teams or solo coders, so I don't know that they're quite as fair game for finger pointing...

Ad I've still never seen a homegrown solution that ties together libraries which was better off after a few years. Your experiences may differ.

Mine do differ. Anecdotal evidence, after all.

Most codebases I've seen that are badly maintained or managed over the years are horrible messes - whether Django, Rails or anything else. The last codebase I worked on - written in Django - was appallingly bad. That's no fault in any way of Django, but no framework is going to save you from poor coders, last-minute rushed requirements, chronic technical debt, or lack of investment in refactoring.

I'm not sure you addressed the issue at hand. Others are arguing that using a framework will make your codebase worse in the long wrong. I'm asserting that all of the homegrown codebases I've worked with are worse than the ones using a framework, after a few years.

I'm not arguing against using a framework, if it fits your project requirements, and we can argue the day long about micro-vs-full-stack. There are good arguments for both, they suit different people and projects.

My own observation is that bad codebases are the result of bad development practices regardless of framework. In my last job the code quality was so poor (and the management processes so broken) that whether they'd used Django, Flask or roll-your-own would not have made a whit of difference.

The original discussion was about a potential difference in the long term quality of a code base if they choose a framework over a homegrown solution. You aren't saying anything about that potential difference. Correct?

I said it makes no difference.

My experience says there is a difference. Allow me to offer one possible reason. A good framework gives a project a good structure to start with. Most homegrown solutions have to recreate much of the structure of the framework, and they often do a worse job than the highly developed frameworks that have the experience of many open source developers behind them.

All other things being equal, a "homegrown" project by coders who know what they're doing is going to be better than a framework project by coders who don't. Yes, I understand your reason, and given coders of equal ability it may be true; but I've seen Django projects written so badly the framework made very little difference to maintenance overhead (and as Django becomes more popular and mainstream we're going to see more examples of this).

Even a team of good coders often produces a worse homegrown solution due to the time pressures of their project. This in my opinion makes the chances of creating a better homegrown solution low. And you lose all the reuse abilities you get from a framework.

Could you summarize your suggested best practices (Specifically what you suggest is a good way to avoid at least some of the problems you list in your last sentence.)

Really, it's more of a management problem than a coding problem. Short-term thinking, bad hiring/outsourcing practices, and poor client expectations management, among others. A framework or language isn't magic pixie dust that will make these problems go away.

At this point I'd prefer to work on a well-managed, professionally coded project written in PHP than one written using <insert-python-framework-du-jour-here> run by idiot managers.

One of the factors I considered when I switched jobs earlier this year was that the new place has a policy of devoting 2 months a year to refactoring :)

Which has an interesting balance: you're then using things developed in isolation, which can give you better parts but it definitely means you have to provide interconnect conventions and that new developers have to get used to your particular combination of parts.

If you think you can do this better than the Django community, this can work out well but I'd say more often than not when I've heard about it people weren't actually able to spend enough time on this as they'd hoped and keep falling further and further behind Django and other frameworks.

Sure, if you did it completely on your own. More likely you use Flask or Pyramid which provide the plugins/entry points/templates to make wiring these components together quite easy.

Out of curiosity, what kind of shape is the average Rails app in after a few years?

I have been creating software for 20+ years and I have personally never seen a case where 'in the end' it wouldn't have been better to use a framework. And mostly actually a framework which is as opinionated and feature rich as possible. These frameworks don't grow randomly; they are based on actual needs. When they are young they answer mostly to acute needs of the developer, when they grow they automatically grow into stuff 'most companies' need. And that's 'your company' as well; you can think you are different, but that's not really true. If you try to be different, you mostly do a lot of work which you shouldn't have. Yes, there is Google. Yes there is Facebook. But you are not those. And you won't become those. Also most companies are not IT companies; non-IT companies benefit even more from frameworks and rigidity; in most cases it's better to remake or form your business process to the framework/software than the other way around. Other people did that heavy lifting already; why should you try to do that again?

I'm not sure where you work, but this is my experience from using 'wysiwyg' clipper & dbase software in the 80s to Delphi frameworks in the 90s to web frameworks. People think they are very different from the start and then (usually after a management change) they notice the same stuff happens everywhere.

Are you talking about frameworks or software products? There is a very good argument around building custom software versus buying a product that matches your argument. In that case, I strongly agree. You should find products that either match your business process or change your process to match the products.

With regards to frameworks. I find it hard to believe that none of them would work out in the long run. I wonder if you are under-estimating the cost involved from the developers to replace or create these frameworks from scratch. This also seems like a selection problem more than an inability of frameworks to meet any development need. I mean they do exist for a reason.

That said, most software products are pretty horrible. Many frameworks are equally bad. Does this mean you should custom build everything? Of course not, you company is not going to be able to afford the time it takes you to write your own ORM, your own web framework, your own logging library, etc... It is your job to make compromises that will allow your company to achieve its goals.

Exactly, and I have exactly the same eye twitch every time someone recommends tearing out Django's ORM "because it's shit" and replacing it with SQLAlchemy.

Each of those arrows from slide 25 on should have a little label: "Things that you have to write yourself in Flask."

You sound institutionalized. Django is indeed awesome for having a ton of features immediately. Of course, once you need to start changing those features you realize you have to dislocate your shoulder to do so.

Django is badass for what it is intended to do: be a kitchen sink. Flask is badass for what it is intended to do: be a platform for composable applications. If you ever need to reason about the internals of your web framework, you want the latter. If you don't, the former is great.

"You sound institutionalized."

I'm not sure what that even means, but I suspect the thing that disproves it is "The last website I built was in Yesod.". And while it may be in some sense targeted to fill the Django space, at the present time (and certainly at the time I worked in it) it was more like Flask and a couple of things lightly tacked on.

No, my main point is that Django is what Django is, and while that may not be perfect, it isn't useless, it doesn't "suck", it just doesn't meet all needs any more than anything else does. Flask doesn't meet all needs either. Don't complain that water is tasteless when what you wanted was mustard. Being tasteless doesn't make the water suck, it just makes it water. Complaining about its watery nature is just silly.

If Django actually sucked I'd probably not have said anything, but it's more successful at actually bringing together all those things than most of its competition. (Though since there are roughly 1000 web frameworks out there I'm sure there's better things somewhere.)

  "You sound institutionalized."
  I'm not sure what that even means
mattdeboard is referring to Red's dialogue from The Shawshank Redemption: http://www.youtube.com/watch?v=TsiFanovOSI


This was a presentation for a room filled with Django developers that likely use it for just about everything.

The purpose of the talk isn't to bash Django, it was to introduce Django developers to some interesting concepts that are worth exploring and a tool that may suit their needs.

And the purpose of the title is to get eyeballs

It's a DjangoCon tradition. There's one every year.

It's true. Cal Henderson's was my personal favorite.


When I got into this, a great friend told me "every tool sucks to someone." I always evaluate content like this under those terms...

To be fair to the author of the presentation: if there is a problem, it isn't features and reuse. It's tight coupling, boilerplate and overhead. (Although it is funnier to say that the problem is features and reuse, like it is more provocative to say that Django sucks).

I won't slam Django, Django is good. Its most salient traits are its mindshare, liberality with features, big plugin ecosystem. And these traits were not all present from the beginning, when it was the Django developers who were reinventing wheels and going without features. Django's top traits are historically contingent. So in an alternate history, we might be talking about CherryPy having basically the same problems, because of the inherent pain of taking on so many features so quickly, then maintaining backward compatibility, etc.

Good framework or library code takes significantly longer to develop than similar functionality inside an app. When you add goals like trying to reduce boilerplate and coupling, it gets much harder and slower. It is totally valid to question why not just charge ahead with something easier to develop and get done more quickly. There is a real issue to think about here, it's not so clear cut.

It isn't as simple as saying "Flask is only nice because it has no features, anything with features is necessarily ugly." Both features and clean design take time and if you want both, even more time. But design is hard while features earn mindshare and dollars... if they work reliably, then who is complaining?

Now, at this point, Flask actually has a significant mindshare and plugin ecosystem of its own, so it is really inaccurate to say it has no features. And actually Flask does have a number of dependencies as well, with much of its implementation tucked away in Werkzeug (which is hardly a simple library).

Better Solution: Combine things that do their own jobs.

It actually is what Flask does.

You just posted what I had intended to say, only you said it better.

I use Django and Flask quite a bit. They are the first two things I go to for building a site. For a small site, usually without a database, I mostly use Flask. For a large site with all the common features like auth and such, I use Django. Yeah, it has its bad points, but that's ok. It's worth suffering through whatever those bad points are because it has one gigantic good point.

You don't have to reinvent the wheel.

That is the fundamental problem of all micro-frameworks. They are so small they are incomplete. You may not like Django auth, but Flask has NO AUTH. You have to go get a third party auth system, or write your own. That means with Django I can get a site, with auth, up in just a few minutes. With Flask, you have to write a login page for the 1000th time in your life. It may be very simple to do that, but it's even simpler to do nothing at all.

You can also have an AUTH library coded against an interface, a protocol - and then use it with may different frameworks. I am convinced that this can be made practical if you choose the interfaces carefully. I have actually coded an auth lib against the PSGI interface (in Perl it is an equivalent of WSGI) plus a few virtual functions to be implemented in subclasses as connection to the storage database: https://github.com/zby/Plack-Middleware-Auth-Form

Why web frameworks tend to grow to become such unwieldy beasts?

Most of the web frameworks I know tend to do at least two things - the web stuff plus creation and initialization of all other components. This means that the framework is coupled with all of these components and this is the root of all evil in web frameworks. Of course you need a place to do that object creation and wiring work - but it is not really related to web stuff - it should have it's own place in the program, ideally in a Dependency Injection compartment, not necessarily a container based on the available libraries - but it can also be coded by hand (I might change my minde some day but for now I don't see any reasons to use DI container libraries in a dynamic language like Perl). All the arguments about using Dependency Injection apply also here, but even for someone rejecting DI it should be pretty obvious that reading config files and initializing objects is not much related to web stuff and if you buy the single responsibility principle you should split them into separate libraries.

I don't know Django or Rails too deeply - but I've observed this with Catalyst. Now, Catalyst is supposed to be decoupled from the Views or Models and other Plugins, there are many different ones in each category and you can replace them freely in your programs. But Catalyst code-base is still pretty big and then you have all these Catalyst::Models, Catalyst::Views and Catalyst::Plugins that don't really do any meaningful work - they only map one interface into another one. It could be much simpler if Catalyst only cared about the web related processing.

(copied from my blog)

I had a simple Flask app that need an auth so I wrote my own and I wouldn't quite call it simple. There are so many security concerns. What password hashing algorithm to use (PBKDF2, bcrypt, scrypt, etc). Even the password reset mechanism can be an attack vector if one-time login url is generated poorly and an attacker can generate a large volume of password reset requests.

I think his point is that this: "You have to go get a third party auth system" is a good thing. That way if the auth implementation needs to change, it can more easily if it's loosely coupled to the application.

Django's auth system is not that hard to hack on if you need to - in most cases you just need to write a custom backend and implement a few methods on it. It's certainly comparable to writing your own, or downloading something and integrating it.

I wrote my own to use SQLAlchemy models you define: http://tomforb.es/using-a-custom-sqlalchemy-users-model-with...

Its really not that bad or hard to do at all.

But now you have an auth system that's tightly coupled to SQLAlchemy. How is that different from the regular system, other than you're using SQLAlchemy rather than Django's ORM?

I'm also finding it hard to think of a use case where you need to authenticate 100 users at once, so your initial rationale (100 separate updates) doesn't really work. Surely you'd use a different tool to populate your database, but Django's ORM for day to day stuff?

Pyramid has an auth system not tied to any ORM or persistence system whatsoever: http://pyramid.readthedocs.org/en/latest/tutorials/wiki/auth...

I'd say that's better than anything hardcoded to a fixed database schema. There's a whole world of development that has no interest in using a mediocre, off the shelf database schema in lieu of one that is designed exactly for the problem at hand.

Er, that looks pretty hideous to me.

I guess the idea is that Pyramid exposes a lot of the internals so that you can tweak it, but what's going on in that code is completely lost in the noise. From all of the hits that I can see on Stack Overflow, I'm not the only one who finds it hard to understand.

Not to mention that it completely punts on adding any sort of persistence for user models or password hashing. I stopped trying to figure out what was going on when I realised that

    headers = remember(request, login)
actually returns the raw headers as a list of strings, and you need to feed them manually back into the response.

Compare to Django's login, which is a lot clearer, even though it includes all of the things that the Pyramid version skips over: https://docs.djangoproject.com/en/dev/topics/auth/#django.co...

When I look at django apps they are often similarly hideous to me. (edit: such as - when hundreds of objects are pulled into memory, then filtered further, or processed one at a time, when the entire thing could be done in one query. They'll do this not only because the Django ORM isn't capable enough to do the work out on the query side, but also because the programmer isn't SQL-aware enough to know that's even how it should be done. Django's lack of capability is matched by the developers lack of awareness, and the conclusion for such a developer is "django works great!" This is why SQLAlchemy users get annoyed by Django and Django users get annoyed by SQLAlchemy. There are two totally different ways of looking at problems going on).

This whole thing is about where you're coming from and what software development traditions you subscribe to. We know full well django isn't going anywhere and you can rebut all you want, the alternatives aren't going away either.

Well, when I see code like that, I see lots of moving parts, all with their own weird API, interacting in odd ways. You just have to know that thing X takes a string, an object and a callback function, and there are twenty thing Xs, not five.

Complexity breeds bugs like rabbits; if you can't look at something and understand what's going on (potentially drilling down into an abstraction or two), then it's going to be a maintenance nightmare.

If you can come up with something that's easy to use and powerful, like the declarative_base stuff in SQLAlchemy over the top of the Mapper/Relationship, then I'm all ears - but if complexity is the price that I have to pay for that then it's not an easy tradeoff to make, and in a lot of cases you're better off with the easier, worser solution.

A quick question: do you have any idea of how much work it would take to port SQLAlchemy to Django properly? ie. so that all of the fancy Django manage commands work. I'm assuming a fair bit, but it might be a good way to get some sort of help as far as SQLAlchemy goes. Or you might be happy to continue forging ahead solo, I don't know. Just a thought ;)

> A quick question: do you have any idea of how much work it would take to port SQLAlchemy to Django properly?

There is a version of this I have in mind that would take at least 6-8 weeks of pretty solid developer time. A new layer would be built on top of SQLAlchemy ORM that would look just like Django mappings/QuerySet. The mappings wouldn't be too difficult, QuerySet maybe a little more.

The advantage to that approach would be that existing Django mappings and QuerySet code could be reused in the context of a SQLAlchemy session conversation, that is, the unit of work/identity map paradigms would be brought in. A lot of the "bolted-on/doesnt-really-work" code I see to approximate these features in a tool like JohnnyCache wouldn't be needed anymore.

I'm not sure that this really encompasses "manage" though, I'd have to increase my familiarity with that tool to know everything it does.

Well that's cause the Pyramid Auth API is admitted by the authors to be overly complex. They did a post mortem here and you can read about some of the mistakes they made when designing the API: http://plope.com/pyramid_auth_design_api_postmortem

The most relevant line to take away from their post mortem is this: "Unfortunately, when designing a framework, you get exactly one shot at creating "the right" API. In this case, we didn't."

So even with a decoupled API, if the design doesn't fit your needs or is too cumbersome to use, you will still need to find a third party solution or hack the core code. Both of which, as mentioned by others, are possible in Django.

Chris' perception of design errors aside, there is no reason a feasible auth system not tied to a specific persistence system can't be built. My usual way of proving this is by building one but I'm really at my max number of OSS projects to be maintaining.

I guess I'm not sure I understand what you're getting at here.

Django's auth system requires a backend to implement an API consisting of exactly two methods. One method is passed a set of credentials and returns something "User-ish" (i.e., possessing the attributes of a Django User object), the other is passed an ID and returns a "User-ish" object corresponding to that ID.

Neither of those methods requires the use of Django's ORM, or the use of a database, or really the use of any way to store data at all.

This means that how the backend stores data, and whether it stores data, is irrelevant; if you want to use a DB and SQLAlchemy to interact with it, you can and the auth system neither knows nor cares. You could, assuming a migration plan in place, switch away from the DB and away from SQLAlchemy and store user data in flat files if for some reason you really wanted to, and the auth system would not care and would not notice anything had changed.

I fail to see how anything would be gained by somehow forcing a store-agnostic data API into this picture as part of the auth system, when the auth system currently doesn't even care whether you're storing things.

So … like Django except with no other users and less auditing?

I'm all for simplicity but some problems have very unfavorable cost/benefit ratios. Auth is one of them.

So basically, you're going to do more work now because it might pay off in the future under certain circumstances?

Talk about solving problems you don't have yet. There may be a very good reason for using a third party anything, but to suggest that this is always the "right thing to do" is ludicrous.

Monolithic frameworks complect things -- see Rich Hickey's talk "Simple Made Easy" (http://www.infoq.com/presentations/Simple-Made-Easy).

Monoliths also lock you into a certain paradigm. Django locks you into a RDBMS if you want to hook into all of Django's components like auth, admin, etc. And being locked into a paradigm limits the types of problems you can solve and makes it difficult to shift when a new paradigm emerges.

We're in a period of rapid development in datastore technology. If you're locked into a relational database, it makes it difficult to switch and take advantage of these developments. Loosely coupled components like Flask follow in the Unix tradition and free you from these bounds.

Django was well positioned 10 years ago when the RDBMS ruled, but with the proliferation of new DBs and data storage services, it's not well aligned with modern architectures.

So yeah, let's use VertexDB for auth.

...are you out of your mind?

Evidently you may be trapped inside yours -- I made no mention of VertexDB nor did I suggest any particular database.

However, for example, Datomic (http://www.infoq.com/presentations/The-Design-of-Datomic) is interesting, which is distributed and uses Amazon's DynamoDB storage service.

I'm yet to see a Django based website that outgrows any old rdbms for auth. Care to back up your claim that it's bad? Same for admin. You do realize that Django's admin is just a search result of objects defined in its ORM, and that objects defined in its ORM are very obviously stored in an rdb - right? What would you like admin to use for managing data stored in an rdb? There's barely anything other than the models being managed that touches the database.

Edit: just before my comment gets skewed, my question is: why would you ever use django for a website big enough to warrant this sort of worry? Let's recap: big websites make money which is used to hire coders. Those people are at that point probably porting your website to Agda, or some other cloudscale technology. Sounds like you're the same kind of person who complains that Bash doesn't support OpenMPI and that JavaScript doesn't do fib() well enough and that this here carpentry hammer can't break diamond. Wrong application, dude. Django is for medium-small websites, not for your Cloneddit, Clonebook, CloneSpace, or news.yclonebinator.com; get a different hammer.

It looks like you're new here. Make sure you understand the context before you go trolling else you might be mistaken for a chatterbot with all the non sequiturs.

I'm not new to Django or programming in general, though. Making generic statements like your original post and catering to hip trends is one thing, backing up your bs is another. Obviously you can't answer the direct and very simple questions I stated, so you resort to pointing out your paltry 3.79 karma average in an attempt to sage me. Nice.

My comment was about simplicity and paradigms, with allusions to Thomas Khun's The Structure of Scientific Revolutions (http://en.wikipedia.org/wiki/The_Structure_of_Scientific_Rev...). You must have missed that because you're trying to pick a fight about scalability, which has nothing to do with my original comment.

Most of my work is with graphs so, for example, if you want to use a graph database to build a social graph with a Bayesian network, you wouldn't use most of Django's components such as auth and admin because they're tied to the ORM -- most of Django would just get in your way. It has nothing to with a Django-based site "outgrowing" auth.

Try to break out of your relational mindset and understand the thread before you decide to go off. And regarding my "paltry 3.79 karma average," you do realize the median for the leaderboard (http://news.ycombinator.com/leaders) is 3.975, right? Again, know what you're talking about.

Given a very specific need of working with a bayesian network based on a social graph, i can see how your point was almost-valid. However, there's no mention of this sort of thing in your top post. The original link is about breaking up web apps into services, a'la amazon. I think it is you who does not understand the topic at hand, but that's a fairly trite way of argumentation, so let's just say that you didn't mention your very specific needs which were needed to appreciate just why not using an SQL db for auth is simpler. The fact is that it's probably not, it's just that it fits your solution better, so the total expense is lower. Having auth or admin backed by an rdb is not more expensive, auth supporting your idea or admin supporting your idea which are two executions of the concept that are very unusual compared to what is normally done with Django. Again, you're complaining your hammer can't be used to screw in things. Get the right tool, or if it doesn't exist make it. Django is not the right tool. So the whole thing is a composition of "why didn't you say so" and barking up the wrong tree.

Of course, the lack of actual motivation in your top post can be explained through being inarticulate as in the paragraph above; it can also be explained by you trying to mesh together a few easy and hip claims. The later motivation could well be something you worked hard to muster up only after initial critique, and given that its connection to the top post hinged on a shaky premise I think that's what has happened here.

Regarding your "paltry 3.79 karma average", the leaderboard is sorted by karma amount, not karma average. There are people on that list who have about 10x as much karma average as you do. And even the guy with the least karma on that list still has over 4x as much karma as you do. Well done computing the median of a biased subset of people. Biased because it selects people with the largest amount of points which easily comes at the expense of post quality. Please read about the bias of controlled, not-randomized studies before you go throwing around statistics you can't interpret. I suggest looking at the tree graph found on page 7 of "Statistics" by Freedman, Pisani, Purves, since you like graphs so much. Coming up with meaningless numbers will only shut up someone troubled by innumeracy, and I am not affected.

Damian, I think I see the disconnect here.

The OP/thread is part of an ongoing conversation about the Python community at large and Django's stronghold on the community mindshare because a large portion of development resources goes toward the Django platform rather than to decoupled, external libraries (as noted in the talk).

Most new Python Web developers choose Django as the default option because that's where the mindshare is (hence the repeated "we'll use Django, of course" in the slides), and Django's design and momentum lock the Python community into a certain paradigm, even though new paradigms are emerging.

Kenneth's talk, my comments, and similar comments by people like Mike Bayer (http://news.ycombinator.com/item?id=4079892) were about breaking that stronghold. My example regarding graphs was just an example for you, but my original comment was about the bigger picture.

BTW you were the one throwing around karma average. Have you looked at yours, and are you aware how it's calculated? -- it's not really a good indicator to use when trying to discredit someone.

At first you have tried argumenting with completely unrelated facts, then tried ad-hominem, then you have tried and failed at coming up with a speculative interpretation of your own original post in a failed attempt to pretend those were your motives. Finally, in a last-ditch attempt, you have strongly detracted from your top post.

> The OP/thread is part of an ongoing conversation about the Python community at large and Django's stronghold on the community mindshare

No, it's not. The highest rated top posts for this link talk about complex monolithic code vs flexible code made out of bits which is however lacking in features. This includes the post you're trying to defend using this detraction strategy. The question of Django having or not having mindshare in the python community is secondary to this, and isn't even a topic of the largest minority of comments I've seen on this link.

To support your claim that it's all about community you come up with a short post that is several levels deep, and purport that the original talk bemoans the fact that Django is domineering the community. The talk barely mentions that Django is just a popular choice, it is your completely disconnected analysis that he was complaining about Django's harvesting of the "python mindshare". In fact it mentions Django because according to the talker it's just the top competitor to what he's selling. This is standard course of action when you're presenting a new contender in a space and has nothing to do with "the state of the python community".

In the same way as you try to paint over the past repeatedly changing what you've meant with the original post, you do the same with the side discussion of karma. If it were really as unimportant as you say, why were you defending it in a post just above? You lack consistency.

Yes, I have looked at my karma average. The same page that displays it will also show you that I barely, if ever, post here, and if you try harder you will find out that I've registered about a year ago to post on my own content after it submitted here. This should in fact display to you that this website is not as important to me as you think it is. It's not that I'm new here - it's just that I'm not, you know, "a part of it". However, your comment was just so disconnected from the discussion, I felt compelled to point it out, and I'm glad I did so, because the resulting trainwreck should give you, and other people here, some fodder for thought - not everyone buys your junk logic. You can see it as a pedestrian bystander jumping in to rescue people from a car crash. Not a member of emergency services per se, but the situation warrants action strongly enough that some bystander felt the need to do something.

Threatening people with your amount of experience, jumping around in the supposed meaning of your point, ad hominem (oh, now my comment means this.. no, it means that and you don't get it because i'm so much better than you.. oh, no, it means something else; oh btw, I've been stalking you, watch out!) don't really form a way to have creative and intellectual discourse with anyone. Glad to stomp that out for you, you may thank me later once you've become accustomed to actually admitting when you had made an error, rather than feeling the need to spin it, pretending it's something else.

In my mind, when I made the original comment to your top post, the fallout looked like this:

(original premise): you say that it's very bad that you have to use an rdb for admin

(baiting answer): yeah, so let's just use (nosql database chosen as an especially ridiculous example)

(your answer): you would need to use a nosql database for admin to do (fringe application)

(my answer): but (fringe application) is not what Django was made for. Wrong tool.

(your answer): ok, here's a better illustration. We truly do need Django to be able to do (some thing which is tied to an rdb), but it's much better done if it were in its stead using (some nosql technology).

This workflow has happened (except for the last part), but it came with a lot of bickering and manipulative speculation, which makes me think that you hadn't even noticed it, much like someone who after getting a speeding ticket attributes it to police depravity and oppression of the common man. Therefore, I decided to point it out. Is it really so difficult to admit when you've shot off on a tangent? I liked the link in your top post, quite a lot in fact, but the comment that followed it was of no or negative value because you have chosen to illustrate with non-examples: concepts that do not support your claim. In addition you did this because you really really like nosql databases and probably feel the need to bash on everything that uses SQL from the angle of it using SQL, and sometimes can't control this need. In this way your nature has really messed up the execution of your intentions. I'd have totally upvoted you had you just made a link and no comment, and probably defended the link adamantly from anyone criticizing it. I'd have loved it even more had you accepted that maybe what you thought wasn't entirely correct. But neither of those two things happened. Instead, you bicker and manipulate, finally resorting to trolling through stalking, hoping that you'll find out my name (it's not Rumpelstiltskin) and somehow shock me or make it more personal. And even worse, you fail at stalking, but while doing that show yourself as a big jerk. And I'm not saying I wasn't being negative, but I'm trying to keep form, whereas you display somewhat of a sleazy, vaguely adversarial, win at all costs quality in your discourse, which shows lacks of consistency. Consistency is the most important thing when conveying information, and without it you end up being viewed as a charlatan. Think about it.

Here's the problem -- you fixated on this:

(original premise): you say that it's very bad that you have to use an rdb for admin

...but it's not what I said; this is what I said...

"Django locks you into a RDBMS if you want to hook into all of Django's components like auth, admin, etc"

I'm not saying that it's bad that you have to use a relational database for auth, I'm saying that if you don't use a relational database and the ORM then you lose admin, auth, third-party apps, etc. Strip all of that out and what do you have left? See slide 71 (https://speakerdeck.com/u/kennethreitz/p/flasky-goodness).

And I have said this several times before (http://news.ycombinator.com/item?id=2911275), so no, I am not trying to retrofit my argument.

The talk barely mentions that Django is just a popular choice, it is your completely disconnected analysis that he was complaining about Django's harvesting of the "python mindshare".

If you don't think that's at least the subtext of what the presentation was about, look at the slide for Kenneth's primary thesis: "Open Source Everything" (slide 10 - https://speakerdeck.com/u/kennethreitz/p/flasky-goodness). And then go through the presentation again to see what he means -- "Single Code Bases Are Evil" (slide 45).

The slide just says "open source everything". How you conceived that this in turn means "django has ingested the python community" is beyond me. Probably the same mental flaw that makes you a stalker. Why should I be replying to a stalker again?

BTW, did I mention: "stalker"?

The benefits of using Django include not having to rebuild a lot of boiler plate features again and again. Things like the admin panel for example. When I used web.py I always had to build some kind of way to manage users easily. Login pages, logout pages, error pages.

I do not know much about Flask and it looks like it has some bare bones middleware and context processor tools, but it doesn't look like it does much more than what web.py offered, well except for all the testing tools (which look pretty cool).

Sure the article has a good argument about separating components, but before you propose your alternative you should include all of those features (decoupled I suppose) that Django does for you already. In addition the patterns page[1] on the Flask documentation is basically a cookbook for things that Django already does, and by the way encourage the one code base architecture this presentation argued against.

[1] http://flask.pocoo.org/docs/patterns/

Heh. Who needs

  python manage.py syncdb
when you can write a function:

  from contextlib import closing
  def init_db():
      with closing(connect_db()) as db:
          with app.open_resource('schema.sql') as f:

wtf is that ?

edit: using the current toolchain it's:

    alembic upgrade head

It's from Flask's recipe section: http://flask.pocoo.org/docs/patterns/sqlite3/#initial-schema...

edit: not if you're using sqlite, since alembic doesn't seem to try too hard supporting it.

> not if you're using sqlite, since alembic doesn't seem to try too hard supporting it.

Because its brand new, written by pretty much one person (I'll give you a hint, it's me), and also sqlite barely supports migrations itself (http://sqlite.org/faq.html#q11). You're trolling pretty hard in this thread, maybe you should let other toolsets besides django have a chance.

Sorry, wait a second. You're comparing a feature built in to the core of django to something brand new that has a support team of one person and accusing the other guy of trolling?

I'm sure your code is fine, but you can't possibly argue that it is on par with a major component of a major framework and be taken seriously.

alembic and sqlalchemy are not only on par with django's tools, they are generally superior. This isn't just my opinion, here's Alex Gaynor, Django core committer, saying the same thing:


Yet the developmental resources SQLAlchemy and Alembic are a tiny fraction of what Django has. It's the tremendous gravitational pull of Django and the habits of its community writing things hardcoded to Django that suck the life out of other projects in the Python community.

You misread him. He's saying that it's unfair to compare alembic, written solely by him, to something built into Django and debugged by lots of people.

Which is fair enough IMO, but it's not really convincing me that Flask is a better way to go.

I'm not "trolling", I just disagree with you.

And yes, I know you wrote it. You wrote SQLAlchemy too.

I would still recommend SQLAlchemy :-)

The point though, is that people bang on about lightweight frameworks and composability, but what's the first thing they do?

Start reimplementing^Wrecomposing Django on top of their lightweight framework.

Who needs a one-line schema migration command that can be rolled back when you can just copypaste boilerplate which doesn't do anything nearly as useful or sophisticated and requires you to go and actually write out the table definitions? You're right, dude. Great idea.

Whoops. Mind the sarchasm there ;)

Personally I'd say:

- Error handling: Django error page is great, unless of course it's a AJAX request. Pylons does this in a much smarter way

- Django ORM is awful. Easy to use yes, but awful

- Django Auth is a "good intention" but awful implementation

- Django templates are sloooooow. Jinja 2 is an order of magnitude faster

Amongst other warts

Also, the author apparently found the hard way: don't use Django as an api server

I may sound critical of Django, but I think it's a "complex framework for simple usages", I mean, if you need low flexibility go for it, you'll do what you want really quickly.

You're quick to toss out unsupported assertions: e.g. calling the ORM awful just sounds naive and microbenchmark claims about the template system assume that it's a common bottleneck, which simply isn't true.

Put another way: I inherited a site where someone noticed that a view was slow and switched everything to Jinja2 for magic pixie dust speed ups. This made almost no difference but did complicate maintenance and require reinventing common Django template tags and filters. I joined the project later and actually made the page much (50x) faster by actually profiling and not executing 8,000 SQL queries.

Jinja2 is a great project but I have yet to run into a case where the Django/Jinja debate in any way affected performance significantly. Pick the one which causes you the least support grief and worry about problems you've actually measured.

"You're quick to toss out unsupported assertions: e.g. calling the ORM awful just sounds naive"

I can assure my assertions are based by a lot of benchmarking of a Django project that heavily depended on the ORM. And it's not even about the quality of the queries, Postgres was eating them like hot cakes, but the ammount of queries itself was making it slow. Even for things like user_token.delete() (this was an open source project in Django that we were adapting)

Oh sure, I don't recommend the first step of optimization to be switching to Jinja2, Django templates are fine for 99% of cases. But in my case, Django templates were being used in a very specific way (which btw was done in the original project, that is, not by me) which was very slow (think 1s per page, and that's without querying the db!)

I would argue that the main problem is so many queries: rather than arguing about ORM dispatch speed it's almost always better to make fewer queries and/or retrieve less data as you can cut out a ton of unavoidable overhead intrinsic to shipping a query to another process (possibly on another system), executing it and handling the results. ORM improvements can only address either end of that process.

Similarly, 1s to render a template sounds rather unusual - if that's not just something like not using the cached loader on a slow filesystem it's screaming for logic to move into the view or a template tag.

I will also note in both cases these started out as general assertions which were then qualified to refer to specific edge cases. Again, without describing the exact code being benchmarked it's a disservice to through out performance advice to people who might take it as a general rule rather than understanding that it's unlikely to be a significant problem for most users.

>> "I would argue that the main problem is so many queries: rather than arguing about ORM dispatch speed it's almost always better to make fewer queries"

In Python there aren't many queries! That's the issue!

Let me explain better. Django ORM is converting a few lines (and sometimes ONE - like user_token.delete() ) of python to tens of queries. These tens of queries take around 200ms (or more) because each query takes around 3ms/10ms

user_token.delete() was taking 300ms (I wish I was kidding)

"Similarly, 1s to render a template sounds rather unusual - if that's not just something like not using the cached loader on a slow filesystem it's screaming for logic to move into the view or a template tag."

No, not cached loader, not slow filesystem. It's a for with an inner include.

If a simple delete call is generating more than one query, it's either oddly customized or you have a ton of related models which need to be updated to adjust the cascade behavior:


“No, not cached loader, not slow filesystem. It's a for with an inner include.”

With a lot of loops - again, not common for most web apps (who wants a 5mb HTML page?). You should be able to avoid this by using a custom template tag to load once and render many times.

I think you are being a bit harsh by using the quickness of Django as a 1 line throwaway - the entire purpose is for it to produce quick, simple applications.

There is an entire class of problems (mainly enterprise-related) for which the simplicity (ORM / Auth / etc..) is great. I managed to tie Django Auth into Active Directory which made the user's experience (relatively) seamless, as opposed to the previous reality (everyone with a different password for different applications).

Can't you also use Jinja templates in Django?

I'm not convinced that I would use Django on a large project where I get to cooperate with 15-20 other programmers, but if the scenario is 3 people with relatively normal business requirements it makes a lot of sense.


You can use Jinja2 with Django, but you lose the ability to use any prebuilt Django templates. Which isn't much of an issue in practice since those are often the first thing you write yourself from reusable apps.

You also can't use templatetags from reusable apps (or Django itself) but it's easy enough to write a wrapper for those that allows you to.

We switched to Jinja2 for Canvas because the Django templates were atrociously slow, and it was absolutely the right decision for us.

I don't disagree with you!

You can certainly use Jinja2 templates on Django, for most uses Django templates are ok

What is wrong with django's ORM? I'm not being flip; I'm honestly curious.

If your models are simple, it's good

If you rely on model inheritance, or your models have lots of relationships, Django uses the DB really inneficiently

Like, making lots of queries (mostly repeating itself), so a simple thing takes a lot of time.

It's a little bit difficult to explain (you can imagine it was more or less difficult to figure this out as well)

> Django templates are sloooooow. Jinja 2 is an order of magnitude faster

Template execution speed is unlikely to be the bottleneck for the vast majority of sites. I prefer Jinja2 for the flexibility (macros etc) rather than the performance.

Agree on Django auth; it's horribly designed - need an extra field - use a separate UserProfile - really? Need to login with unique email address - which EVERY SINGLE client asks for - you're going to go down a rabbit hole. A group/permissions system almost nobody uses outside the admin.

Django auth was designed around the typical use case ca. 2005. The world's moved on a bit since then.

What I end up doing nowadays is roll my own (and re-use bits of contrib.auth where appropriate, such as password hashing) using a custom auth backend and keep a separate site for the Django admin which uses contrib.auth models. As long as I don't have to use 3rd party apps that rely on auth.User I'm fine.

You can also subclass auth.User, which allows you to maintain compatibility with 3rd party apps.

This is how I've gotten around the user name length limitation. I have a longer field in the subclass, and implement a backend to check that. But because it's a subclass, foreign-key relations still work.

What if you want to get rid of the username field altogether?

For example, my typical use case: unique email address for logins, no usernames:

I suppose you could subclass User with a longer username, and sync the username with the email address using a signal, for example.

Still, it's a chunk of workaround I end up doing one way or another with each new project. Hopefully soon (based on discussions on django-developers group) we'll see some kind of pluggable User model.

I'm not quite sure I understand slide 48 which talks about constraints. Does a text editor have more or less constraints than an IDE? I would argue that it has less constraints, however I assume he is arguing that text editors are better which implies that they have more constraints. The same goes for Pen&Paper vs digital notes. Surely being able to write in any direction at any size with any style as well as draw means there are less constraints than simply typing a digital note. Am I misunderstanding which side of these examples he's actually advocating? How does OSX v Linux enter into this whatsoever?

I was at the talk, and the way he explained it was that the first column allows for less customization. Kenneth said that if he would use Linux he would spend all day tweaking it, and not getting work done. The same goes for pen & paper notes over digital notes, once they're written down, you're not tweaking them anymore. A simple text editor does not have all the fancy functions to play with that an IDE does. So he is indeed advocating the first column, with regards to them being tools that are not as configurable as the second column.

> he would use Linux he would spend all day tweaking it

That is a fatigued point. I use Linux and store the few tweak I have to do manually in a install_note file. Next time I want a fresh install I just follow the doc and in 10 mn I have a fully adapted environment. Then I do not tweak anything more at this level. All subsequent tweaks are vimrc and bashrc modifications that are pushed to bitbucket, and I guess I would do those on MacOS anyway.

Being able to fiddle the config do not mean you have to, and the days are gone when Linux was not that stable.

The thing I actually spend a lot of time tweaking for the few days I have a new device or OS version is my phone (Android). On these little big guys I get back the tweaking excitment I got with my first PCs (Oh! Look, you can change the prompt! Look, you can move the start bar to the top!)

I think what is actually interesting with mobile phone is that they are not stabilized, a lot has to be invented for them, and each new OS version or even some apps really add new possibilities.

But for Linux, Windows or Mac, no new exciting thing is in sight, and spending too much time tweaking the config just mean you have time to spare.

Traitor scum! Such an intense title after such a nice conversation on the Django Podcast... [1]

Of course I'm kidding because these are valid critiques. Django's code base has a bad case of introducing really hard to debug interactions. But, to be fair, those are fairly rare.

However, as a Django lover I must say that Flask is missing a lot of what I love about Django: sane pre-built options for getting you to 90% functionality quickly. That last 10% can be difficult, but that is better than a more difficult 90%.

One thing that is rather annoying with Django is the learning curve (there's a lot in there), but the docs are so good that it isn't that bad (and one could argue that Flask is harder to learn because it means learning SQLAlchemy, Werkzueg, etc... too).

As he mentions in the slide, best tool for the job. Flask is certainly more Pythonic (IMO) and beats Django very handily for simple apps, but the ability to skip reinventing the wheel will keep a lot of people in the Django camp for the foreseeable future.

[1] http://3rdaverad.io/shows/django-podcast/episodes/deployment...

I've been working with Django for about 5 years now and I can say it's a great framework for a "quick win" when your use case matches its original intent - that is, if you're building public websites, with a custom CMS backend, and need the usual stuff like authentication, feeds, comments, etc. You can go a long way by just using and extending built-in apps - and for the 20%-40% left you find some great 3rd party libraries for doing what you need.

From my experience, the problems arise when you begin bending it to fit your particular use case. For instance: Django is naive regarding multi-tenancy, something you usually need when building web apps, so you'll have to hack some parts in it; the coupling of most 3rd party apps with the built-in authentication app can also get in the way; etc. If your use case deviates too much from the "website" model, using Flask (or just going down to WSGI) for the plumbing and then picking best-of-breed libraries (SQLAlchemy, Jinja, etc.) can pay off in the long run as opposed to going with monolithic Django from the start because, down the line, you'll find you had to hack most parts anyway.

I love Django for making websites, but I'd go with Flask for an API. The only issue I found with Flask is I often found myself recreating stuff that Django already does, and is already done way better.

I think the "Constraints are Good" slide is massively oversimplified. Especially the "editors vs IDEs" and "primes vs zooms" bullets.

Just for one example: stepping through an IDE's debugger, integrated into the code editor, to track down a problem is incredibly handy. It's a habit I picked up while living in Eclipse doing Java work, and why most of my Rails work is now in RubyMine instead of Emacs like it was when I was in school.

And sure, if I had unlimited resources, and wasn't annoyed at all by having to carry around a bunch of primes, and could change lenses in an instant (or was carrying four different bodies too), I'd rather have a set of excellent primes than a zoom.

Very much like how I'd love to be able to integrate (and possibly write myself) a bunch of services to perfectly fit my problem instead of using a framework. But it just isn't very practical for a lot of areas. And then the problem changes, and the purpose-built solution to be adapted... and then this happens a few more time and how perfectly have you maintained your original separations of concerns?

This is diverging a bit, but weaning yourself off of the debugger habit can be incredibly liberating. I used to be a debugger junkie, but I've changed to a system of carefully reading code and understanding what it does (and often writing unit tests to confirm that each pieces is doing what I think it's doing). Every time I have to go into a debugger now, I curse the person who left me with no other choice (say, due to design choices or laziness). Sometimes... the person I curse is me :)

I wholeheartedly agree. TDD as Test-Driven Debugging is the way to go. :)

Agreed on the "changing service oriented architecture" parts. Once you split once big app into two medium sized apps, it can be hard to make radical changes to the application architecture. It adds a lot of complexity, like (deployment, caching, testing, configuring)

ruby-debug takes a little bit more work to learn in the beginning but in the end is more satisfying and flexible than any of the GUI debuggers I've used (eclipse, visual studio).

Command line interfaces are cool especially for stuff you do all the time

I'm confused about the assertion that Flask is only 800 lines of code.

Counting Flask v0.8 with cloc yields twice that:

  $ perl cloc-1.56.pl flask --exclude-dir=testsuite,ext
  18 text files.
  18 unique files.                              
  114 files ignored.
  http://cloc.sourceforge.net v 1.56  T=0.5 s (36.0 files/s, 8008.0 lines/s)
  Language                     files          blank        comment           code
  Python                          18            694           1748           1562
  SUM:                            18            694           1748           1562
And that doesn't include the size of Werkzeug, without which Flask cannot run:

  $ perl cloc-1.56.pl werkzeug --exclude-dir=testsuite,ext,debug,contrib
        20 text files.
        20 unique files.                              
       126 files ignored.
  http://cloc.sourceforge.net v 1.56  T=1.0 s (20.0 files/s, 13460.0 lines/s)
  Language                     files          blank        comment           code
  Python                          20           2307           4277           6876
  SUM:                            20           2307           4277           6876
Including the contrib and debug packages of Werkzeug adds another 3000 LOC.

I haven't done the numbers in a while but from the given ratio I would assume your line checker tool treats docstrings as code. The red part there is for the most part just documentation, not code: https://github.com/mitsuhiko/flask/blob/master/flask/app.py (as an example)

I think you're right, it is counting docstrings as code.

> I'm confused about the assertion that Flask is only 800 lines of code.

It's called "spin". It's common practice for people trying to sell you on something.

While it is true that Django may be quite a large framework, a 'kitchen sink' in a way, I feel that many people often miss the point of what a framework is, in that you don't have to use all of it.

In my few years of developing in Django I have had my frustrations and joys, many of the frustrations coming from the idea that I should do things how the framework wants me to, only to realize that it is still python that I'm writing code in. The idea of Django is not to be some utopian framework where all of your pythonic dreams come true, it is to enable you to build applications quickly and with ease.

While Django may have been created to be a publishing platform, our primary use for it is a genetic analysis application, which is complicated enough without having to worry about the framework, and trust me, Django is not anywhere near a problem in the app. We also use Django for a separate report delivery system, which has API endpoints and is constantly being fed data from 3 other applications, and again, Django has never been an issue.

Sure, you can roll your own libraries with something small like Flask, and reinvent the wheel many times over, but do you actually get features rolled out? Or are you constantly patting yourself on the back for keeping such a small codebase while maintaining a home-grown system and hoping you can get a feature out the door while fixing all of the bugs that not only the system may have introduced, but your features as well.

Here are my biggest worries of a very customized/home grown framework: 1) Does the knowledge of the framework transfer to the next project you work on? 2) Are you writing documentation so that the next person can understand the code? If so whats the time cost for that? 3) Are you spending more time building the perfect system or rolling out features?

Don't get me wrong though, I love working with small polished libraries and connecting them together, namely in node.js, but it is entertaining more than productive.

This is not about Django and why it sucks. It's a refreshing take on monolithic vs. micro frameworks and it's nice to see that a micro framework like Flask gets the attention it deserves.

I believe that monolithic framework are aged too. Django and also Rails as monolithic as they are force you into given patterns, even if you can choose specific modules. I made my first experiences with a highly modular micro framework (Node with Express) some weeks ago and I have to say that I don't want to go back. Even if it seems that you have to reinvent the wheel sometimes (but in reality you don't) your application reflects your use case much better, it's more fun and you are again programming yourself—deciding on architecture, structure and design patterns.

I think the title is misleading, but the slides/concepts are pretty spot on.

I think something the author didn't really cover was upgrades. When elements are highly decoupled, it's easy to go and upgrade piece by piece. API changes can be factored in and dealt with relatively easily. (I believe this is something Amazon did right as well..)

I know this for a fact because upgrading a massive django deployment from 1.1 to 1.4 was a huge project for us.

That said, I still love all the out of box defaults that django provides and the fact that extending them is relatively painless as long as you spent a few years learning the ins and outs of the system ;)

All frameworks are horrible. Because there is no 1 ring to rule them all. The more "powerful" frameworks become, the more abstract and detached from reality they become, the more you end up solving problems that exist only because you are using said frameworks.

Clearly, there are building blocks that are useful across most applications. You can gather those into libraries and reuse them over time. But, frameworks...no, there are no silver bullets, no fat-free fat, no sugar-free sugar, etc.

What you're asking for is awesome, but.... it's really hard to do well. The extra abstraction is hard to get right. Instead a bunch of decoupled components playing well together, you can wind up with a bunch of chaotic components having their dependencies changed out from under them, and seriously raising the barrier to entry for newbie developers who need to figure out how to put humpty dumpty back together again to actually build an app.

Rails 2->3 tried to the general route you're talking about (but still with language API connections, not REST. That would be even harder in some ways) --- with, well, mixed success. And Rails starts out lower level (much less UI built-ins) than django, another thing that would make it even harder.

I've had many failures in personal homegrown projects. :)

Abstraction is hard. To do super high level of architecture abstraction _well_ takes experience and skill, as well as more developer resources. It's easy to go off into architecture astronaut adventures, and you end up spending all your development time trying to keep the parts working together, significantly sapping resources to actually, you know, provide new functionality.

That said, there is certainly such a thing also as too little abstraction and too much tight-coupling too, obviously. There is a happy medium.


I understand that "why django sucks" is a better, more provocative title that will get read more than "why django isn't perfect in every way and i prefer using flask for this", so i don't fault the author for choosing that subtext.

However, the general "tradition" (yes, its a tradition now) of justifying a tech/infrastructure decision with "Ah! language/framework/db made popular by others is a horribly broken mistake! you are doing it wrong!" is 1. getting old, 2. counterproductive for engineers.

They are tools. There are different tasks with different requirements. They have different pros and cons and different learning curves. Some tools are better suited for some tasks. Some tools are even better suited for most tasks. Sometimes it even makes reasonable sense to use a product that isn't the best of the best of the best if you are really certain you don't care about the dimension in which your tool is not the most amazing.

Hammers are bad for cooking eggs. Spatulas are bad for nailing nails. I made eggs this morning. Keep an eye out for my upcoming blog post: "Why hammers suck!!"

I completely agree with you about needlessly provocative titles.

On the other hand, in the world of frameworks, it's not entirely common for the use cases to be (as) disjoint as they are for hammers vs. spatulas. More often, frameworks overlap in functionality and differ on matters of style and ideology. And this is what feeds the flame wars.

For starters, you have a choice between MyKitchen and spatula. MyKitchen has everything you need to make a reasonable pasta meal for up to 8 guests. The pasta practically serves itself... even when you are making steaks. spatula is totally dedicated to scraping things out of pots, and obviously you could just use MyKitchen.SpatulaFactory(_ctx) instead (you did read the equipment manifest, didn't you?) Plus MyKitchen has a plugin which will make pork buns that practically serve themselves... why waste time with low-level stuff like spatulas?

Some guy graduated from spaghetti to pizzas and he can only scoff at spatula, which is not necessary at all, since you can cook pizzas directly on the rack.

Another guy made this incredible pocket-sized leatherman which includes compact versions of all the kitchen tools including a camp stove.

It is true that most frameworks are better suited to some tasks than others, but for a given task one might be just plain technically inferior, or only different in some stylistic way.

Not that style doesn't matter, if it makes you feel happier doing your job. Otherwise, why bother with Ruby or Python when there is already Java EE or COBOL?

agreed that it is more subtle than hammer vs spatula, but just trying to illustrate the point that this general flavor of X sucks compared to Y isn't instructive.

flask is great. but if you want the admin, then you have to build it yourself. i've used django formsets ONCE, ever, but when i needed them I'm glad that django had them instead of me having to build them on flask.

then i've used flask for awesome projects that i knew in advance i didn't need that stuff.

different needs, different tools.

I agree that Django vs. Flask is not a matter of what sucks or is broken.

If I think a hammer looks nice but someone informed explains that it is designed in such a way that the head will tend to fly off, I find that very instructive. The many broken spatulas on github are also instructive.

If you want a pre-built admin, Django provides for a different need, yeah... but if the needed stuff is in the large overlap between Django and Flask, you can't just say "different needs" because you are considering competition to satisfy the same needs. (For example, Flask is promoted for HTTP APIs, but Django also has some good packages for putting together HTTP APIs, so that it is hardly clear that Flask would always be the better choice for APIs).

Most of the argument (here as in emacs vs. vim) is in matters of taste or philosophy - or a dead heat between valid technical concerns. tastypie or Flask? I submit that it matters more what makes you happy and productive, so that it is entirely valid to choose Flask, or Django, or both. After all, it is your life you are spending on all this, you should be happy. If you hate emacs, there are alternatives.

Django is just badly designed. Many things in Django don't work right from the start, and changing them is a big, big pain. When I tried Django, I had to make some changes to the authentication (I can't remember well, but I think I wanted to be able to sign in with email addresses). It was a big pain that took quite a while, and made it incompatible with the rest.

In the end, as the application grew, I had to throw out most of Django and just use my own custom written code. Steep learning curve for a process that will be thrown out later anyways.

A micro-framework is much better. At least you can mix and match as you want.

The biggest stumbling block for me, and I imagine a lot of other users, is simply getting it installed and running. On Ubuntu I was able to do this within ten minutes, but if I choose to develop on Windows it's next to impossible to get a Django project with a PostgreSQL db running without any issues.

I'm quite fond of Python and I like what I have used of Django, but I'd be willing to wager that a lot of other people from PHP land have wanted to use Django and have been put off by how hard it is to set up.

Obviously, I could be doing something wrong, so if it's obvious that I'm doing something wrong please say so.

First I want to say that, in many (most) cases, when people ask me what python web framework they should use, I wholeheartedly recommend Django.

Unless... the person is a weirdo, like me.

In most cases people are looking to prove some idea and they just want the web framework equivalent of "a car that gets me from point A to point B I don't care how.", Django gets the job done and in that capacity is really nice to use.

Personally I don't like using Django. I like to fiddle. I like to tweak. (I like my string beans quarantined!) I like my systems to work exactly the way I want them to work. I have strong opinions about how things should work and am not usually willing to compromise on fundamental issues.

Django does not (in general) make this easy. I wrote a post a while back about the hoops I had to jump through (and the source I had to spelunk through) just to use form field sets and to modify the error reporting (http://mikepk.com/2010/08/python_django_forms_errors_fieldse...).

The real tipping-point for me in not using Django was the ORM. I think it's great for getting up and running quickly but I tend to be of the "ORM-as-Vietnam-of-software-engineering" camp. It's partially due to my OCD/control-freak need to have maximum control and visibility of the RDBMS. I've been converted to using an ORM by SQLAlchemy, but mainly because the philosophy of that project is not to hide the RDBMS from you but to make it easier and more pythonic to work with.

While Django is theoretically decomposable, you lose the ability to use many of the plugins, apps, etc... the moment you deviate from the standard package / install. That's what the arrows in the slides indicate. If you're willing to get something that nearly approximates the functionality you need, and don't care that's it's not exactly what you want, then Django all the way.

Teh Awesome: * Get up and running very quickly * Lots of batteries included * Great Docs * Limited config hell

The Bad: * Tight coupling of features and third party "apps" * Yes you /could/ customize things but then you lose many of the benefits of why you're using Django in the first place * Customization breaks things * Too-strict templating, almost-python-like-but-not-quite * ORM is of the "vietnam" variety

There's no "better / worse" framework. Django and Flask are two tools that try to accomplish the same thing in different ways.


Django gets you 90% of the way from the start, it's in the tagline: for perfectionists with deadlines. However it's difficult to change certain parts of Django.

Flask gives more control but comes at a cost. Each framework has their uses.

I made a summary of Kenneth's talk at http://reinout.vanrees.org/weblog/2012/06/06/flask-django-su..., for some this might be nicer to read/scan than slides. The slides are more complete, though :-)

I'm really tired of seeing memes & my little pony references in presentations. I thought we were adults?

I think the presenter was referring to the Django Pony -- Django's widely known but unofficial mascot -- and not trying to invoke a My Little Pony meme.


Adults can't have a sense of humor?

There's humor, and there's LCD pandering. Despite that, this submission did get me to try out Flask. Nice and straightforward to get started with, which is good because I'm stupid.

He didn't say that.

It's easy to make a boring but informative presentation. It is much more difficult to make a funny but informative presentation. Of course, if you have no sense of humor, I must assume you are a lost traveler from Boringland.

Really, drunken pony parties are 100% relevant to a talk about django. I don't think the slide deck would be complete without it.

Thanks for posting this. I use Django extensively and I never really felt any pain from the tightly coupled monolithic approach, but I always like improving my tools. I will check out Flask.

Any suggestions for making it easy to build REST style APIs? Is piston the #1 choice still?

Check out Tastypie. You can get a full restful API based around your models up in like 5 lines of code and it's really easy to add extra functionality. Sorry for the lack of a link I'm posting this from a phone

I've used all 3 and I settled on "django rest framework". http://django-rest-framework.org/

The issue I have with piston is that it didn't turn my objects into JSON automatically for me when I returned from the call. I also had to map each and every call (GET/PUT/POST/DELETE) and there was no default out of box behavior. I felt like I was violating the DRY principle over and over.

Tastypie was great when I started but I wanted to do some non-RESTful things with it. Like POSTing to /article/{id}/{action}. Yes it is not REST...I don't care. It makes a lot of sense to POST to /article/15/publish to publish an article. I had to override so much inside tastypie it was getting to me.

Django restframework is a bit different. Default behavior is centered around mixins (basically multiple inheritance). I created a mixin for actions being specified and basically added it to any resource I wanted to have that. If you want to know more feel free to ask.

> The issue I have with piston is that it didn't turn my objects into JSON automatically for me when I returned from the call.

That sounds like the perfect place to use a Python function decorator, which lets you wrap a funtion in standard boilerplate.

I prefer tastypie. It takes a fair bit of time investment to learn how it does things, but once you do it's powerful.

Yes, still the #1 choice in my books, especially if your APIs do not match your models 1:1. Tastypie is cute but gets in your way a little too often for my liking. Django-rest is another contender but I haven't tried that yet

What can be said of Django and Flask may as well be said of Rails and Sinatra.

Having what is essentially one app split into multiple apps is going to introduce a whole lot of complexity to the business that isn't necessarily unless the amount of developers on your team is very large.

the "benefits" of flask vs. django can easily be attributed to any of the so-called web micro frameworks vs web full stack frameworks.

it's interesting to me that django seems to be getting grief for some of the same things zope was/is. Time to reinvent the wheel again I guess.


So surprise surprise, you stray from the happy path the full stack framework lays out for you, be ready for the pain.

from the ruby side of things, here's a very good write-up of the differing philosophies between rails [monolithic, batteries-included] and sinatra [small, lightweight]: http://rubysource.com/rails-or-sinatra-the-best-of-both-worl...

the post goes into why there is room (and a need) for both in the ruby web ecosystem, and where you'd want to use each one.

Not trolling, but didn't we go through this with rails a few years ago and the result was, as usual, it depends upon the context?

I'm an inexperienced web programmer wannabe, but what's the difference between Flask and Sinatra?

Largest different is age and ruby vs python. That said Sinatra is built on Rack which has a ton of extensions to add things like sessions or auth. Where as flask has specific flask modules. Really apples to apples in my opinion.

For one, the language (Python vs. Ruby)

Your argument is just saying a blank piece of paper is the best framework.

Not just Django, every framework sucks for sophisticated applications.

Sounds to me like this guy was using the wrong tool for the job.

And websites that need JavaScript and don't tell you.

How is Flask any different from using say, CherryPy?

this presentation is as true as saying "e-books are bad, books are great! Because e-books have too much functionalities"

What fonts were used in this? I like.


Titles are High Tower Text (Flask Logo Font): http://www.fontyukle.net/en/High+Tower+Text.ttf

Text is Gaudy Bookletter 1911 (Open Source!): http://www.theleagueofmoveabletype.com/goudy-bookletter-1911

And code examples are Monofur: http://www.dafont.com/monofur.font

The typography in your presentation is great, but there's one thing you could do to make it better: don't use a left single quotation mark (U+2018) when what's needed is an apostrophe. For that need, the preferred character is a right single quotation mark (U+2019). "Keep ‘em Separated", for example, ought to be "Keep ’em Separated". (Zoom in a billion times to see the difference.)

Awesome, thanks for the tip :)

I rarely say this, normally preferring a scannable transcript to one-dimensional media, but... is there a video or even audio of the presentation?

It was recorded. I'll try to update this thread when it's posted online.

Meh, I like Django.

If you like this approach, and I certainly do (especially after finishing a very service oriented django project), I fully encourage you to check out Go standard libs combined with Gorilla. Plus you get other fun advantages of Go if you want/need them.

> "Speaker Bio Python Overlord for Heroku. Creator of Python-Requests. Photographer. Curator of The GitHub Reflog™. Knows where his towel is."

Thanks for sharing. The site has a few other interesting presentations by the same speaker.

But have you seen the trailer for Django Unchained?!? (new Tarantino flick)


Sorry if this is a stupid question, but are these just slides without any voice or commentary?

Also, you might be interested in this video, http://www.youtube.com/watch?v=i6Fr65PFqfk "Why I hate Django" by Cal Henderson then of Flicker. 2008 though - I'd love to know about an update about the things addressed.

Is it possible to use DSL instead of a framework ? Could we have web DSL to easily make frameworks ?

Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | DMCA | Apply to YC | Contact