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, weilLOGIN
undLOGIN_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?
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
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. –