我设置了受this答案启发的基于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()
然后需要扩展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'))]
我承认这不是很好,但我不希望管理多个数据库。有趣的是,命名空间参数是什么并不重要,但必须给出它。该应用程序的原始命名空间为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'),
.....
在视图中,我向current_app=request.resolver_match.namespace
的每次调用添加了reverse()
kwarg,如django文档中所述。在模板中解析whith的URL不需要任何修改。
总的来说,除了两个例外情况外,这种情况非常有效:
django.contrib.auth.middleware.AuthenticationMiddleware
,因为LOGIN
和LOGIN_REDIRECT
是常量。我想知道这是否是一个干净的方法,如果有上述两个例外的解决方案。如果没有,那么什么是更好的解决方案?
答案 0 :(得分:4)
这是您要找的文章。
它解释了如何设置多个数据库,以及管理控制台与它一起工作。正如它所说,您需要为您的第二个数据库(非默认数据库)创建自定义模型,并使用文档中给出的方法对其进行注册。