Обратные URL-адреса между сайтами Django - PullRequest
8 голосов
/ 03 августа 2009

Вероятно, простой вопрос, и я просто что-то упускаю, но я застрял в идеях.

У меня есть проект Django, обслуживающий несколько сайтов с разными sessions.py и совершенно разными ROOT_URLCONF с. Один сайт управляет регистрацией пользователей, настройками аутентификации и профиля, другой сайт (в другом домене) выполняет функции файлового менеджера и так далее. Сайты используют одну и ту же базу данных, медиа и шаблоны. Все сайты используют одну и ту же базу пользователей, реализуя своего рода прозрачный механизм единого входа / единого выхода. Это как один большой сайт, охватывающий несколько доменов.

Проблема в том, что у меня много шаблонов {% url %} в моих шаблонах, и они не работают, когда шаблон используется на других сайтах. И я бы хотел как можно больше избегать жесткого кодирования URL.

Например, на сайте A (a.example.org) у меня есть

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

запись в URL-адресе А. Затем в каком-то шаблоне global_menu.html у меня есть {% url list_users %}, и, очевидно, он работает отлично, в результате получается "/users/".

Теперь есть сайт B (b.example.org), который разделяет множество внутренних элементов с A. Чтобы иметь общий вид, я хочу использовать тот же global_menu.html на сайте B и хочу, чтобы {% url list_users %} вывод "http://a.example.org/users/". Как лучше всего этого добиться?

В настоящее время я использую отдельные global_menu.html для каждого сайта, но это нарушает принцип СУХОГО и не очень удобно. И да, я использую Django contrib.sites framework с различными SITE_ID s, определенными в settings.py для каждого сайта, но пока еще не использую его где-либо еще.

Обновление : В настоящее время я думаю о переопределении тега url или исправлении обезьян reverse(), чтобы вызвать исходный тег, а при исключениях выполнить дополнительный поиск в некотором «списке внешних URI» , Если бы уже было что-то подобное - я был бы рад услышать.

Заранее спасибо за ответы!

Ответы [ 4 ]

12 голосов
/ 05 августа 2009

Я реализовал это, переопределив django.core.urlresolvers.reverse своей пользовательской функцией:

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

Затем перечислите URLconfs в settings.py следующим образом:

ROOT_URLCONF = 'project.urls_a'

EXTERNAL_URLCONFS = (
    ('http://b.example.com/', 'project.urls_b'),
)
2 голосов
/ 05 августа 2009

Да, вам нужно создать собственный тег {% url %}, который использует собственный метод обращения.

Например, для обратного обращения к site_a urlconf, вы можете использовать такой метод:

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)
1 голос
/ 08 января 2015

Обратная перезапись для Django 1.7.x с использованием тех же настроек из @ 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

Я поместил код в файл urls.py для запуска при запуске

0 голосов
/ 03 августа 2009

Я бы предложил сделать два изменения. (1) Переместите шаблоны в общий каталог (а не в приложение), если у вас его еще нет. (2) Исследуйте недавно добавленную функцию URL namespaces .

Первое изменение позволит вам иметь общий базовый шаблон и выборочно переопределить его для различных приложений / сайтов. Второй может сделать ваши URL "сухими".

...