Пользовательский обход и шаблоны страниц

Используя отличную запись в блоге Мариуса Гедминаса, я создал специальный каталог для папки на моем сайте.

Это позволяет мне показать: http://foo.com/folder/random_id

Вместо: http://foo.com/folder/object.html?id=random_id

Конфигурационная сторона работает отлично, я могу поймать random_ids и искать в моих сообщениях правильное, готовое к отображению.

Моя проблема в том, что я не уверен, как затем отобразить данные через мои обычные шаблоны страниц - в точке TODO в его оригинальном коде;)

if name == 'mycalendar':
            mycalendar = ... # TODO: do something to get the appropriate object
            return mycalendar

Обычно я бы использовал что-то похожее на:

class Test(BrowserPage):

    template = ViewPageTemplateFile('atest.pt')

    def __call__(self):
        return self.template()

Но я не могу понять, как сделать это правильно в контексте пользовательского обхода.


ОБНОВЛЕНИЕ: Чтобы было ясно, я хочу избегать добавления чего-либо еще в URL (No: http://foo.com/folder/random_id/read).

Мне не нужно, чтобы представление было доступно через любой другой адрес (Нет: http://foo.com/folder/read)

ZCML для представления, которое я хотел бы использовать:

<browser:page
  for="foo.interfaces.IFooFolderContainer"
  name="read"
  template="read.pt"
  permission="zope.ManageContent"
/>

Я предполагаю (на дальнейшие советы), что-то вроде:

return getMultiAdapter((mycalendar, self.request), IPageTemplate, name=u'read')

Или даже представление по умолчанию для типа объекта (в данном случае - dict), которое возвращается:

<browser:page
  for="dict"
  name="read"
  template="read.pt"
  permission="zope.ManageContent"
/>

3 ответа

Решение

Было бы легче ответить на ваш вопрос, если бы вы показали, что делает ваш пользовательский traverser.

По сути, вы хотите что-то вроде этого:

def publishTraverse(self, request, name):
    if name in self.context:
        return MyMessageView(self.context[name], request)

    # fall back to views such as index.html
    view = queryMultiAdapter((self.context, request), name=name)
    if view is not None:
        return view

    # give up and return a 404 Not Found error page
    raise NotFound(self.context, name, request)

где MyMessageView может быть чем-то простым

class MyMessageView(BrowserPage):
    __call__ = ViewPageTemplateFile('read.pt')

Отказ от ответственности: я не уверен, что представление, которое вы непосредственно создаете, будет защищено оболочкой безопасности; убедитесь, что ваши функциональные тесты гарантируют, что анонимные пользователи не смогут просматривать сообщения, если вы этого хотите.

Если в результате вы получите нужный объект с вашим пользовательским traverser, вы можете просто добавить имя шаблона и пользовательский "контекст" в этом шаблоне. Так http://foo.com/folder/random_id/my_template и в шаблоне делай нормально <h1 tal:content="context/title" /> вещи.

IIUC, то, что вы хотите, это сделать представление "чтение", когда кто-то запрашивает / folder / random_id. Если это так, все, что вам нужно сделать, это заставить свой обход вернуть объект (IFolderContent, возможно), представляющий random_id, и указать страницу просмотра в качестве defaultView для IFolderContent.

Требуется defaultView, потому что в вашем URL не указан вид для объекта random_id.

Другие вопросы по тегам