I have set-up separate databases for read operations and for write operations. In my DEV environment this points to the same database but under different alias. In PROD environment this gets overwritten to point to 2 separate databases which are connected between each other and basically hold the same data.
Nonetheless, while the configuration works correctly when using my Django web app (starting the webserver, playing around with the logic using my browser), my unit tests, which are creating/modifying and then asserting changes in model instances, are not able to run at all. The error I get when starting my unit tests is:
ValueError: Cannot force both insert and updating in model saving.
My set-up looks like this:
settings.py
DATABASES = {
"default": {
"ENGINE": "django.db.backends.mysql",
"NAME": "django",
"USER": "dj",
"PASSWORD": "mypassword",
"HOST": "127.0.0.1",
"PORT": "3306",
},
"read_db": {
"ENGINE": "django.db.backends.mysql",
"NAME": "django",
"USER": "dj",
"PASSWORD": "mypassword",
"HOST": "127.0.0.1",
"PORT": "3306",
},
"write_db": {
"ENGINE": "django.db.backends.mysql",
"NAME": "django",
"USER": "dj",
"PASSWORD": "mypassword",
"HOST": "127.0.0.1",
# localhost because otherwise client is trying to connect via socket instead of TCP IP
"PORT": "3306",
},
"root": {
"ENGINE": "django.db.backends.mysql",
"NAME": "root",
"USER": "xxx",
"PASSWORD": "zzz",
"HOST": "127.0.0.1",
"PORT": "3306",
},
}
DATABASE_ROUTERS = ["config.db_routers.ReadWriteDatabaseRouter"]
db_routers.py
class ReadWriteDatabaseRouter(object):
"""
A database router to control all operations on the read and write databases.
"""
read_db = "read_db"
write_db = "write_db"
def db_for_read(self, model, **hints):
"""Defines the database to be used for read operations."""
return self.read_db
def db_for_write(self, model, **hints):
"""Defines the database to be used for write operations."""
return self.write_db
def allow_relation(self, obj1, obj2, **hints):
"""Relations between objects are allowed if both objects are in the primary/replica pool."""
db_set = {self.read_db, self.write_db}
if obj1._state.db in db_set and obj2._state.db in db_set:
return True
return None
def allow_migrate(self, db, app_label, model_name=None, **hints):
"""All models end up in this pool."""
return True
My goal is to use a separate database for write and separate database for read operations. For unit tests, or testing in general, I don’t care if Django will create a separate SQLite3 database or another database in MySQL, it just needs to work correctly.
Any ideas on how could I resolve this issue, please?
Thank you