пятница, 11 апреля 2008 г.

Функциональный виджет.


Функциональный виджет.

Допустим, есть необходимость при редактировании атрибута объекта выбирать,
сохранять его значение или нет.
Например может появится такая необходимость при использовании объекта с атрибутом Bytes.



Интерфейс:

1.from zope.interface import Interface
2.from zope.schema import TextLine, Bytes
3.
4.class IMark(Interface):
5.
6. datax = Bytes(
7. title=u"Check Data",
8. description=u"Des",
9. required=True)
10.
11. dataxx = TextLine(
12. title=u"Data",
13. description=u"Des",
14.required=False)

6-9 устанавливаем тип атрибута Bytes и в строке 9 указываем что он обязательный для заполнения.

Реализация:

1.from zope.interface import implements
2.from zope.app.container.contained import Contained
3.
4.from boom.interfaces import IMark
5.from persistent import Persistent
6.
7.class Mark(Persistent):
8. implements(IMark)
9.
10. def __init__(self, datax='', dataxx=''):
11. self.datax = datax
12. self.dataxx = dataxx
13.
14.from zope.component.factory import Factory
15.
16.markFactory = Factory(
17. Mark,
18. title=u"Create a new mark",
19. description = u"This factory instantiates new mark."
20. )

1012 При инициализации объекта устанавливаем атрибуты

Формы добавления и редактирования:

1.from zope.component import createObject
2.from zope.formlib.form import AddForm, Fields, applyChanges, EditForm
3.from boom.interfaces import IMark
4.from boom.widget import BoolWidget
5.from zope.formlib.namedtemplate import NamedTemplate
6.from zope.formlib.namedtemplate import NamedTemplateImplementation
7.from zope.app.pagetemplate import ViewPageTemplateFile
8.
9.class MarkAddForm(AddForm):
10.
11. form_fields = Fields(IMark)
12.
13. label = u"Add BookMarker"
14.
15. template = NamedTemplate('mark.form')
16.
17. def create(self, data):
18. mark = createObject(u'boom.mark')
19. applyChanges(mark, self.form_fields, data)
20. return mark
21.
22.class MarkEditForm(EditForm):
23.
24. form_fields = Fields(IMark)
25. form_fields['datax'].custom_widget = BoolWidget
26.
27. label = u"Edit BookMarker"
28.
29. template = NamedTemplate('mark.form')
30.
31.form_template = NamedTemplateImplementation(
32. ViewPageTemplateFile('form.pt'))

9-20 Класс добавления объекта, все поля оставляем по умолчанию
2229 Класс редактирования, для байтового поля используем собственный виджет

Виджет:

1.from zope.app.form.browser.textwidgets import FileWidget
2.from zope.app.pagetemplate.viewpagetemplatefile import ViewPageTemplateFile
3.from boom.bookmarker import Mark
4.
5.from zope.app.form.interfaces import ConversionError
6.from zope.app.i18n import ZopeMessageFactory as _
7.
8.from zope.lifecycleevent import ObjectCreatedEvent, ObjectModifiedEvent
9.import zope.event
10.
11.class BoolWidget(FileWidget):
12. __call__ = ViewPageTemplateFile('widget.pt')
13.
14. def _toFieldValue(self, input):
15.
16. delete = self.request.get(self.name+'.delete')
17.
18. if delete=='False' or input == None or input == '':
19. return self.context.context.datax
20. try:
21. seek = input.seek
22. read = input.read
23. except AttributeError, e:
24. raise ConversionError(_('Form input is not a file object'), e)
25. else:
26. seek(0)
27. data = read()
28. if data or getattr(input, 'filename', ''):
29. return data
30. else:
31. return self.context.missing_value

11 - Наследуемся от FileWidget и перекрываем 2 метода call и _toFieldValue
В строке 16 получаем значение флага.
1819 проверяем нужно ли изменять объект, если не нужно или поля не заполнены
возвращается неизмеренный атрибут.


Шаблон формы:

1.<html xmlns="http://www.w3.org/1999/xhtml"
2. xmlns:tal="http://xml.zope.org/namespaces/tal"
3. xmlns:metal="http://xml.zope.org/namespaces/metal"
4. metal:use-macro="context/@@standard_macros/view">
5.<body>
6.<div metal:fill-slot="body">
7.<form class="edit-form" enctype="multipart/form-data" method="post"
8. action="." tal:attributes="action request/URL">
9. <h1 tal:content="view/label">Edit something</h1>
10. <div class="summary" tal:condition="view/status"
11. tal:content="view/status">Status</div>
12. <div class="row" tal:repeat="widget view/widgets">
13. <div class="label">
14. <label for="field.name" title="The widget's hint"
15. tal:attributes="for widget/name; title widget/hint"
16. tal:content="widget/label">Label</label>
17. </div>
18. <div tal:condition="widget/error"
19. tal:content="structure widget/error">Error</div>
20. <div class="field">
21. <input tal:replace="structure widget" />
22. </div>
23. </div>
24. <span class="actionButtons" tal:condition="view/availableActions">
25. <input tal:repeat="action view/actions"
26. tal:replace="structure action/render"
27. />
28. </span>
29.</form>
30.</div>
31.</body>
32.</html>

Шаблон виджета:

1.<div xmlns:tal="http://xml.zope.org/namespaces/tal">
2.
3. <input type="file" id="checkbox.flag" value=''
4. tal:attributes="id string:${view/name};
5. name string:${view/name};
6. "
7. />
8.<p>
9. <input type="radio" id="checkbox.flag"
10. tal:attributes="id string:${view/name}.delete;
11. name string:${view/name}.delete"
12. value="True" /> Изменить
13.</p>
14.<p>
15. <input type="radio" id="checkbox.flag"
16. tal:attributes="id string:${view/name}.delete;
17. name string:${view/name}.delete"
18. value="False" checked /> Не изменять
19.
20.</p>
21.</div>

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