Llevaba tiempo trabajando con PostgreSQL y MySQL, así que pensaba que un framework web me iba a alejar de los datos. Pasó lo contrario.
En Django cada clase de models.py es una tabla. Los campos son columnas, las ForeignKey son claves foráneas con su ON DELETE, y las migraciones son los ALTER TABLE que antes escribía a mano, pero versionados y con marcha atrás.
Lo que más me costó no fue el ORM, fue acostumbrarme a que el framework ya trae resuelto lo que yo estaba a punto de escribir. Un listado con paginación son cuatro líneas heredando de ListView. La primera vez que lo ves parece magia; la segunda te das cuenta de que simplemente alguien ya escribió ese bucle diez mil veces antes que tú.
La trampa del ORM, y me la comí entera, es el problema N+1. Pintas un listado de entradas con su categoría y Django lanza una consulta por el listado y otra por cada fila. Con tres entradas no lo notas; con doscientas la página tarda segundos. Se arregla con select_related para las ForeignKey y prefetch_related para las relaciones múltiples, y hasta que no miras el SQL que genera el ORM no te enteras de que estaba pasando.
Esa es la conclusión que me llevo: el ORM te ahorra escribir el SQL, no te ahorra entenderlo. Venir de SQL no fue un lastre, fue la ventaja.