I have some pretty large Flask apps with dozens of top level dependencies and models spanning across many thousands of lines of code. Even if I don't touch the code base for a few months, it's easy to jump back into it.
I'm also a huge fan of Rails, but truthfully I find Flask apps to be easier to reason about and hack on once they grow to a decent size, simply because Blueprints make it really straight forward and intuitive to modularize your application without increasing the complexity of everything by using micro-services.
If anyone wants to jump into Flask and start building real world apps, you may want to check out https://buildasaasappwithflask.com/. It's a full blown course where we build a SAAS application using Flask and Docker. I recently added a free RESTful API bonus section to the course and now that Flask 1.0 out, I'll be adding another free update which will cover updating all of the packages in the main app. Just going to wait for the dust to settle on the 1.0 release first.
Not sure how to quantify that "large" but I've worked on some api backend services written in Flask with a quarter million lines of python code and not feeling "outgrowing" Flask. Granted, it took some good design and effort to make all piece s work together. These days, horizontally scale apps is the way to go.
The nature of Django encourages tight coupling between unrelated parts of the system - Models intertwine database operations and business logic, ModelViews intertwine db operations, business logic and the interface layer.
This is manageable in the small, but when you hit scale, this tight coupling adds a whole bunch of unnecessary complexity to your system. Good luck trying to tune your database when any template can trigger hundreds of db calls!
That said, I'd rather gnaw off my own ankle than develop a production, customer-facing website that breaks any of the preconditions I listed above. Every time I've needed to deviate from the Django Way of doing things, it's felt like I'm swimming upstream against a rapids. For those kinds of projects, I love Flask very, very much.
It's from a good book called Lightweight Django.
I agree -- if you use Django, you have to do it the Django way. Flask is more flexible.
> The nature of Django encourages tight coupling between unrelated parts of the system - Models intertwine database operations and business logic, ModelViews intertwine db operations, business logic and the interface layer.
It totally depends how your architect your application and how you write code.
Any framework you choose, you need to write good code, keep an eye on db operations, enable caching where it is required and you will survive the scale just fine. All the arguments are exactly same in the favor of slack.
Do not spread the FUD that using a framework can magically make your application scale. I have seen very bad and very good code in both Django and flask. If you want your application to scale, you need to carefully work on it there is no silver bullet.
There are good frameworks in PHP too and not all PHP code is garbage.
Hell, some frameworks even come with their own (DS)Language
That being said when you are careful you can probably end up with reasonably structured applications in either Django, Pyramid or Flask.
Newly released version of PyPi is built in Pyramid.
(I would like to see a way of disabling QuerySet traversing, so that if you try to access something that you didn't already prefetch_related/select_related then you just hit an error (and therefore fix it before you go live). The behaviour of just happily issuing hundreds of DB queries in a single request really hides a bunch of architectural and performance issues.)
That said, as the sibling comment says, if you need a simple- to moderate-complexity, mostly CRUD API, and particularly if you need it fast, then Django is a great tool.
I suppose they call it hack now though.
I'll take what is caching for 500, Alex
What did the application do?
How large was the dev team?
I'm not saying exceeding 500k lines is impossible, but it seems like a very large system for a well written codebase with low duplicity. I would love to see what the codebase looks like for such a system written with Flask.
I've managed to do python for 10 years only working on one codebase that size, and I'm not sure it counts - it was made by low skilled devs (we were encouraged not to do anything "clever", like use the language features) mostly cutting and pasting existing code.
Doesn't seem like viable strategy at all, I'd run the other way if I were approach by such a company.
One of those things is its wonderfully simple oath2 helpers (the simplest I've seen, really).
You'll still have to bring your own model layer though. And its ecosystem isn't as rich as flask. That is a shame, because its a wonderful little framework.
I've never written an app that did not need user management, sessions, admin, db access, form processing, views/templating. Web2py is the best I've found (python).
Add a tiny bit of structure to take the guesswork out of how to lay out your app (or module — it’s very easy to load one Silex app into another), and it nicely meets that “in between” you’re talking about!
Those issues all relate to how Django is an all-in-one solution with a lot of modules, which you start dropping one by one as you use different solutions.
For example, Django's cache layer is great, but as you scale you'll want to use Redis clients directly rather than the memcached abstraction.
The ORM is fantastic (and much more intuitive than SQLAlchemy). But as you scale, you'll want to use Postgres' more powerful features without worrying about compatibility with MySQL / SQLite. (Django has made progress in that area with contrib.postgres, but it's still only scratching the surface)
Forms? Templates? Staticfiles? If you're using a JS (Webpack and the like) frontend, forget about this stuff. You're better off not serving the frontend with Django at all, it'll only cause more trouble than is worth.
What's left? The model layer, and the admin that accompanies it. I wouldn't trade the Django admin for the world but it also has a lot of scalability issues and although it's very declaratively customizable, it's much harder to customize specific models.
The auth layer is also probably something you'll keep for a long time, but it's littered with things you will probably not use such as the whole groups/permissions system, or the adminlogs auditing system (which is super cool but the API is very hard to use outside the Admin).
The problem with Flask is it's missing in the "what's left" parts. And if you use Flask, you're missing out on the entire Django ecosystem of apps that make heavy use of the model layer.
But you dear reader statistically will most likely not hit any of these scalability issues (aside from the frontend ones). So don't feel bad picking Django, it's an excellent framework regardless.
Any articles or blog posts you can recommend to give some examples or comparison?
> entire Django ecosystem of apps that make heavy use of the model layer.
Exactly why I don't want to use the django system. I'm happy with the python ecosystem and have yet to find a django only module where no other alternative exist.
Its not that django is a bad web framework; on the contrary, to be honest. I'm just already invested in other modules that django decided to re-invent/design to fit their needs better.
Not really sorry, it's all personal experience.
> I'm happy with the python ecosystem and have yet to find a django only module where no other alternative exist.
What about all the cases where you need support from database schemas? For example let's say you want to have access to Stripe subscriptions from Python and cache them to your database, you'll need something like dj-stripe. There's nothing "in Python" other than an API client because the Python stdlib doesn't have a model ORM.
I will use the official stripe flask checkout example.
> and cache them to your database, you'll need something like dj-stripe. There's nothing "in Python" other than an API client because the Python stdlib doesn't have a model ORM.
With their OpenAPI definitions to create the needed sqla model boilerplate, which creates the needed pgsql tables. For change log of my models it is kept in my py model files and xml with sql diff using a cheat where I implemented a Liquibase python wrapper.
I'm lucky where I work in a not to enterprise env so self-rolled solutions is sometimes acceptable and we try to keep it sane.
Ok, so let's say someone else wants to apply this pattern (it's extremely common after all). Should they do the same thing as you did?
Should the next guy as well? Where does it stop? At some point, you write a library right?
Well that library will end up containing the ORM models. So your choice ends up being between "I will roll my own models" (whether they're autogen'd from openapi or not doesn't matter) and "I will use someone else's models". You're back at exactly the same point as earlier, none of this actually achieved anything, other than give you extra work.
The point I was trying to originally make is that saying you'll do it "in pure Python" instead of "in Django" doesn't actually work. If by "Python" you mean "SQLAlchemy" that makes more sense.
At the end of the day, I wish the Django ORM were ripped out of Django so we could have libraries that depend on Django's ORM without them depending on the entire Django stack. There's also a lot of demand for the other side of this, which is having Django's ORM be replaceable by SQLAlchemy. Then you're no longer talking about "Django vs Flask", but "djangorm vs sqlalchemy".
The final step after this would be to have the Django ORM support SQLAlchemy's model declarations. The Django and SQLA model declarations are already very similar. Then we live in a world where you can swap out the ORM API at the application layer, but have libraries that are compatible with both and don't need to be reimplemented for both Django and SQLAlchemy. (I strongly believe the distinction between the two model APIs is not useful right now due to how similar they are)
They can, I recommend they look at the swagger-codegen api stub templates. There clients as well.
> At some point, you write a library right?
Normally a flask-ext forms around a established python library. Yes now we are back at the tight integration problem, but at-least your knowledge of the py library will not be lost in another eco-system.
> I wish the Django ORM were ripped out of Django so we could have libraries that depend on Django's ORM without them depending on the entire Django stack... Django ORM support SQLAlchemy's model declarations... Then we live in a world where you can swap out the ORM API at the application layer, but have libraries that are compatible with both and don't need to be reimplemented for both Django and SQLAlchemy.
I have used both Flask and Django for a long time, so I think I could contribute a couple of points in this regard.
- Django with a very good documentation and batteries included helps to build a lot of functionality in less time without having to look anywhere else. In the same time, flask being a microframework, you need to look for the batteries yourself and it takes experience and knowledge to know which components to use and which to avoid.
- None of these two frameworks will magically fix the scaling issues or are free to scaling issues.When you hit issues with scaling, you need to find the bottleneck and fix it. There is no other magic bullet here. I would suggest do not be religious about things and try both of them without any bias in your personal projects and then evaluate. Do not form an opinion without knowing something yourself.
I've never heard that before. It's been the go-to backend server at the last few companies I've worked for, and it's the first Python web framework I reach for when I need to roll out a new service. I think its explicitness is hugely wonderful for maintenance: given a route, it's straightforward to figure out exactly what code is being called.
I think its explicitness is hugely wonderful for maintenance
Only if you want DRY to mean "Do repeat yourself".
I also find a lot of the "magic" is found in flask extensions.
My use-case was I was doing a heavy part of an ETL pipeline out of MySQL and it was taking an unreasonable amount of time. PyPy was a roughly ~8x speedup, which ended up being faster than doing direct manipulation with MySQL via the cli (!!!).
That said, if I'm starting a new project where I'm pretty sure I need async io, I'm not sure Python is my first choice. It's got decent facilities but compared to other ecosystems it's not as mature there
If it has such a stigma, I've never heard or read about it.
What feels clunky about celery? The third party broker? Bunch of "magic" code you feel can be simpler as a couple of pika modules? While I like pika it needs a bunch of boiler plate where celery is just multi-broker batteries included solution... which might feel a bit clunky.
I see a lot of zmq solutions in the wild. But I'm happy with my current setup.
> "It's a full blown course where we build a SAAS application using Flask and Docker. I recently added a free RESTful API bonus section to the course and now that Flask 1.0 out, I'll be adding another free update which will cover updating all of the packages in the main app."
EDIT: To avoid hollow naysaying, here are some alternatives to Flask I find much better designed:
- Tornado Web Framework 
- Falcon 
When I first started learning Python / web frameworks, I went with Flask because it was smaller and "simpler". As my project grew however, I had to organize it. I was basically imitating what Django gives you by default, though less cleanly.
I have exactly the opposite experience: Flask is nicer than Django; SQLAlchemy is better than Django ORM. Love a bit of Flask.
Many of these independent components pale in comparison to their Django counterparts in glaring ways—they are often a pain to use, with some pretty questionable internal code choices. They remain used because they are often the only choice out there, even though their implementations are inferior to Django’s.
I say this as someone who has used Flask for over 5 years, as well as nearly 5 years of Django.
Parts that I mentioned are (or were when I compared) light years ahead (especially sqlalchemy).
I feel like most using Flask would consider “Flask components” to be equivalent to Flask extensions—e.g., Flask-SQLAlchemy vs SQLAlchemy proper. Maybe it’s a pedantic nitpick, but I’ve never heard anyone refer to SQLAlchemy as a Flask component in 5+ years, hence my comment about the distinction. But yes, many of the Flask-compatible Python packages you mentioned are quite a joy to use.
Some of the design decisions of Flask just don't seem logical, such as using the db instance when defining model parent classes. Makes for strange contortions when defining multiple model files to prevent circular references or db not found errors.
db = SQLAlchemy(app)
The obvious move at the time was to move to django and I spent some time familiarizing myself with it's own DSL. But boy was i struggling all along the way to do things how I liked in Flask with django. The Django Templates were extremely limiting (no modules) and couldn't even do regular python things and I came to find that extensions for Django were in no better shape than flask's. There was no clear solution for rate limiting and various other things I was looking for.
I've followed rails from a distance for a long time but, coming from python, ruby seemed so abstract to me i could just never figure it out but towards the end of my django time, i was finding that rails did/had everything i wanted and it all worked just the way i wanted it to and it was calling to me really hard. i took a big leap and spent a couple months diving fully into ruby, doing all the tutorials, reading all the books. at this point i am officially converted and my project app with it is already further along than i ever got with flask or django. when they say "ruby/rails is built for programmer happiness", they really mean it. and i can really feel/appreciate it. it's extremely fun to use and to see real progress without having to rack my brain and figure out some internals before i can proceed every so many hours. i'm just getting shit done and things work just how you'd intuitively think they should. rails ftw
I’ve used it off and on since 2010 (as Pylons) and have been happy with it.
Some more links for anyone interested:
Not really global variables. I would analogize it to dynamic variables from Lisp, which are a feature I wish every language had. I strongly disagree it's a hack or gets in the way. Having access to the request from anywhere without explicitly passing it around is really useful.
Er, no. Their value depends on where in the callstack you read it, not on where/how they're imported. They're like global variables but with thread locality, and with a stack of values.
Uses Python3 type annotations to do serialization. Not sure it's ready for production, but it has some very interesting new concepts.
Also worth mentioning Sanic which is fast and I believe dispenses with Flask warts like the thread-local Request object (though it does bill itself as "Flask-like").
Flask is still one of the most approachable frameworks I've used. It's great for getting something hacked out really quickly, but for asynchronous requests Tornado is where it's at.
That being said, when I really want performance I usually reach for Golang.
But Flask wins hands down on the richness of its ecosystem.
Python if there's a specific library I want to use, I'm just hacking out a proof of concept, or I'm working with text.
Golang for higher performance, concurrency, stream processing, and cryptography (it has good libraries for that kind of stuff).
But you can always use the underlying library (http://werkzeug.pocoo.org/), which does send everything through a function. Or just implement WSGI directly.
It would be much cleaner to just define a handler type with the signature: `def handler(r: http.Request) -> http.Response`. Those handlers could be passed to routers (which themselves could be handlers), for example (not tested):
def __init__(self, routes: typing.List[Route]) -> None:
self.routes = routes
def serve_http(self, r: http.Request) -> http.Response:
"""serve_http implements the http.Handler interface"""
for route in self.routes:
return http.NotFound("404 NOT FOUND")
def first_route(self, r: http.Request) -> http.Response:
"""first_route uses shared `db` resource."""
def second_route(self, r: http.Request) -> http.Response:
"""second_route uses shared `db` resource too!"""
I've used Flask in one other instance, and it wasn't too bad, but I missed CherryPy through the process (cleaner looking code, and obviously more familiarity for me) but I was participating at a Hackathon so maybe my experience is a little shifted. Though I never picked Flask due to never liking how it looked from even just the Hello World I was not a fan of how it's written, but that is just me coming from other languages and looking at frameworks like Sinatra (though I don't do any Ruby it was pretty clean) and Nancy (C#).
But you can go from 0-59 with ease and easily translatable templates, etc.
With that said good to see Flask get to 1.0. Long time coming.
I've never understood logging in Flask or how to do it in a sane way for a simple app while using uWSGI, so I'm glad that has some improvements. I don't remember my exact issues but I couldn't get configuration from a text file to work and for some reason configuring it in-code wouldn't work either. I don't understand python's logger in general so I'm sure that's part of the problem. The changelog is vague on details, but hopefully whatever was modified really does make things simpler and solves my issues for me.
You can also log directly to rsyslog with python logger.
The post describes it as "stable for a long time" :)
Also there was no new group this is the official Flask repo.
If a micro-framework adds a "web forms abstraction", honestly, run the other way.
Still, sometimes nice to see all in one place.
def hello_handler(r: Request) -> Response:
def goodbye_handler(r: Request) -> Response:
if __name__ == "__main__":
router = Router("/")
router.register_route("/hello/", "GET", hello_handler)
router.register_route("/goodbye/", "GET", goodbye_handler)
Basically you are left to your own devices, which sounds great, but user+auth is pretty fundamental to be left to a random absentee third-party in my opinion.
Whatever else you do (email, onboarding, sqlalchemy) you can do downstream, or directly in the (or a different ) middleware if you want.
Countless people are already using 0ver, and always will. In other words, 0ver.org is descriptive, not prescriptive.
It was the biggest reason why I choose this job, as many python shops seem to run Django which I'm not a fan of.
I'd be curious to see some sort of flask "bundles" that would allow it to make more sense for large-scale projects.
I personally love it and have used it for a ton of smaller projects. For example, I just deployed this a couple days ago: http://dadjoke.info
Flask has scaled very well and never run into Django dead-ends, like where Django isn't flexible enough to do something and requires a hack.
For example, a user who has AT&T can receive a text by emailing it to <phonenumber>@txt.att.net.
I'm someone who quit web programming in around 2008 while IE6 was still a thing. I used to write PHP without a framework. As someone just getting back into it, Django and Flask or downright magical. I can do so much so quickly that would have taken days to do before. With Flask-RESTful you can turn some code into a microservice in about 10 minutes.
For me, this is what makes these libraries great, not that they will fit every need of every app ever.
Otherwise I am a big fan of Django, I think it is possibly the best web dev framework out there even if I work in asp.net for most of the time.