Django ORM vs Graphql(or whatever API)

I believe I know enough to know that asking about an ORM vs an API sounds really weird. Making API calls to 127.0.0.1 also feels a little weird though so here’s my thing:

I’ve been writing scripts/desktop applications for a little while now. I’ve never had to deal with managing a database and I’ve only consumed API’s. I started on a web project and my plan was to use Postgreql+TimescaleDB, Django, Graphql(graphene), and Next.js. I have the database and Graphql working(like, pretty much mostly) and a next.js project that is the skeleton of a website. I’m considering dropping next.js in favor of htmx and just rendering html from Django views.

Annnnyway, here’s the problem that I’m running into:

I have some processes that are running on the server that will need to make a lot of updates to the database (thousands every second). I’ve started writing those assuming that those would be Graphql mutations. It works for my tests but it feels like a strange solution and my gut feeling is that it won’t scale very well. Keep in mind, my gut knows basically nothing. I was thinking that it might make more sense to make those changes with the ORM or possibly just in SQL. As far as I can tell, I have to use manage.py shell in order to do ORM things in a script outside of the Django views etc. Passing a script feels weird also so I was wondering, what would be an efficient way to add that data?

You are probably already familiar with how Django works, at a very high level: you get a request object that gets passed to a view and the view will use the orm to do whatever it needs to do and return a response object.

All the packages that help with building apis with Django work by enhacing the views in some shape. For GraphQL you have Graphene and Ariadne, for rest you have Django Rest Framework etc.

Now, the whole infrastructure looks something like this (api version):

  1. external client (mobile app, react app - you are building a react app if you use next.js

  2. external api (whatever you build with graphql) - remember, this is a django view

  3. internal api (the orm and models and you could also add 3rd party apis here)

The non api version, eg when you render html in some shape directly in django views:

  1. django views (I’m not familiar with htmx, but I suspect it fits with the django views)

  2. internal api (the orm and models and you could also add 3rd party apis here)

Here comes the complicated part, where you need to take a big decision: you need to figure out where it makes more sense to you to plop your bussiness logic.

  1. in the orm/model internal api
    Pros: you can easily write either django admin commands or celery tasks.
    Cons: the code can get out of hand quite easily

  2. in the views (eg, in your mutations/queries):
    Pros: your backend scripts are now just another client for your api (so you can write them in whatever language you fancy, more flexibility etc)
    Cons: your backend scripts are now just another client for your api (you have the overhead of having to add a mutation for everything you need to do to your database, and secure these “special” mutations etc).

  3. introduce a “service” layer, where you write functions that do your business logic and you call these functions from both your views (mutations and queries) and from your scripts.
    Pros: keep your models lean and to the point and no extra overhead, simplified views code, easier to test etc. Your views and scripts are going to be thin layers on top of your functions, eg the views will just read the request and figure out with what parameters you need to call the service function with. Same for the scripts.
    Cons: you need to write a service function for everything you do.

Obviously, you can use a combination of both (eg, some stuff in the views, some in the models), but I can guarantee that six months down the road you will forget where a particular data alteration happens and you will have to spend time trying to figure out where to look. Been there, done that.

Thank you for the detailed response. My understanding is that the views are for html. I want to be able to use the ORM without html (for some things). For example, I have a script running on the server that reaches out to external devices and then I want to update the database with the information it gets.

I can’t just import the models file and then use the ORM to make changes(unless I can and I tried it wrong?). It looks like I would need to get together any of the ORM commands I want to use and run them in manage.py shell each time.

This leaves me creating an API on a server and then using that API on the same server.

Not really.

They are called views because of the Model-View-Controller design pattern that Django is using. The views are simply functions, or class methods, that return a Http response. If you return a FileResponse, you are returning bytes, not html.

As for the second question, if you write Django Commands (there is a section in the Django Tutorial about them), or Celery tasks after you read the Celery Django integration tutorial on the Celery website, you can use everything Django gives you.

Thank you. I’ll look into Django Commands and Celery tasks more.