Найти - Пользователи
Полная версия: можно ли из ZMI доступиться ко вложенным методам подчиненного класса.
Начало » Zope/Plone/Bluebream » можно ли из ZMI доступиться ко вложенным методам подчиненного класса.
1 2 3
astoon
misha111, просьба: удалите пожалуйста ссылку на рапидшару - ее на приличном форуме не место.
astoon
Извиняюсь что лень было читать все до конца, но посмотрев по диагонали подметил пока только следущее.

1) zcml-директиву content я бы не стал применять в новых проектах - т.к. она года 3 уже deprecated. В случае перноса проекта на более новые пакеты - этой директивы уже давно нет ( справка )

2) ZPT-Page не равносильны tal-шаблонам. Т.е. zptpage- это ведь персистентный объект со своим контекстом. Отсюда и надо плясать. Если он вставлен в контейнер, то последний будет для него __parent__'ом.

Если я понял, поправьте. Решение всегда должно быть.

PS. Если что, у меня есть альтернативное решение для случаев, когда нужны редактируемые куски страниц, но не просто html, а с динамикой. Называется ice.template и лежит в сырном магазине.
misha111
astoon
спасибо astoon за наставления, исправил на форуме и в п. 1).

По поводу п. 2) понял через слово :-), с зоупом по работе столкнулся совсем недавно. Проблема которая была ранее - решилась, из zpt страниц получилось вызывать методы вложенных объектов - Помогла настройка контент объектов, даже когда они во вложеных папках - подключением через корневой zcml. Вроде б часть переделываемого проекта заработала, но тут столкнулся уже с третьей бедой, когда решение первым способом не помогает.

Теперь обратная ситуация, когда из вложенных объектов нужно вызвать методы родительского объекта. Сам объект родительского придумал передавать как необязательный параметр через init вложенных объектов . Из шаблонов попробовал, вроде опять таки всё работает.

При продолжении выбранного способа решения задачи, полявилась необходимость вызывать методы даже класса1 из zpt страниц в виде
self.класс1.метод1
где класс1 является полем самого себя и появляется вот так self.класс1 = self
опять пишет forbidden attribute на self.класс1.метод1, хотя опять таки из шаблонов вызывается.
Да, согласен с вами, что zpt страници - не равносильны тал шаблонам, иначе оно б одинаково всё вызывалось, и судя по вашим словам - отдельный объект. Ну и похоже на то, что методы вызвавшего класса доступны через view.метод1, например. Значит получается, zpt страница является дочерним объектом вызвывшего класса, если она не вложена в контейнеры. Но непонятно, почему self.класс1.метод1 не вызывается. хорошо, он является вложенным для самого себя, но права то на доступ к его методам открыты, равносильно как и у других вложенных объектов.
Такая накрученность не потому, что я любитель накрутить, просто пытаюсь переделать проект таким образом, возможно, не весьма удачным.
regall
misha111
Теперь обратная ситуация, когда из вложенных объектов нужно вызвать методы родительского объекта.
Вы это делаете через
класс2.__parent__.метод_класса1
?
misha111
Такая накрученность не потому, что я любитель накрутить, просто пытаюсь переделать проект таким образом, возможно, не весьма удачным.
Наверное, не весьма удачным, по крайней мере складывается такое впечатление, лично у меня за 2 года плотной работы с Zope3 таких проблем не возникало, может стоит пересмотреть архитектуру, или хотя бы привести концептуально то, что есть у вас, а тут уж помогут =) ?
misha111
ну идея проста - был один проект, у которого был класс 1 и много методов. Теперь он разросся, и проект был разбит на класс1..класс4
причём класс1 главный, и содержит методы, которые вызываются из остальных классов. Причём в zcml некоторые страници описаны под класс1, некоторые под класс2, то есть первым не обязательно должен вызываться класс1 Я попробовал, вроде б можно создавать динамические объекты и вызывать их методы, но вот теперь дошёл до zpt страниц, чтоб закончить разбивку и запустить проект - получилось только первая страница, когда создаются объект класса1 и какого нибудь вложенного класса, например класса2. А вот когда пошли вариации - когда первый например создаётся класс2, и он создаёт объект класса1 для вызова базовых методов - чот не сильно получается, но возможно я сам напутал не так создавая - но даже при этом становится похоже, что если объект класса является вложенным сам в себя - не получается обратиться к его же методам, даже если они открыты в zcml, поетому пытаюсь разбираться на более простых примерах, возможно, ещё что то открыть или описать надо. Но вроде б на другом форуме сказали что видимостью методов управляют только permission …. attribute….. . Я вообще сторонник сделать по другому, когда объекты не вложенными будут друг в друга, а как то описанные и созданные через zcml, если это возможно, листая книгу я нигде похожего не нашёл. Либо может сделать класс0, например, у которого будут вложенные классы - все остальные класс1..класс4, может тогда не будет проблем при обращении подчинённых к родительскому, ведь все будут подчинённые. Но я больше склоняюсь к глобальным объектам, описанным через zcml, но такого наверно не бывает, ведь объекты классов создаются, насколько я понял именно в момент обращения к какой либо странице.
И естественно во всём этом управляют zpt страници, например есть страница common, которая может быть дочерним объектом класс1, и тогда всё хорошо. Но когда первый был вызван класс2, и common является дочерним объектом класса2 - начинаются проблемы. Потому я и придумал даже к классу 1 обращаться как ко вложенному в самого себя, чтоб описания шаблонов были одинаковые, а родительские классы разные.
Тогда кто бы ни был родителем, всегда будет view.класс1.метод1
От такое накрученное я выдумал, если у кого нибудь конечно есть более проcтая идея - буду чрезвычайно рад выслушать. Потому что моя похоже начинает заходить в тупик, и единственнім способом её продолжить - вывести всё из zpt в шаблоны на диске где нет никаких ограничений по вызовам вложенных объектов, либо как то перегруппировать подчинённость, ну или ещё что нибудь выдумать, до чего я пока не додумался :-)
regall
misha111
создаются, насколько я понял именно в момент обращения к какой либо странице.
Немного не так. Класс есть класс, объект класса создается в момент, когда его добавили в ZODB через ZMI. Объекты в ZODB сохраняются как pickle (почитать про пакет cPickle) и просто “поднимаются” оттуда, если в виде явно, например с помощью getUtility, или неявно, если объект является контекстом вида, присутствует (технически вид - это мультиадаптер: context, request адаптируются к XHTML коду); или если создана собственная директива, которая создает глобальный объект класса, который создается при выполнении директивы и остается в памяти все время, пока живет сервер.
Таким образом, при обращении к странице объект просто вытягивается из базы.
misha111
И естественно во всём этом управляют zpt страницы
Тоже нет. ZPT страницы такие же персистентные объекты базы данных, как и например объекты класса1, на которые можно создать виды (например директивой <page … />) и которые в этом случае являются контекстом, в случае если <page .. /> регистрируется на конкретный интерфейс, то это уже не ZPT, а вид объекта.
misha111
От такое накрученное я выдумал, если у кого нибудь конечно есть более простое решение - буду чрезвычайно рад выслушать.
Вообще ничего не понял, какая задача, перечитав пост три раза, можешь описать задачу, которая стоит или, если это коммерческая тайна, хотя бы описать как то доходчивее, что ли … =)
misha111
regall
создаются, насколько я понял именно в момент обращения к какой либо странице.
да да, я заметил неправильность в формулировке, исправил. Классы, к счастью, описаны статически, динамические только объекты статических классов.

подумаю и сформулирую вопрос, чтоб не отяжеляя ньюансами самого проекта изъясниться, что же мне надо :-) и заодно выясню у руководства что можно говорить в обсуждениях.

а если обобщить текущую проблему аналогично первым постам, то тупик в следующем:
есть класс1 и у него метод1.
сделал полем класса1 опять таки класс1, определил его вот так self.класс1 = self
в настройках контента объекта сдела видимым метод1
<class class = “.class1.Class1”>
………………………………
<require permission = “zope.Public” attributes = “method1” />
</class>

и из zpt страници попробовал вызвать view.класс1.метод1() - пишет что запрешённый аттрибут метод1. из шаблона аналогичный способ срабатывает правильно, без ошибок, на основании чего я делаю вывод что такой вызов вооще возможен.
(возможно покажется странным, но такое действительно нужно из-за того, что одну и ту же zpt страницу “вызывают” объекты разных классов, и не всегда к методам объекта класса1 можно обратиться view.метод1)
хотя если вложенный - например класс2, созданный self.класс2 = класс2(…), то вызов view.класс2.метод2() нормально работает из zpt страниц. настройка контента объекта для объекта класс2 выполнена аналогично настройке объекта класса1
По суте проблема аналогично той, которая описана в первом посте, но почему-то так же не решается :-(
Если уж не получится продолжит в выбранном мной направлении, прийдётся перекраивать архитектуру проекта.
misha111
решили перестроить архитектуру приложения чтоб не долбаться с публекуемыми объектами, вложенными сами в себя, из за чего понадобились
назначение permission динамически.

То есть идея проста - есть публикуемуй класс, в него вложен не публекуемый,
у которого есть метод. Естественно у не публикуемого класса2 нет
configure.zcml, где можно описать
<require permission = “zope.Public” attributes = “method2” />
И нужно из zpt страници вызвать метод2 вложенного непубликуемого
класса2.

view.class2.method2

в __init__ class1 описано создание class2:
self.class2 = class2()

ну и у class2 естественно описан method2

если не назначать прав, то пишет forbidden attribute на method2
когда были все публикуемые - решилось через описание контента объекта через zcml
regall
misha111
и из zpt страници попробовал вызвать view.класс1.метод1() - пишет что запрешённый аттрибут метод1
Ну, тут интересует, как в виде для zpt страницы получен “класс1”.
Я думаю проблема может решиться добавлением в класс вида следующего кода:
from zope.security.proxy import removeSecurityProxy
класс1 = removeSecurityProxy(класс1)
или, если не поможет:
from zope.proxy import removeAllProxies
класс1 = removeAllProxies(класс1)
misha111
если не назначать прав, то пишет forbidden attribute на method2
Естественно, это обусловлено политикой безопасности фреймворка

P.S. Насколько я понял, вам просто важно связать два контент-объекта. Вложение объектов - это не самый хороший подход. Лучше их связывать или через персистентные __weakref__'ы или по id, например добавив в схему класс2 поле
parent_publication  = Choice(vocabulary = class1_publications)
Для этого нужно получить все публикации типа class1 и сформировать из них словарь:
from zope.schema.vocabulary import SimpleVocabulary, SimpleTerm
from zope.app.intid.interfaces import IIntIds
def class1_publications():
intid = getUtility(interface = IIntIds)
.... # получаем все публикации класс1 в переменную all_pubs
return SimpleVocabulary(Simpleterm(id = intid.getId(pub), title = pub.title, value = intid.getId(pub)) for pub in all_pubs)
Тут также используется утилита назначения уникальных идентификаторов объектам в ZODB - IIntIds, ее можно добавить (желательно в /++etc++site/ вашего сайта) через ZMI (“Утилита генерации уникальных идентификаторов”), она также будет нужна если вы хоите организовать поисковые индексы через утилиту ICatalog.
Таким образом при создании публикации класс2 вы сможете привязать ее к класс1 (в форме построится выпадающий список с ‘title’ из созданного vocabulary).

P.P.S. или, наоборот, добавить такое поле в класс1, чтобы привязывать к нему класс2 (в данном случае это будет даже целесообразнее)
misha111
regall
Естественно, это обусловлено политикой безопасности фреймворка

P.S. Насколько я понял, вам просто важно связать два контент-объекта. Вложение объектов - это не самый хороший подход. Лучше их связывать или через персистентные __weakref__'ы или по id, например добавив в схему класс2 поле
Да, так и было, вкладывал объекты друг в друга. Решили что этим заниматься не нужно, и весь функционал, из за которого делалось вложение повыносил из публикуемых классов, и собрал в не публикуемые, которые подключаются к публикуемым и всё хорошо бы, но при вынесении методов обнаружились такие методы, которые используются в как минимум двух публикуемых классах, и вызываются из zpt страниц. Я решил собрать такие методы в один класс и подключать при необходимости. Но опять же проблема
regall
если не назначать прав, то пишет forbidden attribute на method2
Описанный вами способ про персистентные __weakref__'ы или по id, прочитал. Он мне показал сложноватым, и ещё неизвестно какие подводные камни могут появиться, буду это пробовать если вообще ничего по проще не получится.

Может как то при создании вложенного объекта ему можно и права назначить как в zcml?
<require permission = “zope.Public” attributes = “method2” /> - что нибудь такого плана помогло бы, как нельзя лучше.

пробовал self.class2 = removeSecurityProxy(класс2) и self.class2 = removeSecurityProxy(класс2) не помогло.

Уж на крайний случай, если такого не бывает, то тогда прийдётся классу делать configure.zcml и делать настройку контента объекта, что уж очень не хотелось бы, хотелось бы это динамически делать. А когда появится больше времени - то попробую по вашей рекомендации переделать про “персистентные __weakref__'ы”
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB