vendredi 14 novembre 2014

Django multiples bases de données et l'erreur « Impossible d'exécuter dans une transaction read-only » - Stack Overflow


I used the Django docs to set up multiple databases in a master-slave configuration. My routers are set up correctly, and I can see that reads and write go to the correct respective database, but I am running into an error with some of my API calls:


cannot execute [UPDATE or DELETE] in a read-only transaction


In the API handlers where this happens, I am updating or deleting some other model as part of the same call, and Django seems to want to use a slave database for those transactions instead of master.


A workaround I found is to chain .using('default') before update() or delete(), which basically forces Django to use the master database for the update or delete. But this feels hacky and bandaid-ish, so I want to make sure there isn't a better way to do this.


Any help is much appreciated.




Have you tried the following? This was copied out of the Django docs page:


import random

class MasterSlaveRouter(object):
def db_for_read(self, model, **hints):
"""
Reads go to a randomly-chosen slave.
"""
return random.choice(['slave1', 'slave2'])

def db_for_write(self, model, **hints):
"""
Writes always go to master.
"""
return 'master'

def allow_relation(self, obj1, obj2, **hints):
"""
Relations between objects are allowed if both objects are
in the master/slave pool.
"""
db_list = ('master', 'slave1', 'slave2')
if obj1._state.db in db_list and obj2._state.db in db_list:
return True
return None

def allow_migrate(self, db, model):
"""
All non-auth models end up in this pool.
"""
return True

Finally, in the settings file, we add the following (substituting path.to. with the actual python path to the module(s) where the routers are defined):


DATABASE_ROUTERS = ['path.to.AuthRouter', 'path.to.MasterSlaveRouter']


I used the Django docs to set up multiple databases in a master-slave configuration. My routers are set up correctly, and I can see that reads and write go to the correct respective database, but I am running into an error with some of my API calls:


cannot execute [UPDATE or DELETE] in a read-only transaction


In the API handlers where this happens, I am updating or deleting some other model as part of the same call, and Django seems to want to use a slave database for those transactions instead of master.


A workaround I found is to chain .using('default') before update() or delete(), which basically forces Django to use the master database for the update or delete. But this feels hacky and bandaid-ish, so I want to make sure there isn't a better way to do this.


Any help is much appreciated.



Have you tried the following? This was copied out of the Django docs page:


import random

class MasterSlaveRouter(object):
def db_for_read(self, model, **hints):
"""
Reads go to a randomly-chosen slave.
"""
return random.choice(['slave1', 'slave2'])

def db_for_write(self, model, **hints):
"""
Writes always go to master.
"""
return 'master'

def allow_relation(self, obj1, obj2, **hints):
"""
Relations between objects are allowed if both objects are
in the master/slave pool.
"""
db_list = ('master', 'slave1', 'slave2')
if obj1._state.db in db_list and obj2._state.db in db_list:
return True
return None

def allow_migrate(self, db, model):
"""
All non-auth models end up in this pool.
"""
return True

Finally, in the settings file, we add the following (substituting path.to. with the actual python path to the module(s) where the routers are defined):


DATABASE_ROUTERS = ['path.to.AuthRouter', 'path.to.MasterSlaveRouter']

0 commentaires:

Enregistrer un commentaire