Different databases with the same models on Django

我的未来我决定 提交于 2019-12-10 17:38:50

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!