Hacker News new | ask | show | jobs
by aaai 2261 days ago
> I feel like the developer experience is much worse than let's say Django REST Framework

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!

2 comments

I don't understand which parts of DRF you don't like, or why FastAPI is better.

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.

You're probably lucky to have that use-case.

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...

I agree with you on 1) and I'm not saying models and serialisers will always be the right choice. In certain cases custom serialisers will make sense and you will have to write code, but you'd be writing the same code with a framework such as FastAPI or Flask.

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.

This discussion was really valuable to see.

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.

There is a package for DRF that adds automatic validation from type annotations: https://github.com/rsinger86/drf-typed-views (disclaimer: I'm the author)

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.