2. doing real world situations with slightly weird scenarios: This is very confusing. Why did they make this so complicated.
3. after digging into the source code and reading the docs: Oh this makes sense after all. I'm going to extend it where need be but overall stick to the pattern
4. after hiring 5 engineers to work on the same code base: DRF is the bible and and shall heap scorn all MRs that deviate from its mantras.
I have started building a new product. I used standard serializers for everything I can get away with.
If I hit a pain point with a serializer that I can't solve in 10 minutes I drop back to manual serialization methods and leave it at that.
When I have to tidy up or bring more people we try to do everything by the book because, as you said, there's a lot of very good reasons why REST framework is structured the way it is and the predictability it brings is worth the cost of dealing with edge-case quirkiness.
It is pretty confusing, which is why I advocate using only the core pieces of it. This way you get basically all of the benefits, but without each new developer needing to read through hundreds of pages of extra documentation to try to understand lots of random design patterns that might not even be a good idea in the first place.
When I've created style guides for startups, I've been pretty explicit about saying "We use REST framework, but here are all the pieces we don't use, and these are all of the sections of documentation that you don't need to read or understand."
In my experience, most CRUD flask apps end up replicating 80-90% of django projects with 200-300% of the effort. Heck, getting pytest working with flask and sqlalchemy is still a struggle.
ORM, IAM, admin interface, are all included or supported at a decent enterprise-level by Django and will save a TON of early dev hours and rookie mistakes. Remember, this advice is geared at small organizations (startups), which means there is plenty of backend and internal infrastructure required.
Yes, I also found the Django ORM to be absolutely horrendous. The need for using a serializer was also incredibly offputting and the default behavior of said serializers was almost always unhelpful and in fact caused more work than just crafting a JSON (or XML) object as I would do in Flask. Why some developers prefer these awful abstractions is beyond me.
I actually like the Django ORM. Something that I learned working with Django 8+ years is that to use its ORM effectively, you have to play Django's game. Sometimes just by denormalizing a few fields will make some queries/relationships way easier.
At work we have a marketplace engine and a digital wallet/financial app built entirely with Django (100k+ loc) and we don't have a single raw SQL query, everything is done with the Django ORM.
The ORM works pretty well as long as you only need to do pretty basic CRUD queries, though I do agree that it gets much worse as your queries get more complex.
Serializers are definitely one of the worst parts of DRF. Anecdotally, I used Pydantic (instead of Marshmallow as the author recommends) to get around this.
I use pydantic for serializers in Django too- and recently started experimenting with Django Ninja https://django-ninja.rest-framework.com/ if you haven't seen it already.
The learning curve is steeper than a lot of stuff in the Django ecosystem but I felt the payoff was well worth it. It’s a bit like Django itself: maximally decomposable and expressive, so much so that the “right” way to do something can be unclear at first. I found it hard to wrap my head around the division of labor between serializers, views and viewsets, but it eventually made sense and now I see the elegance in it.
IMO, Django Rest Framework has too much magic for my tastes. I haven't spent much time with it (which is maybe why it's so confusing), but it always seems like I need to set certain properties and then it "just works"; I haven't found a good list of those magic properties.
The reality is that DRF documentation can fail at the edges because it's a big framework, however it's ridiculously well documented compared to 95% of frameworks or libraries I've used.
For the edge cases, you can read the source code; it's very clear and well commented. And if you fail to understand a feature, it's relatively easy to drop to a lower level of abstraction without losing too much.
Ex: don't like nested serializers in a read-only method? Just write a serializer method and return your own JSON. Can't grok ViewSets with mixins? Just use a regular API view and override what you need. Don't like routers? Use regular views, and so on.
1. started hello world app: wow magic!
2. doing real world situations with slightly weird scenarios: This is very confusing. Why did they make this so complicated.
3. after digging into the source code and reading the docs: Oh this makes sense after all. I'm going to extend it where need be but overall stick to the pattern
4. after hiring 5 engineers to work on the same code base: DRF is the bible and and shall heap scorn all MRs that deviate from its mantras.