Hacker News new | past | comments | ask | show | jobs | submit login
Django vs. Flask (git-pull.com)
349 points by tony on July 3, 2017 | hide | past | favorite | 200 comments

So having used both, this is what I tend to say about them: some of Flask's commonly-used components are better than django's (SQLAlchemy notably), but altogether, django is a better framework.

I strongly disagree with the notion expressed by some that beginners should start with flask "to learn how things work". Making a sane and maintainable project layout is not a particularly easy thing to do, >90% of people (not just beginners) will generally fuck it up somehow and end up living with a really weird app initialization routine as a result. Django's project/app layout and initialization is really quite well considered and I would say appropriate for 99% of projects. That 1% would probably be better off with flask.

More broadly, this is the whole opinionated vs. non-opinionated debate, and I've come to the belief that the vast majority of programmers need the guidance that an opinionated framework gives. It is said that flask doesn't try to suggest any particular structure for your project, but I would say that the effect of that the majority of the time is to produce a project with no structure. Don't get me started on the pattern of `helpers.py` files everywhere: I mean - what isn't a helper? What doesn't fall into that category? So yeah, just heap everything and god knows what in that file.

It shouldn't be a shock to you by this point if I say that I don't think flask is particularly well designed either, but I won't go into my interface-by-interface rant now...

I agree about Flash/Django. But SQLAlchemy is definitely not "better". It is more powerful, more correct, more proper, more flexible. But boy is it a fucking obtuse, verbose, difficult piece of bahoo to use. Django ORM follows Django's philosophy of pragmatism. Assume sane defaults/be opinionated. Make the easy, everyday shit easy! The hard stuff can be figured out later (or just drop to raw SQL). SQLAlchemy's philosophy is to be correct, like RDBMA academic correct and proper. Make the insanely rare and/or difficult stuff possible even if it means making the common stuff a PITA.

It's like the difference between an esoteric and powerful language like Haskell which is objectively more correct. And Python, which is "who cares purity, it lets me get shit done fast and easy."

There's also, I think, a huge divide in the way developers think/reason about problems. Cause I've never seen anyone like both ORMs. Everyone likes/tolerates one and hates the other. I'm guessing some devs "think" the way SQLAlchemy works and others "think" the way DjangoORM works.

So, I do think both ORMs have their place. Just wish SQLAlchemy's place was not in code I have to write/maintain.

Maybe I have programmer Stockholm syndrome, but SQLA is one of the best ORM in existence. Period. I have spent a lot of time with it.

I think in terms of Python style and SQL and I think SQLA fits it better than Django ORM. Django ORM fits Django better. SQLA makes it easy to do OO style SQL modeling in a very Pythonic way.

I don't hate Django ORM. If I used Django I would use the ORM it comes with. It is ok. I think data is so important I avoid Django because I think its ORM becomes the limiting factor for medium or large projects. For small projects, it hardly matters. Use what you know or has a path of least resistance for you.

An aside, Pyramid is actually in between Flask and Django, but people often think it has to be Flask or Django. Pyramid is beautiful and much less opinionated than Django, but still has some batteries, or rather it supports several different types of batteries.

Practical programmers don't hate tools IMO. Makes you too vulnerable to overvaluing your opinion.

To be honest, SQLAlchemy was the single reason I chose to dive more into Python. I learnt it first because of being curious about it. Then, when I found SqlAlchemy, I, having had long years of using Hibernate and NHibernate, thought "if the other Python packages are as good as this one, i should use Python for serious stuff". Which I did.

SQLAlchemy is damn easy to use.

I'm in the camp of liking SQLAlchemy, and not really liking Django's ORM, which I am admittedly much less familiar with. I especially find Django's functionality for aggregations to be completely arcane and a long way from the SQL that I am modeling in my head. I wonder if that's what it comes down to - as someone who tends to think in terms of the SQL I want to build I find SQLAlchemy to be a lot closer to my mental model than Django.

For just getting an object by ID I don't think there's much difference, for me.

I think one thing in Django's favour is that SQLAlchemy can be confusing to setup (do I need scoped sessions?). Also, you need to find and setup your own solution for migrations, whereas Django will just sort that out for you. So getting up and running is a lot easier.

> I especially find Django's functionality for aggregations to be completely arcane and a long way from the SQL that I am modeling in my head.

Do you mean https://docs.djangoproject.com/en/dev/topics/db/aggregation/ and https://docs.djangoproject.com/en/dev/ref/contrib/postgres/a... ? How would you improve it?

> boy is it a fucking obtuse, verbose, difficult piece of bahoo to use.

I have used SQLAlchemy a lot, and find it very easy to use. I've used other ORMs as well, in other platforms.

I find SQLAlchemy a very good ORM.

> But SQLAlchemy is definitely not "better". It is more powerful, more correct, more proper, more flexible.

Indeed - for my purposes, it's better. But I loves me' databases.

> And Python, which is "who cares purity, it lets me get shit done fast and easy."

Oh - ouch. It is possible to write quite pure python, y'know. But it allows you to break the rules when purity would just lead you down very obtuse paths. Or when your code is fundamentally side-effecty.

It is not practical to write pure python code. There's always the implicit state of a generator so lazyness is fucked. And you don't know whether you're passed a list or a generator and then you tuple-unpack it and the generator is empty. And then, of course, you can override the dot-operator and even bare statements can have side effects.

Have you ever tried to write really _pure_ python? I did and it is harder than it needs to be.

I've found sqla easy to use but it's documention is exactly how you describe. Often I have read a section a few times and still don't quite get it.

I like both ORMs, exactly for the reasons you mention. I wish SQLalchemy had a "simple" mode that resembles the Django orm API though yeah.

I'd wager it would be possible to implement the django ORM on top of SQLAlchemy.

Probably - as long as it didn't have to adhere to the unit of work pattern that Alchemy uses. I've considered trying to implement the Django ORM frontend on an Alchemy backend but.. time.

There was a project to do this back in the day.

Fancy seeing you here njharman. And yeah I am working with a Sqlalchemy codebase right now, and it really really makes me miss django orm.


>More broadly, this is the whole opinionated vs. non-opinionated debate, and I've come to the belief that the vast majority of programmers need the guidance that an opinionated framework gives.

The vast majority of programmers need opinionated because they want to string together 15 or 20 different plugins to do ordinary things like CMS, rate limiting, caching, facebook/github authentication, csv export from the admin, drag and drop within admin, and hundreds of other things where you don't want to reinvent the wheel.

With Django there is a larger ecosystem and those modules tend to play better together, and they are pretty much equally loosely coupled. With Flask you get a few modules that use SQLAlchemy, some that use peewee and others like Quokka (flask CMS) that just decided to use mongo for the hell of it. That's the dark side of not being opinionated.

The "batteries included" argument is a red herring, IMO. It doesn't really matter that Django includes admin in the 'django' package and flask separates it out into 'flask-admin'. You don't have to use either if you don't want and being in a different package is orthogonal to coupling.

The magic argument is also sometimes a bit of a red herring too. SQLAlchemy, django ORM, django admin and flask admin all use tons of magic but everybody loves them. Magic is horrible in the wrong place but incredibly powerful in the right place. Rails gave it a bad rep because it used magic too much in the wrong places.

What about Django makes you feel it is the better framework? It's a great singular package, but basically everything in it is done better somewhere else. I'd take Flask's templates over Django's any day and Peewee or SQLA over Django's ORM as well. I never liked regexs for routing and as I've gotten older and liked regexs more, still don't like that approach - Flask's approach is better.

Django is nice for beginners cause you can say "learn this" and they've got a bunch of books and docs to go through, but having watched Django evolve over the last decade, it hasn't really changed from it's stable but boring and does nothing best manner.

They're both kind of dead tech anyway given enough time. Python isn't the best choice for today's websites. That being said, don't know what language/framework is the right thing to push on a beginner.

Integration, documentation and ecosystem. And together, weight heavily in the balance.


If I tell someone to go away and write me a project in flask or a project in django, provided they "go with the flow", the django one will almost always be nicer. A sensible `manage.py` interface. Apps that can be built to be installable, read-only python packages rather than "here's a project repo, clone it, cd into it and run ./godknows.py".

It is of course possible to design such a project in flask, but it takes some work. The gravity is strongly towards "I am the world" projects.

I've also been very surprised at how much less community support there seems to be for flask. Googling/StackOverflow-ing an issue has tended to get me significantly fewer results, and of those results I do get far fewer of them seem to have (sensible) answers. In the django world there is a much broader coverage of generally-accepted sensible ways of doing slightly obscure things.

Being opinionated is a feature. It's just a feature that not all people agree on. But it is one, since it gives all the user a common ground to build tooling, write doc or tutorials and organize things.

This is a side effect of the FOSS community. We (I, included) believe we should have choice, diversity, openness, flexibility. We see only the good things in those. And it's easy to forget how much having one place to start and a clear direction to go to can help.

> So having used both, this is what I tend to say about them: some of Flask's commonly-used components are better than django's (SQLAlchemy notably), but altogether, django is a better framework.

Most Flask dev however, are unable to leverage the full power of SQLalchemy. They do miss the nice integration of the Django ORM, espacially the form generation, admin and fantastic app ecosystem that assumes you have a User object.

> Making a sane and maintainable project layout is not a particularly easy thing to do

+1000 on this. I noticed this as a dev AND a trainer. In the end, flask is great if you are either very beginer and want to do simple things, or very experienced. For all the rest, you want Django.

But the price to pay to enter the Django world is higher.

> It shouldn't be a shock to you by this point if I say that I don't think flask is particularly well designed either, but I won't go into my interface-by-interface rant now...

Well, the global objects such as request is one of my pet peeve... And the decision of a central "app" object make modularity kinda difficult, and blueprint feel like afterthoughts.

But flask also almost invented the whole @route API, which is really awesome.

> But flask also almost invented the whole @route API, which is really awesome.

-1000 on this. It's a side-effect-on-import nightmare. Not to mention scattering your url scheme all over your view modules makes it much harder to spot where your scheme doesn't make sense.

In my opinion.

You can use regular routing instead of route decorators in flask, iirc.


It's declarative configuration, I don't see how more side effects you get than with the Django way.

Views "register themselves" as functions that should be called given a certain URL at import time. That is a side effect and it's horrible if you want to do anything more subtle. Way more "magic" than anything django does.

Django does the same thing. urls.py are imported automatically at startup, even if you run a regular manage.py command that doesn't run the server.

That's not remotely the same thing. In django, one specific file is looked for and imported if it exists, django then looking for an `urlpatterns` in it. No side effects anywhere. Just a default place to look for something, much like it does with models.py.

> But flask also almost invented the whole @route API, which is really awesome

Emphasis on the 'almost' :)

Turbogears was doing something similar with @expose about 5 years earlier.

Just want to point out since you mentioned it that turbogears is still out there, maintained, new releases, and a great framework.

>But flask also almost invented the whole @route API, which is really awesome.

Hasn't that been inherited from bottle?

> I strongly disagree with the notion expressed by some that beginners should start with flask "to learn how things work". Making a sane and maintainable project layout is not a particularly easy thing to do, >90% of people (not just beginners) will generally fuck it up somehow and end up living with a really weird app initialization routine as a result. Django's project/app layout and initialization is really quite well considered and I would say appropriate for 99% of projects. That 1% would probably be better off with flask.

I actually feel like this is why I recommend beginners start with Flask though. I think learning the mistakes and seeing the problems and pain firsthand let's you appreciate and hopefully understand the decisions that were made.

Of course, I should say I recommend it for something like a toy project that you don't intend to maintain. If it's something that's long term then I would agree that Django is likely to be the better choice.

In the end I suppose everyone is different in the same way some people recommend learning Python vs C as their first language.

> I think learning the mistakes and seeing the problems and pain firsthand let's you appreciate and hopefully understand the decisions that were made.

In my experience, people just don't. They just continue on oblivious thinking nasty code is just part of life. I think I'm lucky having gone to django first so that I'm able to see that things don't have to be nasty.

> In my experience, people just don't.

Agree. Most don't. Most learn best by example and by "partial imitation" not by 1st hand experience... Unfortunately :( This is why I find it frustrating when I try to teach people something the way I learned it best: 99% just "don't get it" if I go about it my way. And it's infuriating, I'd want to stuff them in a concentration camp and do some brain-reprogramming procedures on them!

I'm personally horrible at learning by example / by imitation / from others: you can show me 10 times how to do something and I'd still not get it! But make me experience the problem first hand so I can understand the "why" of the solution and all lightbulbs turn on instantly in my head! Or give me a good book with clear conceptual explanations and a set of problems/projects I can work through alone, and I'll learn in a day what others need a month to learn "by example"...

So for me it's definitely what the OP said, "learning the mistakes and seeing the problems and pain firsthand lets you appreciate and understand the decisions that were made" works incredibly well, especially when complemented with some well-written "design documents"!

I guess that's because some people learn best from experience (kinesthetic learning) while some people learn best from examples (rote learning).

Hmm... then I'll label myself a "conceptual-kinesthetic" learner, that'll surely confuse the hell outta' everyone.

It kinda makes sense, in a way what I'm doing in my head while learning is like "simulations of wrestling matches or gladiator fights between concepts" and keeping the pain and bloody mess in your head drives you slightly insane... guess if you put it this way I can grok why most people don't take well to this learning style... most don't enjoy bloody gladiator fights either... same as they don't enjoy being put to learn C or assembler first so they can actually feel the pain that higher level programming languages were invented to alleviate :)

This is my experience too, looking through online communities based around React and it's tooling. The vast majority of people in these communities work with a few too many abstractions and a bit too much tooling, and are content just auto-piloting through their day to day, praying to god that the trendy stack doesn't change too soon.

Some people learn re-usable code patterns and concepts, the majority just learn APIs.

I was never able to do what I wanted to do in Django. The moment you have something that even slightly breaks apart from the MVC model, it all breaks down. It's great for a blog or simple web app, but not much more than that.

In Django I always felt like I had to do things the Django way. In Flask I always felt like I was doing things the Python way.

Can you give a more concrete example? I have a fairly complex app in Django and it is in no way limited. What magic does flask let you do that you cant in django?

- Using a graph database such as Neo4j is a mess with Django and you can't make use of Django's ORM

- Using something that's not a database (e.g. ElasticSearch) and where you prefer speed over ACIDity also sucks because you probably don't want to use an ORM.

- Django's stubbornly-rigid MVC model sucks for building reactive web apps.

- If your structure is an API back-end that serves up JSON, and static JavaScript front-end that makes API calls to access data as needed, with appropriate API call restrictions, caching, and so forth, Flask is much more suited to this task. Doing this in Django just feels like you're swimming upstream the whole way. Django's ORM is also inefficient if you're dealing with a lot of data and only want to serve a small subset of it.

Yes, there have been improvements on all of these fronts with various Django projects, but a lot of the time Flask just gets the job done easier without the bloat.

I agree that if your server is just serving a JSON API, you're probably not using 90% of Django's capabilities. So you might as well use Flask instead.

But as for non-relational databases or other external systems, Django does not help you nor hinder you in any way. If you want to connect to, say, Redis - the code would look the same under Django and under Flask. You simply don't use the ORM for those things, since it's irrelevant. You use the appropriate client library for connecting to the external system.

ORM stands for Object Relational Manager. I wouldn't expect to use a graph database with it. Its possible to use Django without the ORM, and is in no way required. Haystack integrates Django with Elasticsearch.

I have to say that Django-rest-framework's features blow Flask out of the water in terms of building maintainable, reusable REST enpoints.

That makes sense about project organization done correctly.

The thing that really stands out about Flask to me (using it for small projects, I don't really get to use Python at my day job) is that the codebase is incredibly easy to understand in it's entirety. Anytime I have needed to look something up I can go to the code and usually understand it within a minute or so.

I'd classify myself as a mediocre programmer by big tech company standards and Flask is very easy for me to understand and use.

I would think most Django projects are easy to read also. Part of Python generally...

You should have a look at the monster my team maintains at work. Even with a good framework and one of the most readable languages some people still manage to produce a mess. Some of the worst code I have seen has been by Python users (narrowly beaten by unindented Perl).

while Django's outer layer is pretty great, the innards are somewhat messy.

This is mostly around performance reasons, but also a lot of hard-to-follow code paths.

Though a lot of Django projects can take this and make very clean code, it can bite you when you go deep enough into certain things.

I think the parent meant the codebase of flask itself.

I have a horrible time reading the Django-based project we support at work.

I would have to agree with you, there's no point in learning Flask if you're going to do Django projects. Things don't translate well between the two. I like both frameworks, for different things, but you shouldn't try to do a Flask application in Django.

To benefit from Django, you need to do exactly what the documentation want you to do. You'll be happier, everything will be easier and you write a LOT less code. I tried fighting Django, because I didn't agree with some of the design decision, especially in the Django Rest Framework. The result was a worse product, too much and too complex code. The rewritten version did everything "The Django Way". It took less time, and the result was infinitely more understandable and testable.

> >90% of people (not just beginners) will generally fuck it up somehow and end up living with a really weird app

tbh I've seen this plenty of times regardless of whichever framework people choose. At least with Flask the original developer sometimes gets a twinge of 'hmm this seems like a lot of work & might be a mistake'; Django smooths it over so you end up with cached property counts for things which are trivially computable from the DB (+the associated invalidation bugs).

> Django smooths it over so you end up with cached property counts for things which are trivially computable from the DB

Uuuh I've never encountered this problem

I guess you've never had to support someone else's/a 3rd-party vendor's code.

> It is said that flask doesn't try to suggest any particular structure for your project, but I would say that the effect of that the majority of the time is to produce a project with no structure.

Don't blame Flask, blame whoever hired mediocre developers in your company. No framework that "enforces" things will compensate for bad​ human capital.

I'm not sure why you're getting down-voted. You're (mostly) right.

Though it tends not to be a black and white decision. More of a sliding scale between how badly you want shit done and how much you're willing to sacrifice for that. 10 programmers with an ultra-opinionated library will get more work done than 2 good ones with proper tools for the job. They'll get the finished product fairly close to as good for a fraction of the cost.

Almost every business is time constrained in some way. Sometimes you have to make a conscious decision to hire people that are just "good enough" and write "good enough" code. Sometimes you just don't have a choice in the matter if the talent market is sparse.

> 10 programmers with an ultra-opinionated library will get more work done than 2 good ones with proper tools for the job

Maybe. But if the "2 good ones" cost less than 5 times the rate-per-hour than the so-called "mediocre" ones, i'd hire the good ones without hesitation. And in real life, it is that way, at least here the rph factor is 3x at most, usually 2x.

This topic it's worth a HN thread of its own, really.

Oh don't get me wrong, I'd hire the good ones in a heartbeat. I was just saying I can see why managers like the strategy of going with something like Django then hiring a bunch of cheap "Django" programmers to whip up a CRUD app.

Are we in lake Woebegone, where all developers are above average? Odds are, your company is going to hire mediocre developers. Odds are, you are a mediocre developer. An average or mediocre developer is not bad human capital. It's the only kind of human capital you can reasonably expect to have access to.

I am the one who hires devs at my workplace. Have recruited for years.

I would never call my devs "mediocre". If they were, I was to blame.

I guess i live in lake Woebegone, according to you.

Yes, I think so.

There is nothing wrong with cheerleading (we are better than the competition). But there is something wrong with drinking your own kool-aid.

Then again, you might have all above average programmers working for you -- it's certainly possible to arrange that if your engineering department is very small, and for one instance in time. But the odds of that diminish very rapidly as your company becomes more successful and the size of your engineering department grows. And the idea that no one at your company is mediocre is just crazy. I've seen a lot of start ups, and all of them had some below average people, not to mention mediocre people -- even the very good start ups. Moreover, if you do have good people then your company will grow, possibly rapidly, at which point it's pretty much impossible to beat the market long term -- e.g. to consistently have above average developers while at the same time growing in size. Of course that doesn't stop everyone from saying they are above average, just like every kid needs a trophy and a good grade.

But if you are really responsible for engineering, you will be focused on building an architecture and processes that work well for average people and that can be resilient to even below average people, because you either have them on your team now or will have them in the future, whether you like it or not.

You can't just pretend these people don't exist. The bulk of the developer population are what could be called mediocre. Heck, I'd class myself as fairly mediocre. You will end up working with these people or inheriting a project that was started by one of then sooner or later.

> I strongly disagree with the notion expressed by some that beginners should start with flask "to learn how things work". Making a sane and maintainable project layout is not a particularly easy thing to do

For help with this: https://www.starterkit.win/

Do you think Flask would be any better a choice for a smaller project?

No. It is a common mistake thinking that Flask is simple so it's better for small (simple) projects. Flask is very flexible. I would say too flexible. It can be useful for very complex projects but in 99% projects, Django is better. You can be sure that everything will work together.

I always saw it as Django is the lady with the 30 pound purse that has everything you could possibly need on a trip to disneyland and Flask was the guy who showed up to the camping trip wondering why everybody else brought a tent when it's so nice out.

Django is the camper with the U-Haul. Flask is the camper with the backpack. Bottle is the camper with the fanny pack.

I like bottle, also I like fanny packs.

This statement would not fly in the UK

I wonder how Falcon fits in here.


The focus seems to be on performance, so my guess is they're the camper with a fanny pack but it's already unzipped.

Haha, that cracked me up!

Falcon is the camper, who expects the JS developers to make him a tent.

I would have gone with RV vs car/tent vs backpack. But I guess I'm ok w/ wearing the fanny pack.

Who's Bear Grylls then?

  import socket


Each data gram is valuable too.

no no no,


p.s. full-webapp-docker-image.zip but hey 8.3 are there for a reason!

I believe that is the general consensus.

I'm working with a large, 5 year old Django codebase. My humble opinion: Django itself is actively hindering our ability to deliver new features.

Some pain points:

- Django's fat models approach is bad. By coupling model behaviour to database schema, it all but guarantees that you're gonna have a tough time modifying either.

- Django's class-based views and its admin framework strongly encourages a sort of "one-view, one-model" approach. Just about nobody has requirements that neatly fit that worldview. If you need to interact with two models in a single view, working around it is painful.

- Not Django specific, but Python is a bad choice to use at scale. The lack of a good default immutable data structure means we're stuck using mutable data structures everywhere. In a large codebase, the lack of guarantees around something as basic as the shape of a data structure is a huge problem. A notorious example is Django's HttpRequest, whose attributes may or may not be set by the middlewares.

There are more, but one thing's for sure, I probably won't be using Django for my next project.

I'm a heavy Django user, but I work on a lot of data-intensive projects. I do my data modeling in the database and expose it to Django, and it feels pretty clean to me. I use the ORM for what I would consider its true purpose: converting relations and attributes to objects and properties. I use it very lightly, otherwise, like for filtering and sorting.

* Create primary "fact" models for the things you are CRUDing.

* Process the data in the database. Write your complex operations in SQL, and expose them as views.

* Create corresponding Django models on top of the views. These are not as "fat" because they are unmanaged models that just facilitate getting processed data to the user.

If you're using a good database, you accommodate writes through the views as well. I rarely find a good reason to do this, but when it comes up, it works great. It is especially useful when dealing with legacy schemas.

It won't help you with handling code size so big you really want types, but one advice I would give is ditch class based views. I find that function views much easier to reason about, even if it leads to code duplication. The ability to read the code linearly without jumping through inheritance hierarchies makes everything better.

Me too. I never got CBV. I usually use more than one model in a view.

There are TemplateView and View that give you all the good stuff of CBV's without needing to use the more tailored versions. That way instead of needing to do

if request.method == 'GET': something() elif request.method == 'POST': save()

you can just override the get and post method, and do all the init stuff in dispatch. I have found this to be a really clean way to deal with views that need to do more than what the CBV's give by default.

> Django's fat models approach is bad

while django encourages Fat Models and that approach ends up working well sometimes, django itself has no such approach to models. how much logic to put in a model is left to the application developer.

i think what tends to happen, though, is that coming up with a convention different than Fat Models is difficult, especially early on, so most organizations don't bother and end up with models that are badly abstracted AND fat.

this could be seen as a failure of the django community, but it is not a shortcoming of the framework itself.

You can still opt for function-based views almost 100% of the time. Though I'm a big fan of FBVs for "You see what you get", I've started to find that writing your own, project-specific CBVs might pay off for speed + enforcing style in handling requests though.

Fat models are most definitely a pain. Our solution has been to not rely on models for almost anything except for DB interaction, and instead have wrappers that act as business functions. So instead of Post.objects.create, you just write create_post. You still get ORM goodness for the most part, but your validation/creation layer is under control so you can apply your style.

Overall, Django's defaults and even the fat model approach can work really well if you're writing a CMS, for example. And fortunately it's getting easier and easier to use only what you want.

I hear you for the mutability of request objects. Mypy has helped us out a lot, but Django is pretty resistant to those.

The problem with this sort of advice though is that everyone likes to think their project will go hyperscale, or will be prepared to if necessary. The reality is that very very few of them ever need to yet so many design with this is mind not understanding the tradeoffs and what they're losing by following this approach. (Incidentally I also attribute much of the current popularity of microservices to this idea)

The fact is that once you hit hyperscale you should almost certainly not be using the same codebase as when you were still establishing exactly what your project should do.

For most projects, the fat models approach works really very well and I don't feel is something that people should be dissuaded from. For most projects, the alternatives are far harder to get clean results from.

What framework or language would you use to write the same codebase with from scratch?

Not OP, but as a Python developer with interests elsewhere, I'm very productive in modern C# with ASP.NET Core MVC. (And I can write it on a Mac and deploy on Linux, too!)

What are you using to host the app on linux? I've only worked with ASP.net in IIS windows hosts and havn't seen an alternative so far.

I've only done a few small sites, but just putting my app behind nginx has worked out fine for me so far.


.NET Core is cross-platform.

I'd go for libraries instead of frameworks. Frameworks tend to force you into using a specific pattern or architecture (e.g. active records for Django), and I think the programmer should have full control over that.

Having built couple of toy programs with OCaml, I'd be really interested in building a project in a functional language.

Not close to baked yet, but look forward to Rust. Hyper just got async built in, so the entire ecosystem is going to be scalability first from the start.

There are also a lot of "Flask-like" projects in Rust. Rocket for the framework, Tera for the templates, and Diesel for the ORM.

The barrier right now is mainly upstream. Rocket is a nightly-only Rust crate right now, and a lot of the UX features these kinds of frameworks need / want are still missing from the compiler (like async / await).

I would go with Swift, actually.

Another option would be D, although the lack of "batteries" (libraries and tools) is rather concerning.

> The lack of a good default immutable data structure means we're stuck using mutable data structures everywhere.

Don't completely understand this one. Also, couldn't you create an immutable-in-practice class?

Python's data structures (with few exceptions) are completely mutable, which means any function can add, modify, or even remove attributes from some object at any time.

Look at Django's request object for example. Django, by convention, adds a bunch of attributes to the request object at runtime, via middlewares. This is a problem because a dev can't reason about the shape of request object, without stepping through all the middlewares and figuring out which is doing what.

We could use immutable classes internally, but that doesn't solve the problem that external libraries (like Django!) abuse them all over the place.

If you really need this you can use zope.interface to enforce class immutability..

I share your sentiment about python in large code bases. I used to think dynamic languages like python/ruby provide superior expressiveness and therefor should be excellent choices no matter what kind of project one is working on.

Now I believe they should only be used for small projects or quick prototypes. Anything beyond that and everything starts getting very confusing.

Used both and off the bat found Flask breezy and Django bureaucratic. But then the next day with Flask you look up how to do something elementary like login (for fsck sakes) and find there's alternatives of various qualities and scopes, and the flask-security guy has disappeared. Found myself spending a full week up front wrangling tokens and other crap instead of the project at hand, sigh. Django starts to shine at that point.

Lately I've been yearning for a "Flango" distribution with flask and the top twenty extensions supported by a single dev team.

Checkout Keg (https://github.com/level12/keg)

It could use some documentation and some community TLC, but Level 12 is a solid Python shop with a pragmatic approach to app development. There are libraries for auth, login, webgrids, SQLAlchemy, forms, etc etc.

Disclaimer: I used to work for Level 12 and wrote a large production app atop keg.

I feel like Django has too much magic. I agree that it is easier to get quick wins with Django, and if you're building a small hobby site or something, then it's great.

But if you're building something that you hope you'll have to rapidly scale, Django is going to hurt you. It's way harder to scale due to both its heavy reliance on hidden magic its tight integration with its data store.

When you want to rapidly scale, the easiest way to do that is if your data store and application aren't so tightly intertwined that you have to scale both to solve a bottleneck in either.

>But if you're building something that you hope you'll have to rapidly scale, Django is going to hurt you. It's way harder to scale due to both its heavy reliance on hidden magic its tight integration with its data store.

Considering that Django has 1/5th as much "magic" as Rails, and that Rails powers some of the biggest websites on the world, I'd say "citation needed".

And Django powers some huge sites as well. IMO the magic doesn't really hurt you there as long as your still working with a relatively monolithic piece of software.

What is "magic,' and how do you measure it so that you can say things like "1/5?"

Ever seen Penn and Teller?

Joking aside, generally we call "magic" uses of reflection, monkey-patching, auto-magically configured parts, parts of a framework that do way more than what we explicitly tell them, etc.

"1/5 less magic" is what we call in casual conversation "making a point" and not an actual measurement. It is however more than 85% factually correct.

The Django project leaders have stated that one of their goals was to not have "magic" in the framework, and in fact, one of the early (~ Django 1.2 or so) refactoring efforts was about removing "magic" too-clever parts for more explicitness.

What besides reddit?

There is a list at the bottom of this page: https://www.djangoproject.com/start/overview/

    Knight Foundation
    MacArthur Foundation
    National Geographic
    Open Knowledge Foundation
    Open Stack

If the answer here is to be believed, Pinterest has consciously moved away from Django.


Yes, but that doesn't matter much, since they got to billion valuations just fine WITH Django.

Only one of the main Open Stack projects uses Django - and it is a complete pain to work on as a result.

Most of the projects in OpenStack use Flask or Pecan - or Falcon for one or two of the more performance sensitive APIs

Having used Django and that project (Horizon) extensively, I think that Horizon is not a pain to work on as a result of Django, it was just badly written.

Reddit uses Pylons iirc

But see for yourself: https://github.com/reddit/reddit

Interesting. Looking around because I thought it was ruby at one point, but it turns out it was originally written in Lisp. http://www.aaronsw.com/weblog/rewritingreddit

I don't know where I got that idea from.

And they blogged about moving to typescript for frontend at least

I believe python.org, too, is built on Django[0].

Also, here's an interesting thread on Artima: "Please Teach me Web Frameworks for Python!"[1] by Guido van van Rossum[sic]. It's 11 years old (a lot has changed since?), but interesting.

[0]: https://github.com/python/pythondotorg

[1]: http://www.artima.com/weblogs/viewpost.jsp?thread=146149

Reddit isn't powered by Django as far as I know. But Instagram is and I believe Pinterest was/is.

The Pinterest web backend has some vestiges of Django for form validations and stuff, but IIRC it's mostly custom at this point.

Backend is still django though

PyCon's keynote this year was given by Instagram: https://www.youtube.com/watch?v=66XoCk79kjM

Kept a small list here, including codebase changes made for scaling and references:


Instagram, Disqus, Bitbucket, Pinterest.

Apologies in advanced for any marketing copies you don't want to read. The information is there.

Instagram is one, I'm sure there's others [1].

[1] https://engineering.instagram.com/web-service-efficiency-at-...

Reddit is Pylons based. Instagram is Django though.

As someone who's worked on a moderately large Django project, I have to disagree. There's a lot of stuff done for you without you seeing it (like Admin and the default QuerySets + Managers) but it's fairly easy to understand, customize or debug if you want to and Django's source code is actually really readable.

Plus, Django has some of the best software documentation I've ever seen. It was incredibly rare that I couldn't find an answer to how/why something worked in the docs.

Django's magic and some really "Unpythonic" implementations of magic are mostly annoying when you're trying to use it in any context other than serving exactly one webapp over HTTP per process.

(Unrelated blurb:) Pyramid's design contains a lot of wisdom; some folks working on it have been doing Python web frameworks since the web came into existence.

> I feel like Django has too much magic

Are you kidding? Flask is side-effecty module, global-variables, make-sure-you-put-this-magic-incantation-which-you-dont-understand-in-your-init everywhere.

I never said Flask was better...

Django uses "magic" (mostly in the form of "convention over configuration") to make certain approaches simpler. It also makes other approaches, not planned for by the framework, harder.

This is why Django is great for a particular kind of sites, and not as great for other kinds. "Originally designed for the newsroom", as they note on their site; it still feels.

As it's typical with frameworks, Django helps you as long as you do things "the Django way", and does not help, or counteracts you, if your problem domain does not fit well into Django's.

I suspect it's the case with any reasonably specific tool. A hammer is damn efficient as long as you have to deal with nails, and a wrench is great for nuts and bolts — but neither is going to help you to assemble an electronic device. Choosing the right tool for the job is as important as always.

Django, on the other hand, is not a tool, but a toolset ("framework"). Replacing any tool in it is not impossible but loses some of the affordances of the original custom-adjusted tool. I used SQLAlchemy with Django, and it definitely can be done, but you lose e.g. automatic admin pages. I had to go to immense lengths to change the way settings initialization works in Django when I had to update some of them after `import settings`.

Flask is a more loosely coupled bunch of tools. E.g. SQLAlchemy is an entirely separate project, just adopted to work in Flask with a custom layer. From the point of view of long-term development, it's better, it's more flexible. From the POV of a rapid prorotyping of a typical CRUD app, Django is better because it's more integrated. It will bite later, but at the start, most people are ready to make technical debt in exchange for velocity.

I'm currently working on rebuilding a fairly large Django app in Flask. My situation is exactly what you describe, the use case is not one which Django is really built to accomplish. The result is lots of difficulty dealing with the data. I feel like Django is great if you're building content driven websites. Our website barely scratches the surface of our application, and the Django backend has become very.

I completely agree.

My favorite framework is Flask, but I have to work with Django professionally. I find that using Flask produces much cleaner, readable code (depending on the engineer, of course).

When I'm working with Django code, I find myself opening two to four different files just to make a tiny change in some restful API. I find myself doing the same just trying to read some code or trace down a bug or even a utility function.

I find that the object oriented nature of Django also tends to produce overly complex codebases for the things that people try to create. It hides code in favor of magic which just complicates the development process.

Ability to "rapidly scale" is an overrated virtue. Scaling is exactly when you should step back and reflect on your architecture, at which point you should understand that very few of your scaling concerns are at the framework level. I continue to be involved with a 2+ million LOC Django site that's been 8 years under continuous development that went from 10+ million users to 100+ million a summer ago. Django was never the issue.

If the particularities of Django are what's in the way of scaling for you, you have bigger issues than Django.

Scalability problem is the nicest thing that can happen to you which means you are successful. Short time to market and low budget are the common cases for startups. If you have money and time then you can more worry about scalability issues and all generalizations are false, including this one.

> If you're building something that you hope you'll have to rapidly scale, Django is going to hurt you.

Yet somehow people have built wildly successful companies handling massive amounts of traffic using Django. Yes, many have had to re-architect to scale better, but which company hasn't had to do that as they grow from thousands to millions of daily active users?

Django has a lot less magic than Flask. Flask has thread-local global request objects for example, among other things. Under the hood Django is quite explicit in how it works.

What examples of magic do you have, specifically?

Django has hidden thread locals, Flask makes them explicit, so a lot less magic.

I was interested so I had a look at the source. There is a single use of a threading.local object in the RegexResolver.

There are 5 other usages in total, one in the live reloader, two in the tests and two in GeoDjango.

Explicit magic is still magic, and Django contains surprisingly little magic of any type overall, including thread locals.

Good point, I was only searching for explicit "threading.local" references. So there are 4 more or so.

Django uses thread locals in some places where it's needed, but that's beside the point though. It doesn't put thread local objects at the core of its API. Passing an explicit request (real or fake) into functions is much more testable and generally better than relying on a 'request' global, IMO. Same with all the other app globals [1].

A better, more specific argument about Django's use of magic is the models. It uses some dark black magic voodo metaclasses to implement those. Apart from that, the forms, admin, app registry, urls, views is pretty straightforward.

But hey, it's personal preference. I like flask mostly: for some situations it is amazing.

1. http://flask.pocoo.org/docs/0.12/api/#application-globals

About testing: it's not actually True. Flask is easy to test. Also, Flask makes everything explicit which is less surprising than hidden thread locals.

Also, putting things into thread locals somewhere makes explicit request objects totally pointless, because you still depend on threads and can't use Django in an async manner. So it's not a valid good technical argument either. You might like that better, but that's just a subjective opinion.

Django does have magic:

The key thing is Django's implicit behavior is directly proportional to the job it's trying to do [1]:

- Django's settings can be invoked at any time. So it's kept as a lazily-loaded singleton that isn't processed until an attribute is first accessed.

- Django needs to know which apps to load (a la INSTALLED_APPS). And to know the models, django needs to know the apps. These app models can contain relationship dependencies, so its necessarily from a invocation perspective to have a settings that declare them all.

- Using Django's initialization is a must. For the reasons above (settings), but there is work done behind the scenes to make sure everything lines up when Django starts.

- It's most likely project's using Django are going to be using it's ORM.

On the other hand:

- Django doesn't hold every project, or every request for that matter, to its batteries. Intricacies like middleware and context processors are opt-in. Things like template filters are also opt-in on a per-file basis via {% load %} tags.

- Whether or not to use Forms Framework / crispy-forms, for instance, is optional. But projects would miss out on nicely generated forms with validation.

- Projects can also switch out template engines for Jinja2 or something totally custom.

- While strictly speaking, projects can just keep models.py empty, QuerySet's are like the ultimate reusable interface in Django's Frameworks. QuerySet's can be used:

  - by class-based views (CBV)
  - ModelForms to provide database-backed form validation
  - by third party extensions like Django REST Framework (DRF), django-filter, django-tables2, django-guardian, and so on
  - in context processors (which can access URL regex group matches), that later are passed into in templates.

    While that may feel like overkill, this is useful for things like database-backed menus that CMS like Drupal and WordPress would use by default.
> It's way harder to scale due to both its heavy reliance on hidden magic its tight integration with its data store.

I plan on making a future article diving into Django's ORM. Sure, ORM's hide a lot of machinery behind a facade of sugary objects. But on most web projects the database's aren't doing much more than simple joins.

Django's ORM can scale into medium-sized code bases. By the time it gets beyond the point the ORM can handle, heavier data tools (like ElasticSearch, Hadoop) would end up being brought in regardless of whether Django was picked. That doesn't mean earlier code or data schemas need to be thrown out.

Put it another way: When project's get to the point they need a datamart or other things, they're likely to create a separate service for that distinctive from the web front-end.

[1] https://www.git-pull.com/code_explorer/django-vs-flask.html#... / https://www.git-pull.com/code_explorer/django-vs-flask.html#...

I also thought it was magic and scary when I started using it. Then I got to understand how it all works and it's no longer magic, just python.

Which parts are you referring to as magic, the models? I use DRF and find the way it deals with defaults quite nice, your can use a model and it will generate fields or not, and specify or generate them yourself.

Mostly the ORM. If you rely on it, you can't really lay out your tables in any way except the way they do it, at least not without a whole lot of headache.

It requires you have a primary key. That's it.

Everything else table names, fk's, multiple databases, etc. is overridable. The only thing I know of that is a slight headache is postgresql namespaces (aka schemas).

Django does make choices for you. But almost everyone of those choices can be overridden. I have found that most people who think Django (or any large/mature/widely used project) can't to something is because they don't know it well enough.

Not sure what you mean by this. You have full control over your table schemas and relationships with the Django ORM.

Na, I built a video streaming website with django. It has 400 000 v/d.

The team now working on it is not very gifted, and yet they manage to make it evolve because Django makes it easy.

Flask is still one of my favorites in web frameworks, mainly because it was from the Sinatra/microframework moment and still is a pleasure to work with. Just plugin other micro frameworks for the data, middleware, routing, templating as desired.

Express is similar in Node still because of the simplicity and micro size of it.

Micro frameworks don't dictate and grow with a product as needed rather than growing into a monolith and it dictating too much.

As far as Django, it is still one of the most desirable monoliths out there but you don't have to use it that way. However, it is meant to take over like Angular, Rails, MVC etc.

Hmmm. OK. Read through most of this thread. Not sure I agree with some of what is being said about Django. In particular about this "magic" thing.

It took me a while to get comfortable with Django. I tried to learn it on and off for about four years. I finally decided the only way to do it was to focus, commit to it and not jump off into something else until I got it.

That probably took about six months. Much of it felt confusing and, yes, magical. Until I made one more decision: Read The Source Luke.

Seriously. I started to look things up in Django source code. Every single time I came across something I did not understand or that seemed magical I went to source. It was painful at first but it became easier as it turned into a habit.

And then it happened, one day it just clicked. What seemed like a confusing mess months earlier made complete sense. It almost felt like this happened overnight, which wasn't the case.

I now believe the best way to learn Django is to do it exactly this way. Have the source open on another monitor and look-up everything as you go through a tutorial or book. In the process you'll discover much more than what you were looking for originally.

I find myself doing this more and more often with python libraries, even with the well-documented ones like Django REST Framework - always keep a source browser open on the virtualenv dir so I can read library source. There's something about the style of python documentation that makes it difficult to really understand how the classes in a library fit together, so this is necessary for larger python frameworks.

(My personal gold standard for programmer reference documentation has been the Qt API docs for very, very long. They've varied in quality over the years but they're always an example of how to do it.)

Reading the source of libraries I'm using has been a real eye-opener for me. Even from very good documentation you can only learn how to use it, not learn how to write something similar yourself.

PyCharm is amazing help for it as well. Control-click on a function or class, and you will jump into its definition in the library source.

I use PyCharm too. Love it.

This so much. Getting past the "it just magically saves to your db with .save()" by reading the source was critical to my improvement with django.

I love and use both frameworks on a daily basis.

For tiny applications: go with Flask.

For medium and big applications: it depends.

Flask is great since you can mix and match different parts from the toolbox and build/use exactly what you want. But it is easy to end up at a point where you are just rewriting your own mini-Django on top of Flask.

Django on the other hand brings a full meal to the table. Using other toys from the toolbox is certainly possible, but it feels "wrong". And yes, Django certainly has some rough/not-so-shiny edges here and there, partly due to legacy code that cant be easily refactored due to compatibility. But overall it gets the job done and it gets polished more with every release.

At the end of the day, it comes down to personal preference.

To paraphrase: "Whoever does not know Django, is doomed to reinvent it".

You can use Django with its "batteries included" philosophy. Or you can use Flask and start adding in lots of extra libraries (which may or may not play together nicely) to get an ORM, user models, admin site, etc. etc. So you end up reinventing a full web framework based on Flask.

I've done trivial and non-trivial projects in both, and the general summary presented here feels correct. If you've got something with content, that matches most common situations (users, content related to users, content related to other content), Django will get you there quickly and efficiently.

But I still use Flask a lot more, because most of what I create are limited use web services that do interesting things behind the scenes. Caching proxies to improve performance of legacy services, script runners, report generation tools.

Most of the time, Flask feels like the de facto web server, like Requests is the de facto web client.

For nearly a decade now, Python has been my web project language of choice. I started out working exclusively with Django, and I still applaud the rock-solidness and the convenience of Django. However, over the past few years I've shifted entirely to Flask, and I now code most new projects (no matter what size) in Flask, whenever I have a choice.

Flask's main strength over Django, in my opinion, is that it does things in a more modern and a more Pythonic way. The nice "app" object and nice import of settings in Flask, that lets you instantiate multiple app objects in a single process, vs the global app / settings in Django. The use of contexts for exposing requests, sessions, and the like in Flask, vs using arguments and globals in Django. The breakdown into separate, lightweight, independently-usable projects for WSGI toolkit, template engine, CLI toolkit, etc in Flask, vs the monolithic project that is Django.

I have always thought of Flask as the natural and the worthy successor to Django, in terms of being the gold standard among Python web frameworks.

Yes, Flask's ecosystem is sometimes hit-and-miss in terms of code being well-maintained and integrating together reliably. But, considering the number of disparate projects and authors involved, it is actually (in general) quite stable and it does all work nicely.

In terms of helping to enforce a good code structure, and in terms of bundling together popular third-party libraries for Flask, there are a number of utilities that can help. My personal favourite is https://github.com/sloria/cookiecutter-flask , but there are others.

On my next side project will use pyramid next aiohttp or tornado. Python has a good ecosystem of libs. Pick one when you need it. Django is perhaps the less pythonic option. After some time doing go and js.. I prefer the lib approach.. on the end you don't need so many things to quickly respond to http requests ;)

Pyramid really is the underappreciated hidden gem in Python web development. It can be as much of an micro- or full stack framework as you need it to be, while being much better thought out and extensible than something like Flask or Bottle.

No crazy thread local state imports to complicate testing and encourage people to couple their code to the web framework, features like renderers to make _unit_ testing view functions easy, almost 100% test coverage in all the core libraries...

It's a shame that the mainstream basically boils down to Django or Flask. But it's no wonder that organizations like Mozilla and new PyPi are building on Pyramid instead.

Be careful with aiohttp, async io is great, but the actual http parser in aiohttp is super slow.

See https://magic.io/blog/uvloop-blazing-fast-python-networking/ for a full write up.

I've been building stuff in sanic, which is built on uvloop and is super fast. I can recommend it if you're willing to sacrifice a bit of project maturity for a solid async webserver.

I think the most interesting bit about that is that with a re-working of the http header handling, python could be within spitting distance of "best of breed" more or less out of the box (using async, not wrapping uvloop).

And also, of course: benchmark first, optimize later.

I started out with Zope 15 yrs ago, then switched to Django. Now I use Tornado for it's support for web sockets and an async programming style. Tornado coroutines work beautifully with RethinkDB.

I discovered zope some months ago and I really must say that is impressive. Once you get the ZCA and the object publishing is really easy to build things. Zodb is also a good tool! Plone has a good and rich ecosystem and as a CMS is far a way better than all django based ones... There is a lot of things outside django and flask...

The acquisition mechanism is a bit of head twister. Once you're on top of it you can be very productive with Zope.

Django re-usable apps and admin is the killer feature, making it a breeze to do 99% of the work on most agencies websites and then the 1% is just tying it together.

But I'm missing a good abstraction over Django, with most websites features included (user registration, job runner, webpack integration). Also I've come to hate django templates DSL so much I'm now only using a non-DSL method[0] (but it's kinda painful when you want to use apps, making you appreciate standardization)

[0]: https://github.com/mdamien/lys

Rule of thumb for Python web development:

Do you already know Django really well? Then use Django for small and big web projects.

Do you not know either? Then learn Flask for small, trivial applications and learn Django when you find yourself creating your own web framework on top of Flask.

The difference is easy to explain;

You adapt yourself, and your requirements, to Django. Django is "convention over configuration" which means thar first you need to learn all conventions. This takes time.

You adapt Flask to your requirements and your preferences. You build Flask to your liking and needs. Flask is extremely easy to learn.

I think both Django and Flask are good frameworks that solve different problems. Django has a batteries included philosophy that gets you up and running quickly without ever leaving Python (as the developer). Flask is drastically less opinionated and focuses on providing you web hooks to bring your project/logic to the web letting you do whatever you need behind the scenes.

Personally, I feel like Django is great for a "traditional" and straightforward web applications and Flask is better for projects that may require a bit more flexibility both in modeling and backing services.

I think this line from the article follows this perspective:

> Before long, projects will be dealing with forms, REST endpoints and other things that are all best represented via a declarative model with types. The exact stance Django’s applications take from the beginning.

The first application I worked in from the ground-up is a flask app; quite a learning experience, to put it lightly. Despite the amount of technical debt accumulated, however, I don't regret it. I grew a lot as a developer and became more knowledgeable about web development in general.

I picked flask then because I, rather dogmatically, distrusted Django and its batteries included approach. Nowadays, I think it's great and almost the perfect choice to prototype something quickly. That said, if I felt the application would grow in functionality too much, I'd use Flask. Django gets in one's way rather quickly.

One of these things is not like the other. You don't have to choose and there will be cases for both where one is the vastly superior choice. For example: I'd go with Flask for microservices but django for a CMS. I'm sure some people will argue the more apposite. The nodejs thing is so fragmented and difficult by comparison. Flask's routes are better. django's admin absolutely rocks (still). I guess these face-offs are fun but I don't find them very informative, relevant or meaningful. A weird hybrid though - now that would be cool. Or a SAP killer in django.

My apprehension about using flask for microservices is that calls to another microservices are going to block. With NodeJS, the webserver and http libraries are async and mature. Python's really missing a solid async requests library (but async webservers like sanic are getting better).

I worked with flask once. It was code made by an obviously gifted russian coder i worked with. Cleanest webcode i have seen. I never played with django, all i can say is flask can produce really clean code.

Python in general does this. Its designed to be readable first in most regards, something really valuable for other languages to learn - for every line written, it will probably be read dozens of times. Optimizing for the writing part with arcane or convoluted syntax at the expense of legibility only makes projects age poorly.

Once upon a time I made this short worksheet you can use when deciding to use Flask or Django:


With a comparison between the two:


Your guide is way more comprehensive, so mind if I link to it?

No mention of web sockets or asynchrony? Fifteen years ago I was coding against Zope. I've used Django a fair bit too. Both were heavyweight, blot-out-the-sun one-way-to-do-it. Now I use Tornado because it's lightweight, has good web socket support and embraces the async style. It's a joy to code Tornado coroutines with RethinkDB. If you thought Twisted was cool, but couldn't hack the learning curve, Tornado is the answer.

One thing I'm surprised hasn't been mentioned much is the Django Rest Framework (DRF). If you're building a CRUD-heavy website with very separate back and frontend (no django templates) then the fact that DRF can give you a big hyperlinked REST API for free is something I've found extremely useful.

I tend to use Django for big websites and Flask for small websites/microservice APIs.

I like both of them a lot for different reasons:

If I build a more generic web application that will include most of their typical features I'd go with Django. If it is more of an one purpose API type of project or solving a very domain specific problem it would be Flask.

Django gets your out of the door quickly and there are extensions for anything I've ever needed, but it can get in your way later on. If you have to go against its opinions or if you need to actually understand what it does under the hood. E.g. file upload goes trough several hundreds of lines of code if I remember correctly. Most of it probably doesn't apply to your project, but you need to understand it anyway.

Flask projects are also super quick for simple projects, but if it is something more elaborate you really have to spent the extra time setup the architecture accordingly from the get go, otherwise it very easily becomes a big unmaintainable mess.

My experience is mostly b2b products and projects, so scalability is less of an issue for me.

I've found falcon a real pleasure to work with building pure json APIs, super sane approach to hooks and middleware which makes handling auth and db pooling both explicit and simple. Plus it's pretty fast which is always nice for building a REST API.

Seems to me that an accurate analogy is Rails:Django::Sinatra:Flask

I'm a big fan of flask, purely because there's no wrangling `request` objects down your stack, and you can just fish it out later when you need it.

My main complaint would be Flask's 'extensions'. I'm really not a fan of the

> app = Flask(__name__) > db = Database(app)

pattern. it makes getting your db back later a little trickier. It would be nice if the `Flask` instance held it for you, so you could get it back with `flask.current_app` later.

It further doesn't work when the plugin provides a sets of views (i.e. CRUD) e.g.

> app = Flask(__name__) > crud = CrudPlugin(app)

I've yet to see a case of why this isn't implemented as a blueprint.

Extensions can register themselves with the Flask application object, so you can look there: current_app.extensions['whatever']. However, it is not specified what exactly this dictionary contains, so eg. SQLAlchemy puts a custom State class there. You can still get the extension object out of it, it's just that there is no common convention.



For the python web folks, what web server do you tend to put in front of your Django/Flask apps and how do you typically deploy new updates with zero downtime?

Nginx + Gunicorn is what we use. It has worked great for us. We have also tried uWSGI, a waitress for our production and Nginx + Gunicorn have been sure shot winners in terms of scalability and performance.

This is our gunicorn.conf that ensures gunicorn does not cause memory leaks

    import multiprocessing
    import os
    import random
    from getenv import env

    def pre_fork(server, worker):
       f = '/tmp/app-initialized'
       open(f, 'w').close()

    bind = 'unix:///tmp/nginx.socket'
    workers = os.environ.get('WEB_CONCURRENCY', 
    (multiprocessing.cpu_count() * 1 - 1))


       max_requests = MAX_GUNICORN_REQUESTS


        max_requests_jitter = env('MAX_REQUESTS_JITTER', 25)

Nginx is the one I see the most these days.

Having multiple instances behind a reverse proxy allows you to do rolling deploys, which will have no downtime.

For a while I did nginx with gunicorn. No downtime rolling deploys. Just need a git pull and the proper kill signal.

Now I use kubernetes with uwsgi. Once you are kubernetes any app server works, so went uwsgi because it is very very simple.

I currently use Apache with mod_wsgi. New updates involve just touching the .wsgi file. schema changes are a bit more involved obviously.

And here they are some specific numbers on the topic of "Django" VS "Flask" https://python.libhunt.com/project/django/vs/flask . Flask is supposed to have a better code base?

Offtopic but does anyone know of a Django alternative in JavaScript with similar level of maturity?

If you mean in the frontend, AngularJS was going in that direction. Then react came along and the angular developers decided to copy it, in a different language and with even more boilerplate.

I believe nowadays it's ember the one that comes with batteries included, but I haven't used it nor read a lot about it so don't quote me on that.

If you meant the backend, the only one I always hear about is express, but I'm not sure about that one either.

Sails.js is a fill-stack JavaScript framework with similar scope to Django, such as:

- MVC - routing - templating (though, swappable) - ORM

As for maturity, Sails.js has been under active development for around 5 years, with a 1.0 release candidate available.


If a newbie looks into this I would say this : Flask :- Magic Django :- More Magic

P.S. : Great work making a comparison of both, must have been >48 Hours of work. Take a bow sir.

Use Pyramid.

I'm surprised to see a Django vs Flask blog on the frontpage of HN in 2017. So many of us ditched Python for greener pastures as the dev team lost focus on the Zen of Python in recent iterations. I definitely wouldn't start a new webdev project in Python today, even though I used to love it. There are just faster, more convenient alternatives. I've moved all my projects to TypeScript and a lot of people moved to Go.

I am interested in your story. Concrete examples would be helpful. Did the team follow a performance improvement mandate, analyzing the Python system and then deciding how best to proceed, or was performance not the primary motivator?

Both. It was loss of faith in the Python BDFL and core dev team, and also an examination of performance and reliability. Running on V8 and having type safety is a sweet spot that I haven't found elsewhere. Primary motivator was that Python has been creaking along for a while now, with a precarious future and there was finally a clear spot of greener grass to move to.

For the "keep it simple" camp, I wonder why Bottle isn't more popular.

If you need user authentication use django. If it's for APIs use flask or gRPC.

I found Flask-user to be pain free. This is important because almost all applications need some form of persistent user data.

At this point I wouldn't use suggest Django for anything other than a straightforward server-rendered crud app, particularly if the developers are less skilled.

Applications are open for YC Winter 2024

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact