When I need a simple-ish CRUD app, I use Django. I know the parts I need to know, and learning wasn't too hard. The database schema lives in one easy to view/edit file, no need to both create language objects and write SQL. Jinja2 is the nicest templating language that's not HTML-specific. Deploymemt is easy enough.
That said, I have some issues with Django as well: Integrating JavaScript with the Django goodies (e.g. form system, CSRF prevention) is far from ideal. I remember spending hours to add a form field for multiple handwritten entries "properly", I ended up writing the form template manually and just not using the abstraction for that one field. It worked, but felt hacky. I now had rendering, parsing, and validation in two places.
Permissions are handled the way you'd probably expect them to be: Permissions are strings which users have and pages can require or check them. This is fine for most apps, but sometimes you want multiple views of the same data with complex permissions (e.g. the data determines whether the current user can see the item), Django provides little support there.
I also wish the Admin interface was easier to modify. It can be done, but feels to me like monkeypatching an existing app, not using an abstraction I could build an app on. It's probably meant that way, but I wish there was a framework with a less rigid analogue.
I'm slowly working on my own approach to tackle this problem, mostly focusing on declarative permissions (I wrote about an old version: https://dvdkon.gitlab.io/articles/mocasys-dascore/). I'd appreciate any pointers to other solutions to similar problems.
EDIT: As an aside, here are my criteria for a good CRUD app framework:
- The data model is the source of truth: I shouldn't have to repeat what tables and columns I have, or what constraints are placed on them. Server-side validation and client-side inputs should be autogenerated
- Permissions are all in one place: Critical parts of app security shouldn't be all over the place, especially they shouldn't be duplicated between the backend and frontend.
- Permissions should be granular to both columns and rows: I know this isn't always needed and that it's hard to implement, but sometimes you just need granularity, and hacking it in is, IMO, a bad idea for security reasons (see point above)
- The app is in a git repository, separate from the data it operates on: This is where a lot of "low-code" solutions fail for me, I get the goal of user-extensibility, but when I'm making software that will run a business' core functions, I don't want hidden state. Plain text is the best we've got in that regard.
EDIT2: Another criterion: Transparent handling of history. Keeping every change of an item should't need to be programmed once for every datatype, same for the retrieval UI.