Domanda

Probabilmente una domanda semplice e mi sto perdendo qualcosa, ma sono rimasto senza idee.

Ho un progetto Django che serve diversi siti con sessioni.py distinti e ROOT_URLCONF completamente diversi. Un sito gestisce la registrazione dell'utente, le impostazioni di autenticazione e profilo, l'altro sito (su un altro dominio) funge da file manager e così via. I siti condividono lo stesso DB, media e modelli. Tutti i siti condividono la stessa base utenti, implementando una sorta di meccanismo trasparente single sign-on / single-sign-off. È proprio come un grande sito, che si estende su più domini.

Il problema è che ho molti tag {% url%} nei miei modelli e non funzionano quando il modello viene utilizzato su altri siti. E vorrei evitare il più possibile la codifica degli URL.

Ad esempio, sul sito A (a.example.org) ho un

url('^users/

voce in URLconf di A. Quindi, in alcuni modelli global_menu.html ho {% url list_users%} e ovviamente funziona perfettamente, risultando in " / users / ".

Ora c'è il sito B (b.example.org), che condivide molti interni con A. Per avere un aspetto comune, voglio usare lo stesso global_menu.html sul sito B e vuoi che {% url list_users%} produca " http://a.example.org/users/ " ;. Qual è il modo migliore per raggiungere questo obiettivo?

Attualmente sto usando un global_menu.html separato per ciascun sito, ma questo viola il principio DRY e non è molto conveniente. E sì, sto usando il framework contrib.sites di Django con SITE_ID definiti in settings.py per ciascun sito, ma non ancora effettivamente usandolo altrove.

Aggiorna : attualmente sto pensando di reimplementare il tag url o il patching delle scimmie reverse () , per chiamare quello originale, e sulle eccezioni esegui ulteriori ricerche in alcuni "elenchi URI esteri". Se esiste già qualcosa del genere, sarei felice di sentire.

Grazie in anticipo per le risposte!

, 'example.accounts.list_users', name='list_users'),

voce in URLconf di A. Quindi, in alcuni modelli global_menu.html ho {% url list_users%} e ovviamente funziona perfettamente, risultando in " / users / ".

Ora c'è il sito B (b.example.org), che condivide molti interni con A. Per avere un aspetto comune, voglio usare lo stesso global_menu.html sul sito B e vuoi che {% url list_users%} produca " http://a.example.org/users/ " ;. Qual è il modo migliore per raggiungere questo obiettivo?

Attualmente sto usando un global_menu.html separato per ciascun sito, ma questo viola il principio DRY e non è molto conveniente. E sì, sto usando il framework contrib.sites di Django con SITE_ID definiti in settings.py per ciascun sito, ma non ancora effettivamente usandolo altrove.

Aggiorna : attualmente sto pensando di reimplementare il tag url o il patching delle scimmie reverse () , per chiamare quello originale, e sulle eccezioni esegui ulteriori ricerche in alcuni "elenchi URI esteri". Se esiste già qualcosa del genere, sarei felice di sentire.

Grazie in anticipo per le risposte!

È stato utile?

Soluzione

L'ho implementato sovrascrivendo django.core.urlresolvers.reverse con la mia funzione personalizzata:

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

Quindi elencando URLconfs in settings.py in questo modo:

ROOT_URLCONF = 'project.urls_a'

EXTERNAL_URLCONFS = (
    ('http://b.example.com/', 'project.urls_b'),
)

Altri suggerimenti

Sì, dovresti creare il tuo tag {% url%} che utilizza il proprio metodo di inversione.

Ad esempio, per invertire in modo specifico contro urlconf site_a, è possibile utilizzare un metodo come questo:

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)

Sovrascrivi al contrario per Django 1.7.x usando le stesse impostazioni di @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

Ho inserito il codice nel file urls.py da eseguire all'avvio

Suggerirei di apportare due modifiche. (1) Sposta i modelli in una directory comune (anziché per applicazione) se non l'hai già fatto. (2) Esamina l'URL appena aggiunto namespace caratteristica.

La prima modifica ti permetterà di avere un modello base comune e di sostituirlo selettivamente per varie app / siti. Il secondo potrebbe servire a rendere i tuoi URL "più asciutti".

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top