2017-04-03 1 views
6

Ich richte URL-basiertes Datenbank-Routing ein, das von this inspiriert wurde, um dieselbe App für verschiedene Projekte/Datenbanken zu verwenden. Die Projekte müssen keine Daten teilen, die Zugriffskontrolle wird von jedem Projekt selbst verwaltet und ich benötige eine Admin-Site für jedes Projekt. Wie in dem ursprünglichen Beitrag verwende ich einen Datenbankrouter und eine Middleware, die bestimmt, welche Datenbank aus dem Anfragepfad verwendet werden soll, z. /test/process/1 wird an die Datenbank test und /default/process/2 an die Datenbank default weitergeleitet.URL-basiertes Datenbank-Routing

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() 

die URL-Muster müssen dann verlängert werden, um den Unterpfad umfassen, die auf eine bestimmte Datenbank bezieht. Ich tat dies, indem Sie die URLs in der Projektebene urls.py wie diese hartzucodieren:

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

Ich gebe zu, dass dies nicht sehr schön, aber ich erwarte nicht mehr als ein paar Datenbanken zu verwalten zu haben. Interessanterweise spielt es keine Rolle, was das Namespace-Argument ist, aber es muss angegeben werden. Der ursprüngliche Namespace der App war logbook und wird für die URL verwendet, um die Ansichten und Vorlagen der App umzukehren.

Dann wird in der App-Ebene urls.py die app_name hat zu definieren (und auf den ursprünglichen Namensraum gleich sein):

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

In den Ansichten Ich habe eine current_app=request.resolver_match.namespace kwarg zu jedem Aufruf von reverse() als erklärt in den Django-Dokumenten. URL-Auflösung innerhalb der Vorlagen musste nicht geändert werden.

Insgesamt ist dies sehr gut mit zwei Ausnahmen funktioniert:

  • URL für eine der Admin-Ansichten Umkehren wird immer in urls.py auf den ersten Eintrag löst
  • Ich kann es nicht mit den django.contrib.auth.middleware.AuthenticationMiddleware funktioniert meist Ich denke, weil LOGIN und LOGIN_REDIRECT Konstanten sind.

Ich frage mich, ob dies ein sauberer Ansatz ist und ob es eine Lösung für die beiden oben genannten Ausnahmen gibt. Wenn nicht, was wäre eine bessere Lösung?

+2

Wie implementieren Sie? Es klingt für mich, dass das Beste, was zu tun wäre, wäre, die URLs in der Server-Konfiguration, z. Apache, und dann einfach zwei völlig separate django wsgi Anwendungen verwenden, so dass Sie sich keine Gedanken darüber machen müssen. Ich denke nicht, dass die Django Admin App gut mit mehreren Datenbanken funktionieren wird. Sie können einige Kilometer erreichen, indem Sie die Datenbanken admin und auth usw. in einer einzigen Datenbank zentralisieren, wenn Sie nicht mehrere Benutzerdatenbanken benötigen. – daphtdazz

+0

Ich habe noch nicht über die Bereitstellung nachgedacht, ich arbeite mit dem Python-Webserver. Jedenfalls erwarte ich, dass es mehr Probleme geben wird, z.B. mit den Mediendateien und wie Sie sagen, es scheint nicht, dass die Admin-App mit mehreren Datenbanken arbeiten wird. Ich werde wahrscheinlich alles in einer einzigen Datenbank hinterlassen. Danke für deine Gedanken. –

Antwort

2

Dies ist der Artikel, den Sie suchen.

Django Multi DB Documentation

Es wird erläutert, wie mehrere db, und die Admin-Konsole mit ihm zu arbeiten zusammen einzurichten. Wie es heißt, müssen Sie ein benutzerdefiniertes Modell für Ihre zweite Datenbank erstellen (die nicht standardmäßig ist) und sie mit der in der Dokumentation angegebenen Methode registrieren.

+0

Ich lese diese Seite vorher aber offensichtlich nicht bis zum Abschnitt über die Admin-Oberfläche.Das Problem mit der Authentifizierungs-Middleware bleibt jedoch bestehen. Im Moment habe ich beschlossen, die Idee fallen zu lassen und eine große Datenbank für alle Projekte zu erstellen. –