среда, 8 октября 2008 г.

Особености работы IntIds при создании объекта "сайт".

Вот решил тут перейти от теории к практике и написать небольшую CMS-ку. Написал скин использующий z3c.layer.pagelett. Написал объект "Сайт". Сделал форму для его добавления используя z3c.forms. Естественно любой сайт должен содержать стандартный набор утилит, которые надо в нём создать и зарегистрировать. И первая из этих утилит это генератор уникальных числовых идентификаторов для объектов сайта - IntIds. Эта утилита обрабатывает событие добавления объекта в контейнер, тем самым регистрируя добавленный объект. Вот тут я и натолкнулся на мистику.

Вот не полный код добавления и иницализации объекта "Сайт".


def add(self, site):
self._name = site.title.lower().strip()
self.context[self._name] = site
notify(ObjectAddedEvent(site, self.context, self._name))
site = self.context[self._name]
# -- Установка и регистрация необходимых утилит --
# Генератор уникальных номеров объектов
sm = site.getSiteManager()
sm['IntIds'] = IntIds()
sm.registerUtility(sm['IntIds'], provided=IIntIds)
sm['IntIds'].register(site)
notify(ObjectCreatedEvent(sm['IntIds']))
# Хранилище сессий в памяти
sm['RAMSessionDataContainer'] = RAMSessionDataContainer()
rs = sm['RAMSessionDataContainer']
sm.registerUtility(rs, provided=ISessionDataContainer, name='RamSession')
notify(ObjectCreatedEvent(rs))
...
Как видно из кода утилита IntIds добавляется и регистируется самой первой, затем добавляется утилита хранения сессий в памяти RAMSessionDataContainer. Теоритически этот объект должен быть автоматически зарегистрирован утилитой IntIds, но это оказалось не так. Если после создания сайта посмотреть через стандартный скин Zope3 информацию о количестве зарегистрированных в IntIds объектов, то окажется, что он только один - это сам сайт, который регистрируется в IntIds непосредственым вызовом метода register.
Ручное добавление объектов в созданый сайт обрабатывается утилитой IntIds нормально.

Я обратился за помощью в Russian Zope3 group, где и помогли мне с решением этой проблеммы. Вот цитата Андрея Орлова:

Про добавлении intids мистика, к сожалению, есть. И даже ks.installtool от нее не спасает, правда, в документации на него решение описано.

Итак, про мистику читаем тут: http://eaglenest.ru/mirror/doc.orlov/Zope3/SiteManager/SiteManager.txt
Как видите, решение на самом деле очень простое, сразу после создания sitemanger надо зарегистрировать его также, как это делает траверсер. До этих пор в ваш код не вызывает ваш SiteManager, и, соответственно, IntIds.
Об этом можно прочитать тут: https://code.keysolutions.ru/svn/ks.installtool/trunk/src/ks/installt..., приложение 1.

Последовав совету я добави необходимый код в конструктор объекта "Сайт" и всё заработало как и должно по теории.

...
from zope.app.component.hooks import setSite

class CykoozCMSSite(folder.Folder):
u''' CykoozCMS website. '''
zope.interface.implements(ICykoozCMSSite)
title = FieldProperty(ICykoozCMSSite['title'])
description = FieldProperty(ICykoozCMSSite['description'])

def __init__(self, title=None):
super(CykoozCMSSite, self).__init__()
if title is not None: self.title = title
sm = site.LocalSiteManager(self)
self.setSiteManager(sm)
sm.registerUtility(self, provided=ICykoozCMSSite)
# Следующей строчки не хватало для работы IntIds
setSite(self)

Комментариев нет:

Отправить комментарий