Недавно я разработал систему электронной коммерции с аналогичными требованиями - многие экземпляры, запущенные из одного проекта, делятся практически всем.Предыдущая версия системы представляла собой набор независимых установок (~ 30), поэтому она была практически не поддерживаемой.Я уверен, что требования по-прежнему отличаются от ваших (например, в моем случае все модели использовали одни и те же модели), но все же было бы полезно поделиться своим опытом.
Вы правы в том, что Джанго непомогите с подобными сценариями из коробки, но на самом деле удивительно легко обойти это.Вот краткое описание того, что я сделал.
Я видел синергию между тем, чего я хотел достичь, и django.contrib.sites
.Кроме того, потому что многие сторонние приложения Django знают, как работать с ним и использовать его, например, для создания абсолютных URL-адресов для текущего сайта.Основная проблема с sites
заключается в том, что он хочет, чтобы вы указали текущий идентификатор сайта в settings.SITE_ID
, что является очень наивным подходом к проблеме с несколькими хостами.Естественно, и то, что вы также упоминаете, - это определить текущий сайт из заголовка запроса Host
.Чтобы решить эту проблему, я заимствовал идею ловушки из django-multisite
: https://github.com/shestera/django-multisite/blob/master/multisite/threadlocals.py#L19
Затем я создал приложение, включающее в себя все функциональные возможности, связанные с аспектом нескольких хостов моего проекта.В моем случае приложение называлось stores
, и среди прочего оно включало два важных класса: stores.middleware.StoreMiddleware
и stores.models.Store
.
Класс модели является подклассом django.contrib.sites.models.Site
.Хорошая вещь о подклассе Site
заключается в том, что вы можете передать Store
любой функции, где ожидается Site
.Таким образом, вы по-прежнему просто используете старую, хорошо документированную и протестированную среду sites
.В класс Store
я добавил все поля, необходимые для настройки всех различных хранилищ.Таким образом, у него есть такие поля, как urlconf
, theme
, robots_txt
и еще много чего.
Функция класса промежуточного программного обеспечения заключалась в сопоставлении заголовка Host
с соответствующим экземпляром Store
в базе данных.Как только соответствующий Store
был получен, он исправил бы SITE_ID
способом, аналогичным https://github.com/shestera/django-multisite/blob/master/multisite/middleware.py.. Кроме того, он посмотрел на store
urlconf
и, если бы не было None, он быустановите request.urlconf
, чтобы применить его специальные требования к URL.После этого текущий экземпляр Store
был сохранен в request.store
.Это оказалось невероятно полезным, потому что я мог делать такие вещи в своих представлениях:
def homepage(request):
featured = Product.objects.filter(featured=True, store=request.store)
...
request.store
стал для меня естественным дополнительным измерением объекта request
на протяжении всего проекта.
Еще одна вещь, определенная в классе Store
, была функция get_absolute_url
, реализация которой выглядела примерно так:
def get_absolute_url(self, to='/'):
"""
Return an absolute url to this `Store` or to `to` on this store.
The URL includes http:// and the domain name of the store.
`to` can be an object with `get_absolute_url()` or an absolute path as string.
"""
if isinstance(to, basestring):
path = to
elif hasattr(to, 'get_absolute_url'):
path = to.get_absolute_url()
else:
raise ValueError(
'Invalid argument (need a string or an object with get_absolute_url): %s' % to
)
url = 'http://%s%s%s' % (
self.domain,
# This setting allowed for a sane development environment
# where I just set it to ".dev:8000" and configured `dnsmasq`.
# The same value was also removed from the `Host` value in the middleware
# before looking up the `Store` in database.
settings.DOMAIN_SUFFIX,
path
)
return url
Так что я мог легко генерировать URL-адреса для объектов, отличных оттекущий магазин, например:
# Redirect to `product` on `store`.
redirect(store.get_absolute_url(product))
Это было в основном все, что мне было нужно для создания системы, позволяющей пользователям создавать новый интернет-магазин, живущий на его собственном домене, через администратора Django.