问题
I have the following issue:
I need a different database with the same models for each user (or set of users). I have a way of finding out to which database the user is related. The issue is I always have to use the using
method on every query I make.
For example:
Thing.objects.using('appropriate_database').all()
Is there a way to avoid the use of using
and making the user/database relationship implicit somehow?
回答1:
Sounds like a bad design that can't scale to me. You have to duplicate the schema every time you add a user.
A better design would have a table USER with one-to-many and many-to-many relations with entities required by each user.
回答2:
We did it! Let me explain how.
We wrote a custom middleware and registered it as an middleware class inside our settings.py file.
MIDDLEWARE_CLASSES = (
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'our.custom.middleware.Class',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
)
This middleware has a process_request method that creates a thread variable (from threading import local
) to store the appropriate database name for the current user. Since every request is handled by a different thread, we know that our variable's value won't be accidently changed by another thread.
The next step was creating a Database Router and registering it as such.
DATABASE_ROUTERS = ('our.custom.database.Router',)
Attention: The default settings.py
doesn't have a DATABASE_ROUTERS
variable. You'll have to create it.
Our custom Router
has the same implementations for db_for_read
and db_for_write
. The only thing these methods do is return the database name stored on our thread variable.
That's it. Now we don't have to call using
every time we need to recover or save model objects.
回答3:
You can create a 2nd manager on your models:
class MyModelManager(models.Manager):
def get_query_set(self):
return super(MyModelManager, self).get_query_set().using('appropriate_database')
class MyModel(models.Model):
# "objects" is the default manager
objects_db2 = MyModelManager()
field1 = models.CharField(...)
class MyModel2(models.Model):
objects_db2 = MyModelManager()
...
Then use queries MyModel.objects_db2.filter(...).order_by(...)...
来源:https://stackoverflow.com/questions/18016779/different-databases-with-the-same-models-on-django