我設置了基於URL的數據庫路由,其靈感來源於this答案,以便爲不同的項目/數據庫使用相同的應用程序。項目不需要共享任何數據,訪問控制由每個項目自行管理,我需要每個項目的管理站點。與原始文章中一樣,我使用數據庫路由器和中間件來確定從請求路徑使用哪個數據庫,例如/test/process/1
將被路由到數據庫test
和/default/process/2
到數據庫default
。基於URL的數據庫路由
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
,它用於在應用程序的視圖和模板中反轉網址。
然後,在應用程序級別的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
kwarg到的reverse()
每個呼叫作爲在Django文檔中解釋。在模板中解析URL並不需要任何修改。
總的來說,這工作得很好但有兩個例外:
- 網址倒車任何的管理意見,將永遠解決在urls.py中的第一項
- 我不能讓它與
django.contrib.auth.middleware.AuthenticationMiddleware
大多工作,我認爲因爲LOGIN
和LOGIN_REDIRECT
是常數。
我想知道這是否是一種乾淨的方法,以及是否有解決上述兩個例外的問題。如果不是,那麼更好的解決方案是什麼?
你如何部署?在我看來,最好的做法是在服務器配置中對網址進行分類,例如apache,然後使用兩個完全獨立的django wsgi應用程序,所以你不必擔心這些。我不認爲django管理員應用程序可以很好地處理多個數據庫。如果您不需要多個用戶數據庫,您可以通過將管理和授權等數據庫集中在一個數據庫中來獲得一些里程數。 – daphtdazz
我還沒有想過部署,我正在使用python webserver。無論如何,我預計會有更多問題,例如與媒體文件一樣,正如你所說,似乎管理應用程序不會與多個數據庫一起工作。我可能會把所有數據都放在一個數據庫中。謝謝你的想法。 –