1. 72

  2. 20

    I’ve recently been moved to a Django shop and I definitely miss the sense of “It doesn’t do much more than that.” Django seems like a wizard that you only interact with through a tin-can phone. You trust because you see things happens and because everyone else also talks to the same wizard, but you can’t help but feel a fool.

    While the boilerplate-y nature that I stumble upon in many Flask projects is something I don’t like, nor as the the author mentioned, configuration, I do appreciate the grounds-up approach, the you know exactly what’s going on because you wrote it. That sense of ownership I don’t feel with Django projects.

    1. 10

      While the boilerplate-y nature that I stumble upon in many Flask projects

      I’ve come to see boilerplate as a side-effect of being explicit. I see the same argument made for/against Redux (the JavaScript state management library) and its surrounding ecosystem. I too don’t like boilerplate but 9 times out of 10 I’ll happily trade a lot of boilerplate for being explicit about what’s going on (and often static analysis).

      1. 6

        I felt like that about Django for the first year or two, but it went away once I’d spent enough time spelunking the Django code. None of it is magic, but there is a lot of it.

        1. 2

          This has been a common complaint about Django for many years, so I made mini-django[0]because I too started to enjoy Flask’s simplicity, but every. single. time. my Flask projects bloated in to a frankenstein of semi-supported apps with little consistency between them. Now I can have a single file Django “function” that can use as much or little of Django as needed. Just look at the source of mini-django/mini_django.py.

          [0] https://github.com/readevalprint/mini-django

          1. 1

            http://padrinorb.com/ tries to be a django-inspired framework built out of flask-like components (sinatra). I used to be involved in it and really liked that it had a story of growth. You would start with a one-line project and could evolve it along into new and new structures until it could look similar to the size of a Rails project, which I find appropriate for huge projects. I agree with you that following along with that story gives you a ton of ownership into the project. You know why each component is there, because you chose it.

            The disadvantage is that there’s another ton of work to do on the project side to explain that philosophy, why it’s worth it and how and when people should move along that story. It needed a lot of resources to maintain that.

          2. 15

            As someone who was watching Django since its inception in 2005, and seeing Flask coming on the scene later, I’m surprised to see the same exact argument surfacing after so many years again. And it breaks my heart! Like,

            I’d have spent twice as long ripping out the rest of Django’s bits

            There’s no need to rip anything out. You just don’t use the bits you don’t need, simple as that. Django is just a Python library. Sure you won’t get any related integration (like supporting a novel auth scheme in the built-in admin) but that’s expected, and you don’t get that in Flask either.

            But I always found that the bits you would want to use are usually much more thought out and polished in Django than in other frameworks. (Although I haven’t done any actual comparisons lately.)

            1. 10

              But I always found that the bits you would want to use are usually much more thought out and polished in Django than in other frameworks.

              I love Flask, it’s one of my favourite web frameworks, but what you’re saying is true in a sense. See, Flask’s components are very pluggable and this makes it flexible. Flask has many modules, which I found to be unmaintained (hasn’t had updates for months/years, kinda scary). So because Flask is flexible you can just write everything yourself. Most of the time you don’t want to do that. That’s where Django shines, Django gets maintained so everything Django ships gets maintained. This is one of the strenghts Django has over Flask IMO, just because Flask gets maintained doesn’t mean that all the plugins get maintained, which is a huge weakness if you ask me. The cost of either forking and maintaining it yourself or rewriting everything from scratch are both ridiculously high. Maybe OP has the luxury of writing everything himself or forking and maintaining everything himself, but certainly not everyone can do that.

              1. 7

                I have seen a bunch of flask apps in my career that probably started as the simplest flask app. They all grew into chaotic collections of code, reimplementing a lot of functionality Django provides directly. Problem is that if you look at 10 flask apps they all do it subtly different.

                So instead of setting up flask apps with the standard flask plugins and tinkering for a day or too about initializing then in the right order, you might just start with a Django project and use the parts you need.

                If Django had a Single-App template I think many would not use flask, because Django’s multi app directory layout scares a lot of people off.

                1. 2

                  That is exactly why I made mini-django project, I wanted a single file no install needed flask-like app that could grow as needed: https://github.com/readevalprint/mini-django/blob/master/pico_django.py

            2. 18

              Nice post! I like reading posts that go like this:

              1. I built something real with library/framework/language X
              2. Here are the pros and cons, from my experience

              A lot of articles I see fall down on one of those two points. For example, the author tries to generalize from their toy to the entire world (not realizing that the space of problems is very big), or it’s pure advocacy and they fail to mention any of the cons, which every technology has.

              I mentioned the talk “Production Prolog” here which fits that criteria:


              A lot of the stuff I read about Prolog was like “it’s the best thing ever and let’s use it for everything”, which is not accurate …

              1. 9

                We’ve used Flask for the past 6-7 years, and written dozens and dozens of applications with it, everything from small silly sites to full blown global e-commerce implementations that handle millions of dollars of sales.

                The flexibility it offers, while sometimes a disadvantage, ends up being very useful to us when we have special/odd requirements to fulfill.

                1. 2

                  It seems pretty hard and time consuming to write e-commerce implementation in Flask. Don’t get me wrong, I like Flask, but it seems unsuited for such tasks due to the minimalist nature it embodies. I guess you guys have many in-house modules which you can reuse, which speeds development up quite a bit. How do you people manage?

                  1. 1

                    This was a very, very specialized task that involved gluing together a dozen different services from different departments within the same multinational company; one department built the product catalog, while the other built the product descriptions, while another was responsible for certain variants of each product, not to mention getting inventory from the fulfillment provider warehouses, or the department responsible for pricing, and many of the above was also on a per-country basis.

                    It was going to be time-consuming no matter how you sliced it, really.

                2. 6

                  I prefer Bottle. It has the same features as Flask and it’s faster and smaller.

                  1. 5

                    I’m a big fan of falcon. Flask does have decent docs and ecosystem (supporting libraries) though.

                  2. 2

                    I agree with the list of negatives (particularly jinja2 support), but would add the global request context. It’s very convenient for really small projects but makes the testing story harder than it needs to be when things get more complicated than a few files with a handful of endpoints.

                    1. 2

                      One nice and simple way to write web services is to use plain Node like this:

                      port = process.env.PORT || 8000
                      endpoints = {
                        "GET /": ({ request, response }) => {
                          sendFile(response, 200, "./public/index.html")
                        "POST /frob": ({ request, response, params }) => {
                          // ...
                        (request, response) => {
                          let url = new URL(`https://${request.headers.host}${request.url}`)
                          let route = `${request.method} ${url.pathname}`
                          let params = url.searchParams
                          try {
                            if (endpoints[route]) {
                              await endpoints[route]({ request, response, params })
                            } else {
                              response.end("not found")
                          } catch (e) {
                            response.end("internal error")
                      ).listen(port, () => console.log(`Listening on ${port}...`))

                      If necessary, switch to matching the routes by regexp.

                      This kind of trivial “framework” often feels nicer to work with than even something like Express, because it’s utterly clear what’s going on. Having all the routes defined in a single object makes it super clear what the web service can do. There’s no modular middleware; those things always just confuse me.

                      Basically Node’s standard library is already a decent HTTP server framework; that’s kind of the point.

                      1. 7

                        With the downside that then you need to work with JavaScript. I like simple web services in golang, clojure, and Python, just for my use cases.

                        1. 14

                          On the plus side, though, you don’t have to work with Golang, Python, or Clojure. In matters of taste, there can be no disputes!

                      2. 1

                        I agree with much of the assessment of Flask, especially this:

                        flask.Flask and flask.Blueprint should be the same thing.

                        Blueprint instances are just different enough from Flask instances to be slightly inconvenient. For example, blueprints can be registered to a flask instance, but not to other blueprints, preventing nesting.