Django vs. Flask
git-pull.com
git-pull.com
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...
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.
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.
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.
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.
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.
-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.
http://flask.pocoo.org/docs/0.12/api/#application-object
add_url_ruleHasn't that been inherited from bottle?
Emphasis on the 'almost' :)
Turbogears was doing something similar with @expose about 5 years earlier.
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.
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.
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?
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.
Have you ever tried to write really _pure_ python? I did and it is harder than it needs to be.
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.
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.
SQLAlchemy is damn easy to use.
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.
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 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.
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.
Some people learn re-usable code patterns and concepts, the majority just learn APIs.
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"!
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 :)
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.
- 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.
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.
For help with this: https://www.starterkit.win/
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).
Uuuh I've never encountered this problem
Don't blame Flask, blame whoever hired mediocre developers in your company. No framework that "enforces" things will compensate for bad human capital.
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.
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.
I would never call my devs "mediocre". If they were, I was to blame.
I guess i live in lake Woebegone, according to you.
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.
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.
import socketCOPY CON APPDOCKR.ZIP
p.s. full-webapp-docker-image.zip but hey 8.3 are there for a reason!
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.
Having built couple of toy programs with OCaml, I'd be really interested in building a project in a functional language.
https://docs.microsoft.com/en-us/aspnet/core/publishing/linu...
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).
Another option would be D, although the lack of "batteries" (libraries and tools) is rather concerning.
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.
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.
Now I believe they should only be used for small projects or quick prototypes. Anything beyond that and everything starts getting very confusing.
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.
* 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.
Don't completely understand this one. Also, couldn't you create an immutable-in-practice class?
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.
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.
Lately I've been yearning for a "Flango" distribution with flask and the top twenty extensions supported by a single dev team.
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.
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.
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".
[1] https://engineering.instagram.com/web-service-efficiency-at-...
But see for yourself: https://github.com/reddit/reddit
I don't know where I got that idea from.
https://www.wyc.io/posts/just-build-it-in-django-or-rails/
Instagram, Disqus, Bitbucket, Pinterest.
Apologies in advanced for any marketing copies you don't want to read. The information is there.
Disqus
Instagram
Knight Foundation
MacArthur Foundation
Mozilla
National Geographic
Open Knowledge Foundation
Pinterest
Open Stackhttps://www.quora.com/Would-Pinterest-consider-Flask-in-plac...
Most of the projects in OpenStack use Flask or Pecan - or Falcon for one or two of the more performance sensitive APIs
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
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.
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.
(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.
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.
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.
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.
What examples of magic do you have, specifically?
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.
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
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.
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#...
The team now working on it is not very gifted, and yet they manage to make it evolve because Django makes it easy.
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.
If the particularities of Django are what's in the way of scaling for you, you have bigger issues than Django.
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?
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.
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.
(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.)
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.
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.
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.
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.
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.
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.
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.
And also, of course: benchmark first, optimize later.
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)
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.
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.
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.
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.
What do you think?
https://wakatime.com/django-vs-flask-worksheet
With a comparison between the two:
https://wakatime.com/blog/14-pirates-use-flask-the-navy-uses...
Your guide is way more comprehensive, so mind if I link to it?
I tend to use Django for big websites and Flask for small websites/microservice APIs.
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.
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.
http://flask.pocoo.org/docs/0.12/api/#flask.Flask.extensions
https://github.com/mitsuhiko/flask-sqlalchemy/blob/master/fl...
Having multiple instances behind a reverse proxy allows you to do rolling deploys, which will have no downtime.
Now I use kubernetes with uwsgi. Once you are kubernetes any app server works, so went uwsgi because it is very very simple.
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_GUNICORN_REQUESTS = env('MAX_GUNICORN_REQUESTS', 100)
if MAX_GUNICORN_REQUESTS:
max_requests = MAX_GUNICORN_REQUESTS
MAX_REQUESTS_JITTER = env('MAX_REQUESTS_JITTER', 25)
if MAX_REQUESTS_JITTER:
max_requests_jitter = env('MAX_REQUESTS_JITTER', 25)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.
- 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.
P.S. : Great work making a comparison of both, must have been >48 Hours of work. Take a bow sir.
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.