2009-08-03 24 views
8

Wahrscheinlich einfache Frage und ich vermisse nur etwas, aber ich bin stecken aus Ideen.Django Cross-Site-Reverse-URLs

Ich habe Django Projekt mehrere Standorte mit unterschiedlichen sessions.py und völlig anderen ROOT_URLCONF s. Eine Website behandelt die Benutzerregistrierung, die Authentifizierung und die Profileinstellungen, eine andere Site (in einer anderen Domäne) fungiert als Dateimanager und so weiter. Websites teilen dieselbe DB, Medien und Vorlagen. Alle Websites nutzen die gleiche Benutzerbasis und implementieren eine Art transparenten Single-Sign-On-/Single-Sign-Off-Mechanismus. Es ist wie eine große Site, die sich über mehrere Domains erstreckt.

Das Problem ist, ich habe viele {% url %} Tags in meinen Vorlagen, und sie funktionieren nicht, wenn Vorlage auf anderen Websites verwendet wird. Und ich möchte vermeiden, URLs so hart wie möglich zu codieren.

Zum Beispiel vor Ort A (a.example.org) Ich habe einen

url('^users/$', 'example.accounts.list_users', name='list_users'), 

Eintrag in A die URLconf. Dann, in einigen global_menu.html Vorlage habe ich {% url list_users %} und offensichtlich funktioniert es perfekt, was zu "/users/".

Jetzt gibt es Platz B (b.example.org), viele Einbauten mit A. teilen, um gemeinsame Look-and-Feel ich die gleiche global_menu.html vor Ort B verwenden möchten, und wollen {% url list_users %} ausgeben "http://a.example.org/users/ ". Wie kann ich das am besten erreichen?

Derzeit verwende ich separate global_menu.html für jede Website, aber das verletzt DRY-Prinzip, und nicht wirklich praktisch. Und, ja, ich benutze Djangos contrib.sites Framework mit verschiedenen SITE_ID s definiert in für jeden Standort, aber noch nicht tatsächlich tatsächlich woanders.

aktualisieren: Zur Zeit von Ich denke url Tag oder Affe-Patchen reverse() Neuimplementierung, das Original zu nennen, und auf Ausnahmen in einiger „fremden URI-Liste“ nachschlagen zusätzliche auszuführen. Wenn es so etwas schon gibt, würde ich mich freuen zu hören.

Vielen Dank im Voraus für Antworten!

Antwort

12

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 Liste URLconfs in wie folgt:

0

Ich würde vorschlagen, zwei Änderungen vorzunehmen. (1) Verschieben Sie Vorlagen in ein gemeinsames Verzeichnis (statt pro Anwendung), wenn Sie dies nicht bereits getan haben. (2) Untersuchen Sie die neu hinzugefügte URL namespaces.

Mit der ersten Änderung können Sie eine gemeinsame Basisvorlage erstellen und diese selektiv für verschiedene Apps/Websites überschreiben. Die zweite könnte dazu dienen, Ihre URLs "trockener" zu machen.

+0

(1) ist bereits getan. (2) ist eine nette Funktion, danke für das Hervorheben, aber hilft nicht viel für nicht existierende benannte URLs. Ich habe versucht, etwas wie 'URL (' http: \/\/a \ .example \ .com/users/', Lambda r: None, name =' list_users ') 'zu B's URLconf hinzuzufügen, aber das tut es nicht' Ich arbeite wie erwartet (gibt "/ http: ..." zurück). – drdaeman

2

Ja, Sie müssten Ihr eigenes {% url %} Tag erstellen, das seine eigene Umkehrmethode verwendet.

Zum Beispiel umkehren spezifisch gegen das Site_A URLconf dann könnten Sie eine Methode wie folgt verwenden:

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) 
+0

Danke! Ich habe Monkey-Patching 'reverse()' beendet (setzen Sie meinen eigenen Code in eine getrennte Antwort). – drdaeman

1

umge für Django 1.7.x überschrieben werden aus den gleichen Einstellungen @drdaeman

# -*- 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 den Code in der Datei urls.py platziert beim Start auszuführen

Verwandte Themen