Django Cross-Site-Reverse URLs
Frage
Wahrscheinlich einfache Frage, und ich bin nur etwas fehlt, aber ich bin aus Ideen stecken.
Ich habe Django-Projekt mehrere Standorte mit unterschiedlichen sessions.py
dienen und ganz anderen ROOT_URLCONF
s. Eine Website behandelt die Benutzerregistrierung, Authentifizierung und Profileinstellungen, andere Seite (auf einer anderen Domäne) fungiert als Dateimanager und so weiter. Seiten teilen sich die gleiche DB, Medien und Vorlagen. Alle Websites, teilen die gleiche totzukriegen, eine Art transparenten Single-Sign-On-Implementierung / Single-Sign-off-Mechanismus. Es ist wie eine große Website, über mehrere Domänen hinweg.
Das Problem ist, ich habe eine Menge {% url %}
-Tags in meinen Vorlagen und sie funktionieren nicht, wenn Vorlage der auf anderen Websites verwendet. Und ich möchte so viel wie möglich hartzucodieren URLs vermeiden.
Zum Beispiel vor Ort A (a.example.org) Ich habe ein
url('^users/$', 'example.accounts.list_users', name='list_users'),
Eintrag in A den URLconf. Dann in einiger global_menu.html
Vorlage Ich habe {% url list_users %}
und offensichtlich funktioniert es perfekt, was zu einem "/users/
".
Jetzt gibt es Website B (b.example.org), viele Einbauten mit A. teilen gemeinsam haben Look-and-Feel Ich möchte die gleiche global_menu.html
vor Ort B verwenden und wollen {% url list_users %}
ausgeben „http://a.example.org/users/
“ . Was ist der beste Weg, ich dies erreichen kann?
Derzeit bin ich mit separaten global_menu.html
für jeden Standort, aber das verletzt DRY-Prinzip und nicht wirklich praktisch. Und, ja, ich bin mit Django contrib.sites
Rahmen mit unterschiedlichen SITE_ID
s in settings.py
definiert für jeden Standort, aber noch nicht wirklich es anderswo verwendet wird.
Aktualisieren : Derzeit url
Tag oder Affen-Patching reverse()
, das Original zu nennen und auf Ausnahmen durchführen zusätzliche aufblicken in einigen „fremden URI-Liste“ Ich denke an die Neuimplementierung. Wenn es schon so etwas existiert. - Ich würde gerne hören,
Vielen Dank im Voraus für die Antworten!
Lösung
ich implementiert haben sie durch zwingende django.core.urlresolvers.reverse
mit meiner benutzerdefinierten Funktion:
from django.core import urlresolvers
from django.conf import settings
__real_reverse = urlresolvers.reverse
def reverse(viewname, urlconf=None, args=None, kwargs=None, prefix=None):
try:
return __real_reverse(viewname, urlconf, args, kwargs, prefix)
except urlresolvers.NoReverseMatch, no_match:
external_urlconfs = getattr(settings, 'EXTERNAL_URLCONFS', [])
for p, c in external_urlconfs:
c = urlresolvers.RegexURLResolver(r'^/', c)
try:
return p + c.reverse(viewname, *args, **kwargs)
except urlresolvers.NoReverseMatch:
pass
raise no_match
urlresolvers.reverse = reverse
Dann URLconfs in settings.py
wie Eintrag:
ROOT_URLCONF = 'project.urls_a'
EXTERNAL_URLCONFS = (
('http://b.example.com/', 'project.urls_b'),
)
Andere Tipps
Ja, Sie müssen Ihren eigenen {% url %}
Tag machen, die ein eigenes Umkehrverfahren verwendet.
Zum Beispiel umkehren spezifisch gegen die Site_A URLconf dann könnten Sie eine Methode wie folgt verwendet werden:
from django.core.urlresolvers import reverse
import site_a
def site_a_reverse(viewname, args=None, kwargs=None):
# If your sites share the same database, you could get prefix from Site.objects.get(pk=site_a.settings.SITE_ID)
prefix = 'http://a.example.com/' # Note, you need the trailing slash
reverse(viewname, urlconf=site_a.urls, args=args, kwargs=kwargs, prefix=prefix)
Reverse-Überschreibung für Django 1.7.x die gleichen Einstellungen von @drdaeman mit
# -*- coding: utf-8 -*-
from django.core import urlresolvers
from django.conf import settings
__real_reverse = urlresolvers.reverse
def reverse(viewname, urlconf=None, args=None, kwargs=None, prefix=None, current_app=None):
try:
return __real_reverse(viewname, urlconf, args, kwargs, prefix, current_app)
except urlresolvers.NoReverseMatch, no_match:
external_urlconfs = getattr(settings, 'EXTERNAL_URLCONFS', [])
for p, c in external_urlconfs:
urlconf = c
try:
return p + __real_reverse(viewname, urlconf, args, kwargs, prefix, current_app)
except urlresolvers.NoReverseMatch:
pass
raise no_match
urlresolvers.reverse = reverse
Ich legte den Code in der urls.py Datei beim Start auszuführen
Ich würde vorschlagen, zwei Änderungen vornehmen. (1) Verschieben Vorlagen auf ein gemeinsames Verzeichnis (anstelle von pro-Anwendung), wenn Sie nicht bereits. (2) Untersuchen Sie die neu hinzugefügte URL Namespaces Feature.
Die erste Änderung ermöglicht es Ihnen, eine gemeinsame Basis-Vorlage zu haben und es selektiv für verschiedene Anwendungen / Webseiten, außer Kraft setzen. Der zweite könnte dazu dienen, Ihre URLs „trockeneren“ zu machen.