|
Оглавление
|
Система сайтов Django является базовой средой, которая позволяет вам управлять множеством сайтов с помощью одной базы данных и одного проекта Django. Это абстрактная концепция и её не всегда легко понять, поэтому мы начнём с описания ряда сценариев где эта особенность Django может быть полезной. Как мы рассказывали в главе «Введение в Django», сайты LJWorld.com и Lawrence.com управляются одной новостной компанией: газетой Lawrence Journal-World в городе Lawrence, штат Канзас. Сайт LJWorld.com сфокусирован на новостях, в то время как сайта Lawrence.com сосредоточен на местных развлечениях. Но иногда корреспонденты желают разместить свою статью на обоих сайтах. Мозгодробящим способом решения этой задачи будет использование раздельных баз данных для каждого сайта и наличие требования к корреспондентам о необходимости размещения их статьи дважды: на одном и на другом сайтах. Но этот метод неэффективен и приводит к дублированию информации в базе данных. Есть ли решение получше? Оба сайта используют единую базу данных для статей и статья ассоциирована с одним или несколькими сайтами с помощью отношения «многие-ко-многим». Среда управления сайтами предоставляет таблицу базы данных через которую статьи ассоциируются с сайтами. Сайты LJWorld.com и Lawrence.com имеют функциональность для уведомления пользователей по электронной почте о появившихся новостях. Это очень просто: пользователь регистрируется на форме сайта и немедленно получает по электронной почте сообщение: «Спасибо за вашу подписку.» Будет неэффективно и избыточно реализовывать код регистрации дважды, таким образом сайты должны использовать единый код. Но сообщение должно различаться для каждого сайта. Используя объекты Site, мы можем абстрагировать ваше уведомление так, что оно будет использовать атрибуты объекта name (т.е., LJWorld.com) и domain (т.е., www.ljworld.com). Среда управления сайтами предоставляет место для хранения атрибутов name и domain для каждого сайта вашего проекта Django и это означает, что вы можете повторно использовать эти значения в общем виде. Среда управления сайтами больше походит на ряд удобств, чем на полноценную среду. Всё основано на двух базовых концепциях:
То, как будут использоваться эти две концепции, полностью зависит от вас, но Django автоматически использует их в ряде случаев. Для того, чтобы установить приложение среды управления сайтами, выполните следующие шаги:
Следующие секции описывают различные варианты использования среды управления сайтами. Для повторного использования данных на множестве сайтов, как было описано в «Сценарий 1: Использование данных на множестве сайтов», следует создать поле ManyToManyField в модели Site, например: from django.db import models
from django.contrib.sites.models import Site
class Article(models.Model):
headline = models.CharField(max_length=200)
# ...
sites = models.ManyToManyField(Site)
Эта инфраструктура необходима вам для ассоциирования статей со множеством сайтов в вашей базе данных. Используя это, вы можете использовать один и тот же код функции представления для множества сайтов. Продолжая работу с примером модели Article, так может выглядеть код представления article_detail: from django.conf import settings
def article_detail(request, article_id):
try:
a = Article.objects.get(id=article_id, sites__id=settings.SITE_ID)
except Article.DoesNotExist:
raise Http404
# ...
Эта функция представления может быть использована повторно, потому что она динамически проверяет сайт для статьи, учитывая значения параметра SITE_ID. Например, предположим что SITE_ID для LJWorld.com имеет значение 1, а для Lawrence.com — значение 2. Если данное представление будет вызвано с использованием конфигурационного файла от LJWorld.com, то выборка статей будет ограничена теми записями, у которых в списке сайтов есть LJWorld.com. Аналогично, вы можете ассоциировать модель к Site как многие-к-одному с помощью ForeignKey. Например, если отображение статьи разрешено только для одного сайта, вы можете использовать следующую модель: from django.db import models
from django.contrib.sites.models import Site
class Article(models.Model):
headline = models.CharField(max_length=200)
# ...
site = models.ForeignKey(Site)
Такой подход имеет те же преимущества, аналогичные описанным в секции «Фильтры разметки». На низком уровне, вы можете использовать среду управления сайтами в ваших представлениях для выполнения определённых действия, основываясь на текущем сайте, например: from django.conf import settings
def my_view(request):
if settings.SITE_ID == 3:
# Делаем что-то.
else:
# Делаем что-то другое.
Конечно, руки бы оторвать за такой код с жёстким определением идентификаторов. Более явным способом выполнения тех же действий является проверка домена текущего сайта: from django.conf import settings
from django.contrib.sites.models import Site
def my_view(request):
current_site = Site.objects.get(id=settings.SITE_ID)
if current_site.domain == 'foo.com':
# Делаем что-то.
else:
# Делаем что-то другое.
Идея получения объекта Site для определения
значения параметра конфигурации SITE_ID
довольно стандартна, поэтому менеджер модели
Site (Site.objects) имеет
метод from django.contrib.sites.models import Site
def my_view(request):
current_site = Site.objects.get_current()
if current_site.domain == 'foo.com':
# Делаем что-то.
else:
# Делаем что-то другое.
ЗамечаниеВ последнем примере нет необходимости импортирования django.conf.settings.
При использовании методики «Не повторяйся» название вашего сайта и его доменное имя, как было показано в секции «Сценарий 2: Хранение информации о сайте в одном месте», являются всего лишь ссылками на атрибуты name и domain объекта Site. Например: from django.contrib.sites.models import Site
from django.core.mail import send_mail
def register_for_newsletter(request):
# Check form values, etc., and subscribe the user.
# ...
current_site = Site.objects.get_current()
send_mail('Thanks for subscribing to %s alerts' % current_site.name,
'Thanks for your subscription. We appreciate it.\n\n-The %s team.' % current_site.name,
'editor@%s' % current_site.domain,
[user_email])
# ...
Продолжая наш пример с LJWorld.com и Lawrence.com, на последнем сообщение имеет заголовок «Thanks for subscribing to lawrence.com alerts.» На LJWorld.com, соответственно, такой — «Thanks for subscribing to LJWorld.com alerts.» Аналогичное поведение применяется и для тела сообщения. Более гибким (но и более сложным) способом реализации такого поведения будет использование шаблонной системы Django. Предположим, что сайты LJWorld.com и Lawrence.com хранят свои шаблоны в разных каталогах (TEMPLATE_DIRS), тогда переложим ответственность на шаблонную систему: from django.core.mail import send_mail
from django.template import loader, Context
def register_for_newsletter(request):
# Check form values, etc., and subscribe the user.
# ...
subject = loader.get_template('alerts/subject.txt').render(Context({}))
message = loader.get_template('alerts/message.txt').render(Context({}))
send_mail(subject, message, 'do-not-reply@example.com', [user_email])
# ...
В данном случае вам потребуется создать шаблоны
Хорошей идеей будет максимально возможное развитие объекта Site, чтобы удалить ненужную сложность и избыточность.
Метод >>> from django.contrib.sites.models import Site >>> obj = MyModel.objects.get(id=3) >>> obj.get_absolute_url() '/mymodel/objects/3/' >>> Site.objects.get_current().domain 'example.com' >>> 'http://%s%s' % (Site.objects.get_current().domain, obj.get_absolute_url()) 'http://example.com/mymodel/objects/3/'
Если объект Site играет ключевую роль в вашем приложении, рассмотрите использование CurrentSiteManager в ваших моделях. Это менеджер модели, описанный в приложении «Справочник определений модели», который автоматически обрабатывает свои запросы так, чтобы они включали только объекты ассоциированные с текущим сайтом. Для использование CurrentSiteManager его следует явно подключить в модель. Например: from django.db import models
from django.contrib.sites.models import Site
from django.contrib.sites.managers import CurrentSiteManager
class Photo(models.Model):
photo = models.FileField(upload_to='/home/photos')
photographer_name = models.CharField(max_length=100)
pub_date = models.DateField()
site = models.ForeignKey(Site)
objects = models.Manager()
on_site = CurrentSiteManager()
При использовании этой модели, вызов Photo.objects.all() возвратит все объекты Photo из базы данных, а вызов Photo.on_site.all() — только те объекты Photo, которые относятся к текущему сайту (это определяется с помощью параметра SITE_ID). Другими словами, эти два оператора эквивалентны: Photo.objects.filter(site=settings.SITE_ID) Photo.on_site.all()
Как же CurrentSiteManager определяет какое поле объекта Photo относится к Site? По умолчанию он смотрит на поле с именем site. Если ваша модель имеет поля ForeignKey или ManyToManyField с именами отличными от site, вам потребуется явно передать имя в виде параметра в CurrentSiteManager. Нижеприведённая модель, у которой такое поле называется publish_on, демонстрирует такой случай: from django.db import models
from django.contrib.sites.models import Site
from django.contrib.sites.managers import CurrentSiteManager
class Photo(models.Model):
photo = models.FileField(upload_to='/home/photos')
photographer_name = models.CharField(max_length=100)
pub_date = models.DateField()
publish_on = models.ForeignKey(Site)
objects = models.Manager()
on_site = CurrentSiteManager('publish_on')
Если вы попытаетесь использовать CurrentSiteManager, передав имя несуществующего поля, Django вызовет исключение ValueError. ЗамечаниеВероятно вы пожелаете иметь обычный (не привязанный к сайтам) Manager для ваших моделей, даже если вы используете CurrentSiteManager. Как описано в приложении «Справочник определений модели», если вы определите менеджер вручную, тогда Django не будет создавать менеджер автоматически objects = models.Manager(). Также определённые части Django, а именно интерфейс администратора и базовые представления, используют тот менеджер, который был определён первым в модели. Таким образом, если потребуется, чтобы ваш сайт администратора имел доступ ко всем объектам (а не только к тем, которые относятся к сайту), следует поместить objects = models.Manager() в модели до определения CurrentSiteManager.
Несмотря на то, что использование среды управления сайтами необязательно, это настоятельно рекомендуется делать, потому что Django пользуется некоторыми преимуществами среды. Даже если Django используется для управления единственным сайтом, вы должны потратить несколько секунд на создание объекта Site с правильными значениями атрибутов name и domain, а затем указать на этот объект с помощью параметра SITE_ID. Опишем, как Django использует среду управления сайтами:
|
Увидели ошибку?
Выделите её мышкой и нажмите
-
Обработано:
1049
49
130
71
Версия книги
1.0
2.0
Версия 2.0 в процессе перевода!
Мой луч
Многообразие света
Полезное
Актуальные вакансии,
Python работа
для python-разработчиков.
Скачать в формате
CHM от 2 сентябряЗаказать PDF файл можно через почту, чат, джаббер. Всего 2WMZ. Содержимое точно соответствует содержимому сайта. Чем чаще заказываете — тем больше перевожу. Русская группа
Ускорить процесс перевода!
R130494980980
Z425285133788 E112528079659 U327380922061 Книга помогла реализовать:
|
| © 2008-2009 Ruslan Popov @ gmail.com | Powered by Django 1.1 beta 1 SVN-11114 |