基于URL的数据库路由

Chr*_* K. 7 python django

我根据答案设置了基于URL的数据库路由,以便为不同的项目/数据库使用相同的应用程序.项目不需要共享任何数据,访问控制由每个项目自己管理,我需要每个项目的管理站点.与原始帖子一样,我使用数据库路由器和中间件来确定从请求路径使用哪个数据库,例如/test/process/1将路由到数据库test/default/process/2数据库default.

import threading
from django.conf import settings

request_cfg = threading.local()

class RouterMiddleware(object):
    def process_view(self, request, view_func, view_args, view_kwargs):
        path = request.path.lstrip('/').split('/')
        if path[0] in settings.DATABASES:
            request_cfg.db = path[0]

    def process_response(self, request, response):
        if hasattr(request_cfg, 'db'):
            del request_cfg.db
        return response

class DatabaseRouter(object):
    def _default_db(self):
        if hasattr(request_cfg, 'db') and request_cfg.db in settings.DATABASES:
            return request_cfg.db
        else:
            return 'default'

    def db_for_read(self, model, **hints):
        return self._default_db()

    def db_for_write(self, model, **hints):
        return self._default_db()
Run Code Online (Sandbox Code Playgroud)

然后需要扩展url模式以包括引用特定数据库的子路径.我通过硬编码项目级urls.py中的url来做到这一点,如下所示:

urlpatterns = [
  url(r'^default/admin/', include(admin.site.urls)),  # does not work
  url(r'^test/admin/', include(admin.site.urls)),  # does not work
  url(r'^default/', include('logbook.urls', namespace='anything')),
  url(r'^test/', include('logbook.urls', namespace='anything else'))]
Run Code Online (Sandbox Code Playgroud)

我承认这不是很好,但我不希望管理多个数据库.有趣的是,命名空间参数是什么并不重要,但必须给出它.该应用程序的原始命名空间是logbook,它用于遍历应用程序的视图和模板的URL.

然后,在app level urls.py中,必须定义app_name(并且等于原始命名空间):

app_name = 'logbook'

urlpatterns = [
    url(r'^$', views.redirect_index, name='index'),
    url(r'^(?P<date>[0-9]{4}[0-9]{2})/$', views.Index.as_view(), name='index'),
.....
Run Code Online (Sandbox Code Playgroud)

在视图中,我在django文档中解释了current_app=request.resolver_match.namespace每次调用时添加了一个kwarg reverse().在模板中解析whith的URL不需要任何修改.

总体而言,这非常有效,但有两个例外:

  • 任何管理员视图的URL倒置将始终解析为urls.py中的第一个条目
  • 我不能让它与django.contrib.auth.middleware.AuthenticationMiddleware大多数人一起工作,我认为因为LOGIN并且LOGIN_REDIRECT是常数.

我想知道这是否是一个干净的方法,如果有上述两个例外的解决方案.如果没有,什么是更好的解决方案?

Abh*_*non 4

这就是您正在寻找的文章。

Django 多数据库文档

它解释了如何设置多个数据库以及与之配合使用的管理控制台。正如它所说,您需要为第二个数据库(不是默认的数据库)创建一个自定义模型,并使用文档中给出的方法注册它。