Обратные URL-адреса между сайтами Django
Вероятно, простой вопрос, и я просто что-то упускаю, но я застрял в идеях.
У меня есть проект Django, обслуживающий несколько сайтов с sessions.py
и совершенно другой ROOT_URLCONF
s. Один сайт управляет регистрацией пользователей, настройками аутентификации и профиля, другой сайт (в другом домене) выполняет функции файлового менеджера и так далее. Сайты используют одну и ту же базу данных, медиа и шаблоны. Все сайты используют одну и ту же базу пользователей, реализуя своего рода прозрачный механизм единого входа / единого выхода. Это как один большой сайт, охватывающий несколько доменов.
Проблема в том, что у меня много {% 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
на сайте Б и хочу {% url list_users %}
выводитьhttp://a.example.org/users/
". Как лучше всего этого добиться?
В настоящее время я использую отдельные global_menu.html
для каждого сайта, но это нарушает принцип СУХОГО и не очень удобно. И да, я использую Джанго contrib.sites
рамки с четкими SITE_ID
определены в settings.py
для каждого сайта, но пока не использую его где-либо еще.
Обновление: в настоящее время я думаю о переопределении url
тег или обезьяна-патчинг reverse()
, чтобы вызвать исходный, и для исключений выполнить дополнительный поиск в некотором "списке внешних URI". Если бы уже было что-то подобное - я был бы рад услышать.
Заранее спасибо за ответы!
4 ответа
Я реализовал это путем переопределения 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'),
)
Да, вам нужно сделать свой собственный {% 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)
Обратная перезапись для 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 для запуска при запуске
Я бы предложил сделать два изменения. (1) Переместите шаблоны в общий каталог (а не в приложение), если у вас его еще нет. (2) Изучить недавно добавленную функцию пространств имен URL.
Первое изменение позволит вам иметь общий базовый шаблон и выборочно переопределить его для различных приложений / сайтов. Второй может сделать ваши URL "сухими".