Виды.txt
2008-01-11 18:58Виды: Конечный результат запроса к Zope - вызов специального объекта - "Вида". Назначение MixIn класса - приспособить интерфейсы объекта, для которых создан данный вид, к потребностям представления через ZPT. ZPT, используемый в виде, может обращаться к следующим пространствам имен: request -- пространство имен запроса; Таким образом, при желании можно легко обойтись без MixIn'а: нужно только умело программировать zpt. ...
Виды:
Конечный результат запроса к Zope - вызов специального объекта - "Вида".
Как работает вид:
Вид - это мультиадаптер от интерфейса контекстного объекта и интерфейса запроса к интерфейсу Interface, дополнительно выделямом специаалььным именем. Каждый такой мультиадаптер уникален. Тем не менее, может существовать несколько видов под одним именем для одного интерфейса контекстного объекта, так как можно варьировать интерфейс запроса. Это позволяет создавать так называемые "скины". Скин - это множество видов, объединенных единым замыслом. Выбор скина в пространстве имен skin (++skin++) приводит к делегированию текущему запросу дополнительных интерфейсов, для которых и декларирован вид.
Таким образом, переключая интерфейсы запроса можно выбирать skin. Некоторое время назад все было чуть более сложно, но теперь все стало так.
Как устроен вид:
Вид состоит из страницы-темплейта (ZPT) и специального класса, предоставляющего атрибуты для темплейта в пространстве имен view. При декларации вида, создается новый класс, в котором декларированный класс фигурирует как MixIn.
При вызове вид (и, соответственно, MixIn), получает через функцию __init__ два аргумента: контекст и запрос. Контекст - это, фактически, тот объект для которого был вызван данный вид. Назначение MixIn класса - приспособить интерфейсы объекта, для которых создан данный вид, к потребностям представления через ZPT. Вид можно представить себе как цепочку из двух адаптеров: собственно zpt-страницы и адаптера интерфейса к этой странице. Эта комбинация используется настолько часто, что была создана специальная директива, механически собирающая эти два адаптера в единое целое, которое, собственно, и называется - вид.
ZPT, используемый в виде, может обращаться к следующим пространствам имен:
- request
- пространство имен запроса;
- context
- объект, в контексте которого вызван вид;
- view
- класс-MixIn;
Таким образом, при желании можно легко обойтись без MixIn'а: нужно только умело программировать zpt. Но это не очень хорошая практика.
Какие директивы используются для декларации видов:
Для создания видов используются три основных директивы: page, pages и view. Все они получают в качестве параметров список интерфейсов обслуживаемых объектов, класс, темплейт, имя, под которым вид будет существовать в пространстве имен видов (и, соответственно, вызываться через URL) и еще несколько менее важных параметров.
Кроме основных директив, существует ряд директив для создания специальных видов (заранее запрограммированных), это, например, addform, editform, form, containerViews и некоторые другие.
Пример:
В качестве примера приведем вид, отображающий частотную характеристику объекта quota (quotaview).

Декларация вида:
<page
name=".histogram.html"
permission="zope.ManageContent"
class=".histogram.Histogram"
template="histogram.pt"
for="quota.interfaces.IQuota"
menu="zmi_views" title="Histogram"
/>
Здесь histogram.pt - шаблон, .histogram.Histogram - специальный класс, для доступа к данным адаптируемого контекста:

Исходный код класса:
# Гистограмма длин объектов
from zope.proxy import removeAllProxies
class Histogram(object) :
def __init__(self,quota,request) :
super(Histogram,self).__init__(quota,request)
quota = removeAllProxies(quota)
self.vn = min(quota.osz.values())
self.vx = max(quota.osz.values())
self.count = len(quota.osz.values())
self.size = max(5, min( self.count / 10 + 1, 30))
self.h = [0]*self.size
self.average = 0.
size = 0.
for value in quota.osz.values() :
size += value
self.h[int((self.size-1)*(value-self.vn) / (self.vx-self.vn))] += 1
self.average = size / self.count
mx = max(self.h)
mn = min(self.h)
self.h = [ {
"count" : (x-mn)*200/(mx-mn),
"size" : y*(self.vx-self.vn)+self.vn
} for x,y in zip(self.h,range(0,len(self.h))) ]
Собственно шаблон:
<html metal:use-macro="views/standard_macros/view">
<title> Quota histogramm </title>
<body metal:fill-slot="body">
<h1> Statistica: </h1>
<p> There are some statistics computed on our quoted storage: </p>
<dl>
<dt> Object count: </dt> <db tal:content="view/count"> </db>
<dt> Size minimum: </dt> <db tal:content="view/vn"> </db>
<dt> Size maximum: </dt> <db tal:content="view/vx"> </db>
<dt> Size Average: </dt> <db tal:content="view/average"> </db>
</dl>
<h1> Histogram: </h1>
<table width="60%" height="40%" border="1" cellspacing="0" cellpadding="0">
<tr><td tal:repeat="item view/h" border="1" bgcolor="red">
<table width="100%" height="100%" border="0" cellspacing="0" cellpadding="0">
<tr><td bgcolor="blue"
tal:attributes="height python:'%s' % (200-item['count'])"> </td></tr>
<tr><td bgcolor="red" align="center" valign="bottom"
tal:attributes="height python:'%s' % (item['count']+1)"
tal:content="python:'%(count)u' % item"> </td></tr>
</table>
</td></tr>
<tr border="1">
<td border="1" bgcolor="green" align="center"
tal:repeat="item view/h" tal:content="python:'%(size)u' % item">
</td>
</tr>
</table>
</body>
</html>
Заключение:
В приведенном примере не показаны многочисленные возможности, которые дает программирование на ZPT, использование макросов и библиотек макросов, взаимодейтсвие видов в рамках одного скина. Его главная цель - продемонстрировать что:
- К любому интефейсу может быть написан вид;
- Этот вид универсален - т.е. зависит только от интерфейса, а не от предоставляющей его компоненты;
- С каждым объектом может быть связано несколько видов, образующих сложную систему взаимодействия пользователя с этим объектом;
- Эта система собирается автоматически, до тех пор, пока объект предоставляет только известные системе интерфейсы.
Таким образом, программирование видов лишний раз подчеркивает главную особенность компонентной модели: здесь никогда не идет речь о специфических реализациях объектов, сдесь идет речь только о (возможно различных по структуре) компонентах, предоставляющих стандартные интерфейсы.



