That said, I don't see as much written about FastAPI and Starlette. I want to recommend it for a major project. Is there a large community around Starlette/FastAPI? Have you used it for large mission critical projects with many users? Would love to hear more about real world usage.
The creator of Django-Rest-Framework, Tom Christie, created a new API framework with what he thought would be the best approach for building APIs in modern Python. It was called APIStar.
APIStar had to deal with some complexities underneath like supporting WSGI (the same used by Flask and Django) and ASGI, the new standard, etc. So, at some point, Tom decided that a new approach was needed. So, he created a new framework/toolkit form scratch, based on ASGI, called Starlette. The server part of APIStar was deprecated and from then on APIStar was only a set of tools for OpenAPI validation.
Starlette was made to be a minimal micro-framework and toolkit at the same time, so that other tools could be built on top of it, but providing a very solid foundation, and the best performance available in Python, on par with NodeJS and Go.
Then, FastAPI was created on top of Starlette, inheriting a lot of the ideas form APIStar (that actually come from even before, with Hug) and updating/improving them, to use standard Python type hints, dependency injection, OpenAPI with docs by default, etc.
About community, you can check the FastAPI Gitter chat, it has a lot of people and there's always someone asking questions and many great community members helping too.
And yeah, FastAPI is being used for what could be called major projects, e.g. Microsoft APIs for Windows (among others).
Disclaimer: I created FastAPI :)
https://www.youtube.com/parttimelarry
My recommendation is to just go with Django until the performance becomes a problem and it can't be solved by a "boring" solution such as throwing more hardware at it. Even after that, you can still squeeze out extra performance by using Serpy serialisers instead of the built-in DRF ones. Finally, if performance is still a problem then you could potentially use one of these frameworks. In most cases though, your underlying data store will be the bottleneck.
In my client's case, we were looking at a couple requests per second maximum, so they unnecessarily spent extra time learning and using an obscure framework without actually benefiting from it in any way.
Give FastAPI a try! You probably have DRF-Stockholm-syndrome like many do. The joy of having all pieces fit right in and be understandable and have validation auto-generated from type annotations (if you choose to) is a-f-mazing!
After using DRF quite a lot for quite a while I can clearly self-diagnose myself as being abused by it - such ugly patterns you always end up coding around and fighting the framework everywhere...
Use Flask if you're afraid of Python async, there's probably good reasons to be, never had to debug it in production... but LIKING DRF?! I cannot fathom that, I mean, one can like Django itself, it's good for what it was built to do, but what abominations ppl built on top of it instead of starting from scratch... ugh!
In my case the reason I like DRF is because it handles most of the work for me - I do my best to make my APIs RESTful which means I expose the underlying data model whenever possible. DRF makes that easy and I only need to handle the authentication classes and hiding sensitive fields in the serialiser.
As an example, let's assume I have a User model in Django and I want the mobile app to be able to read and edit the user's profile (name, bio, etc). With DRF I just create a ModelSerializer for my User model, put it in a ViewSet with the appropriate permission classes (so write operations are only allowed on the currently logged in user) and call it a day.
With FastAPI, looking at their homepage, it seems like I have to implement every single HTTP method (GET, PUT and PATCH in this case) separately? I just don't see the point.
Maybe if you're looking to create an RPC-style API then I guess it could get in the way, but for REST APIs I don't see why this is better.
Most problems I had where with:
(1) deeply nested tree-like objects updates - model serializers have limited support for nested updates, but it breaks down fast, if your frontend-exposed data looks more like trees than tables you'll be fighting it all the way
(2) REST semantics can only get you that far! You end up doing some form of domain-driven-design sooner or later and your verbs are no longer (just) create/read/update - you have "approve", "reject", "approve with comment", "flag for review", "restore to version 123" etc. REST is not CRUD, you can have REST semantics with only R from the default actions and everything else can be domain specific.
In general I prefer to (a) not expose to the API the actual backend's data model in all its gory complexity and (b) figure out what actions make sense for the application domain, drop the CRUD handcuffs.
Once these choices are made, which I now prefer to do early on, pre-emptively, something like DRF becomes pure-pain, 0% gain: I use nothing from it, and it's too dumb to autogenerate stuff like validation or to offer some structural patterns from which to hang code for things like sub-object permission checks or anything like that...
Regarding 2), REST will get you most of the way there, and depending on what "approval" means (does it trigger some process, or does it just change a flag in the database?) it might just be a PATCH "approved = true" on the RESTful endpoint, but when that's not the case you can indeed extend DRF ViewSets with custom actions.
I disagree on not exposing the data model; unless the model is really bad or needlessly complex, I think exposing the model is fine instead of "fabricating" a new model full of RPC-style endpoints. I've wasted way too much time in RPC-land where every little extra bit of data needed a change in some other microservice managed by another team with a convoluted deployment process meaning the change took a good part of the day, where as if they were just using REST I would've had the data to begin with. I don't think CRUD is handcuffs, at least the "R" part feels very valuable to me.
I started off with FastAPI, and it got me off the ground really quickly without a lot of boilerplate, and my API was mostly read only, internal, I didn't even bother with authentication at this point. The prototype worked well.
But then I started to add in all the grown-up, boring stuff and realized would have to do a lot from scratch. Now porting it to Django/DRF and the stability feels really nice. I kinda wish I had just started with DRF now.
Regarding other commentary on DRF: I wonder how many pain points result from trying to squeeze non-CRUD operations into DRF's ModelViewSet/ModelSerializer constructs? My company's approach has been to use that DRF magic for dumb CRUD resources and use plain function-based views for everything else, with the freedom to use Pydantic/Marshmallow/etc. This has made us very productive and I can't image having to write create/update/delete/get/list operations one at a time.
That said, I'm sure there are use cases that DRF isn't suited for and I would definitely look at FastAPI for new projects.
But it's lovely and a pleasure to work with, most developer friendly thing I've ever touched lately!