Django多数据库映射

3
在Django中使用多个数据库时,如何映射数据库。例如:从请求中有一个名为app1的参数,它映射到db1,而另一个请求的app2映射到db2。现在在将请求发送到视图之前如何选择数据库。
DATABASE_APPS_MAPPING = {'app1':'db1','app2':'db2'}


DATABASES = {
  'default': {
  },
  'db1': {
      'ENGINE': 'django.db.backends.mysql',
      'NAME': 'hp1',
      'USER': 'server',
      'PASSWORD': 'hpdata',
      'HOST': '192.168.3.11',
      'PORT': '3306'
  },
  'db2': {
      'ENGINE': 'django.db.backends.mysql',
      'NAME': 'hp2',
      'USER': 'server',
      'PASSWORD': 'hpdata',
      'HOST': '192.168.3.11',
      'PORT': '3306'
  }
}

你希望app1中的所有模型都从db1提供服务,而app2中的所有模型都从db2提供服务吗? - Árni St. Steinunnarson
我希望模型只从app1中提供,但使用db1和db2。 - Rajeev
2个回答

3

假设我可以导入一个函数,该函数可提供给我数据库:

project/app/views.py:

from .utils import which_db, item_search
from django.shortcuts import render
from .models import SomeModel

def some_view(request):
    obj = SomeModel.objects.using(which_db(request)).filter(**item_search(request))
    return render(request, "some_model.html", {'object':obj}

每次附加使用都很麻烦。有一种方法可以将类似的查询路由到不同的数据库(在此处更详细地记录)。

项目/settings.py:

DATABASE_ROUTERS = ['project.db_routes.AppRouter',]
DB_ROUTING = {'app1':'db1','app2':'db2'}

project/db_routes.py:

from django.conf import settings


class AppRouter:
    def __init__(self):
        self.DB = settings.DB_ROUTING

    def db_for_read(self, model, **hints):
        return self.DB.get(self.model.app_label, 'default')

    def db_for_write(self, model, **hints):
        return self.DB.get(self.model.app_label, 'default')

    def allow_relation(self, obj1, obj2, **hints):
        return True

    def allow_migrate(self, db, app_label, model=None, **hints):
        return self.DB.get(app_label, None)

我假设你希望在数据库之间设置外键。如果不是,请从allow_relation函数返回False。allow_migrate函数确保对象仅存在于其正确的数据库中。

我尚未测试此解决方案,但它符合文档要求。


不清楚你在问什么。我看到你正在尽力。我也是。你似乎想要做的是编写一个管理器来设置正确的using子句(但管理器无法访问请求)。没有中间件钩子来处理SQL查询。您的用例可能适用于数据库路由。 - Árni St. Steinunnarson
我的问题非常简单,从我的请求中我想知道是否需要使用app1或app2。因此,当我知道我需要使用app2时,中间件应该怎么做才能设置连接到app2,而不是像在视图中这样设置SomeModel.objects.using(which_db(request)).filter()。 - Rajeev
没有中间件可用。尝试路由解决方案。我认为它可以满足你的需求。 - Árni St. Steinunnarson
如果您需要更复杂的规则,则需要在AppRouter类中编写该判别式。如果您只想将读取发送到只读从服务器并将写入发送到主服务器,则只需在每个函数中返回标识字符串即可。 - Árni St. Steinunnarson

0

即使有自定义中间件,如何选择与app1或app2相关的数据库?有任何示例吗? - Rajeev

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接