Opened 8 months ago
Last modified 8 months ago
#35349 closed New feature
Transaction API does not respect the DATABASE_ROUTERS configuration — at Version 1
Reported by: | Vitaliy Diachkov | Owned by: | nobody |
---|---|---|---|
Component: | Database layer (models, ORM) | Version: | |
Severity: | Normal | Keywords: | transaction, db, database routers |
Cc: | Vitaliy Diachkov | Triage Stage: | Unreviewed |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description (last modified by )
Using the transaction API from django.db.transaction
module directly does not respect the DATABASE_ROUTERS configuration and it does not grab the db_for_write() database alias by default. Instead, it always falls down to django.db.utils.DEFAULT_DB_ALIAS. The expected behaviour for this case would either use db_for_write() or introduce a new db_for_transaction() method for database routers as was proposed in this discussion. The discussion itself has no resolution in a two years, so I have decided to create a dedicated issue for that.
What I mean, if that whenever in code you use:
from django.db import trasnaction @transaction.atomic() def foo(...): # ... do stuff ... transaction.commit()
The atomic()
, commit()
and other functions should access the write/transaction database under the hood.
Note : I am developing an application that switches the database connection on per-tenant bases. The database configurations are added to settings.DATABASES at runtime in a middleware and then, using the contextvars.ContextVar
thread-local variable, I am passing the database alias to use from a middleware to my custom database router. It works fine for reading and writing data outside the transactions, but it fails when it comes to transaction. I could potentially pass the value of ContextVar
as an argument to all Transaction API calls, but it still fails for the third-party libraries that are mostly calling this functions without arguments. I have patched globally django.db.transaction.DEFAULT_DB_ALIAS
to a stub string-like object that resolves dynamically in a runtime to a value of ContextVar
, but that solution seems to be weird and I wish I could make it through configuring DATABASE_ROUTERS
.