2017-04-03 12 views
6

Konfiguruję routing bazujący na adresie URL, zainspirowany odpowiedzią this, aby korzystać z tej samej aplikacji dla różnych projektów/baz danych. Projekty nie muszą udostępniać żadnych danych, kontrola dostępu jest zarządzana przez każdy projekt na własną rękę i potrzebuję strony administratora dla każdego projektu. Podobnie jak w oryginalnym wpisie używam routera bazy danych i oprogramowania pośredniego, które określa, która baza danych ma być używana ze ścieżki żądania, np. /test/process/1 zostanie przekierowany do bazy danych test i /default/process/2 do bazy danych default.Routing bazujący na adresach 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() 

Wzory adresów URL należy następnie rozszerzyć, aby uwzględnić podścieżkę, która odnosi się do konkretnej bazy danych. Zrobiłem to przez sztywno adresy URL w urls.py poziomie projektu takiego:

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'))] 

muszę przyznać, że nie jest bardzo ładny, ale nie spodziewam się, aby zarządzać więcej niż kilka baz danych. Co ciekawe, nie ma znaczenia, jaki jest argument przestrzeni nazw, ale należy go podać. Oryginalna przestrzeń nazw aplikacji to logbook i służy do odwracania adresów URL w widokach i szablonach aplikacji.

Następnie w poziomie aplikacji urls.py APP_NAME musi być zdefiniowany (i być równa oryginalnej przestrzeni nazw):

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'), 
..... 

W widokach dodałem current_app=request.resolver_match.namespace kwarg do każdego wezwania reverse() jako wyjaśnione w dokumentacji Django. Rozwiązywanie adresów URL w szablonach nie wymagało żadnej modyfikacji.

Ogólnie działa bardzo dobrze z dwoma wyjątkami:

  • url cofania dla któregokolwiek z widokiem administratora zawsze rozwiązać do pierwszego wpisu w urls.py
  • Nie mogę pracować z django.contrib.auth.middleware.AuthenticationMiddleware głównie , Myślę, że ponieważ LOGIN i LOGIN_REDIRECT są stałe.

Zastanawiam się, czy jest to podejście czyste i czy istnieje rozwiązanie dwóch wyjątków wymienionych powyżej. Jeśli nie, jakie byłoby lepsze rozwiązanie?

+2

W jaki sposób wdrażasz? Wydaje mi się, że najlepszą rzeczą do zrobienia byłoby triage adresów URL w konfiguracji serwera, np. apache, a następnie po prostu użyj dwóch całkowicie oddzielnych aplikacji django wsgi, więc nie musisz się o to martwić. Nie sądzę, aby aplikacja admin django ładnie grała z wieloma bazami danych. Możesz uzyskać pewien przebieg, centralizując bazy danych admin i auth itp. W jednej bazie danych, jeśli nie potrzebujesz wielu baz danych użytkowników. – daphtdazz

+0

Nie myślałem jeszcze o wdrażaniu, pracuję z serwerem Pythona. W każdym razie spodziewam się, że będzie więcej problemów, np. z plikami multimedialnymi i jak powiadasz, wygląda na to, że aplikacja administratora nie będzie działać z wieloma bazami danych. Prawdopodobnie zostawiam wszystko w jednej bazie danych. Dzięki za twoje myśli. –

Odpowiedz

2

To jest artykuł, którego szukasz.

Django Multi DB Documentation

Wyjaśnia, jak skonfigurować wiele db, a konsola administracyjna do pracy wraz z nim. Jak mówi, musisz stworzyć własny model dla drugiej bazy danych (tej, która nie jest domyślna) i zarejestrować ją przy użyciu metody podanej w dokumentacji.

+0

Przeczytałem tę stronę wcześniej, ale oczywiście nie do sekcji o interfejsie administratora.Problem z oprogramowaniem pośredniczącym uwierzytelniania pozostaje jednak. Na razie zdecydowałem się zrzucić pomysł i stworzyć dużą bazę danych dla wszystkich projektów. –

Powiązane problemy