Размер: 15358
Комментарий:
|
Размер: 19875
Комментарий:
|
Удаления помечены так. | Добавления помечены так. |
Строка 329: | Строка 329: |
== Добавление комментариев == {{{#!wiki warning Эта глава не завершена }}} В этом разделе вы создадите объекты комментариев, которые могут быть добавлены к заявкам. В качестве первого шага вам необходимо определить интерфейс комментария. Добавьте определение интерфейса в ''src/tc/collector/interfaces.py'': {{{#!highlight python from zope.interface import Interface class IComment(Interface): """Comment for Ticket""" body = Text( title=u"Additional Comment", description=u"Body of the Comment.", default=u"", required=True) class ICommentContained(IContained): """Interface that specifies the type of objects that can contain comments. A comment can only contain in a ticket.""" __parent__ = Field( constraint = ContainerTypesConstraint(ITicket)) }}} Для реализации комментария вы можете создать файл ''src/tc/collector/comment.py'': {{{#!highlight python from zope.interface import implements from tc.collector.interfaces import IComment from tc.collector.interfaces import ICommentContained from zope.container.contained import Contained class Comment(Contained): implements(IComment, ICommentContained) body = u"" }}} После этого зарегистрируйте интерфейс и класс, для этого обновите файл ''src/tc/collector/configure.zcml'': {{{#!highlight xml <interface interface="tc.collector.interfaces.IComment" type="zope.app.content.interfaces.IContentType" /> <class class="tc.collector.comment.Comment"> <implements interface="zope.annotation.interfaces.IAttributeAnnotatable" /> <require permission="zope.Public" interface="tc.collector.interfaces.IComment" /> <require permission="zope.Public" set_schema="tc.collector.interfaces.IComment" /> </class> }}} Вам также следует добавить '''!ItemTypePrecondition''' к '''ITicket'''. Откройте ''src/tc/collector/interfaces.py'' и обновите определение интерфейса: {{{#!highlight python class ITicket(IContainer): """Ticket - the ticket content component""" number = TextLine( title=u"Number", description=u"Ticket number", default=u"", required=True) summary = Text( title=u"Summary", description=u"Ticket summary", default=u"", required=True) def __setitem__(name, object): """Add an ICollector object.""" __setitem__.precondition = ItemTypePrecondition(IComment) }}} Вы можете обновить файл с шаблоном ''src/tc/collector/ticketmain.pt'', добавив туда новое содержимое: {{{#!highlight xml <html> <head> <title>Welcome to ticket collector!</title> </head> <body> You are looking at ticket number: <b tal:content="context/number">number</b> <h3>Summary</h3> <p tal:content="context/summary">Summary goes here</p> <a href="@@add_comment">Add Comment</a> </body> </html> }}} Вы можете создать форму добавления (!AddForm) как показано ниже. Откройте файл ''src/tc/collector/views.py'' и добавьте в него '''!AddComment''', как показано ниже: {{{#!highlight python from zope.container.interfaces import INameChooser from tc.collector.interfaces import IComment from tc.collector.comment import Comment class AddComment(form.AddForm): form_fields = form.Fields(IComment) def createAndAdd(self, data): body = data['body'] comment = Comment() comment.body = body namechooser = INameChooser(self.context) number = namechooser.chooseName('c', comment) self.context[number] = comment self.request.response.redirect('.') }}} Вы можете зарегистрировать вид в файле ''src/tc/collector/configure.zcml'': {{{#!highlight xml <browser:page for="tc.collector.interfaces.ITicket" name="add_comment" permission="zope.Public" class="tc.collector.views.AddComment" /> }}} |
Учебник - часть 2
Содержание
Введение
Это вторая часть учебника. В первой части вы узначли о структуре папок проекта, настройке Buildout, компонентах содержимого, и использовании библиотеки форм. Компоненты содержимого - объекты с видимым для пользователя видом. Вид может быть браузерным (HTML/JS/CSS), JSON, XMLRPC или любым другим. Чтобы обяснить идею контент компонентов, проект, который был начат в первой части учебника, будет расширен путем добавления новых функций. По сути объект коллектор, который был создан в последнем разделе - контент компонент. В этом разделе, вы создадите и другие контент объекты, такие как заявки и комментарии. Также следует упомянуть, что каждый контент компонент, включая контейнеры, имеет хорошо определенные интерфейсы.
Этот раздел исследует контент компоненты более детально. После окончания раздела, вы будете уметь:
- Определять схему контент компонентов
- Создавать контейнеры
- Использовать ZCML для настройки компонентов
Перед продолжением, вот обзор того, что рассматривается:
Добавление заявок – В этой части вы создадите объект заявки. Мы обеспечим подробный обзор создания контент объектов и покажем их использование на простом примере.
Списки заявок – Дальше вы увидите, как отобразить список заявок на главной странице коллектора.
Добавление комментариев – В этой части вы научитесь добавлять контент объекты внутрь контейнеров. Объекти заявки будут превращены в контейнеры.
Списки комментариев – В этой части вы создадите объект комментарий и напишете код для отображения комментариев на странице заявки.
Примеры для этой документации могут быть загружены отсюда: http://download.zope.org/bluebream/examples/ticketcollector- 1.0.0.tar.bz2.
Исходники доступны на разных этапах соответственно разделам:
- Этап 1 : От раздела 5.2 до 5.7
- Этап 2 : Раздел 5.8
- Этап 3 : Раздел 5.9
- Этап 4 : Раздел 6.2
- Этап 5 : Раздел 6.3
- Этап 6 : Раздел 6.4 и 6.5
Добавление заявок
Определение схемы
В этом разделе вы научитесь добавлять заявки в коллектор. Для того, чтобы использовать объекты заявки, вам нужно создать интерфейс заявки. Обновите src/tc/collector/interfaces.py, добавив туда интерфейс заявки:
1 from zope.container.interfaces import IContainer
2
3 class ITicket(IContainer):
4 """Ticket - the ticket content component"""
5
6 number = TextLine(
7 title=u"Number",
8 description=u"Ticket number",
9 default=u"",
10 required=True)
11
12 summary = Text(
13 title=u"Summary",
14 description=u"Ticket summary",
15 default=u"",
16 required=True)
TextLine и Text должны быть проимпортированы, если нет - проимпортируйте их:
Будет очень хорошо, если вы установите предусловие для ограничения на типы объектов, добавляемых в коллектор. Если вы знаеие, что в объект коллектор можно добавлять только объекты заявки, добавьте предусловие для того, чтобы удостоверится, что в коллектор будут добавлять только заявки. Для того, чтобы сделать это, вам нужно добавить метод _ _setitem_ _ интерфейса ICollector в определение интерфейса ( _ _setitem_ _ - часть API интерфейсв IContainer). Ниже нужно добавить атрибут предусловия, который является экземпляром класса ItemTypePrecondition. Вы можете передать в класс temTypePrecondition интерфейсы в качестве аргументов. В примере ниже передается тольео один интерфейс - ITicket. Таким образом, только объекты заявки можно добавлять в коллектор. Вам нужно переместить определение интерфейса ITicket выше определения IContainer, поскольку ITicket используется им. Добавьте следующее определение метода в класс ICollector:
Класс ItemTypePrecondition предоставляет ограничения на типы объектов, которые могут быть добавлены внутрь контейнера. Вы также определяете объекты заявки, которые могут быть добавлены в коллектор. Для того, чтобы сделать это, вы должны создать другой интерфейс, который наследуется от zope.container.interfaces.IContained.
1 from zope.schema import Field
2 from zope.container.interfaces import IContained
3 from zope.container.constraints import ContainerTypesConstraint
4
5 class ITicketContained(IContained):
6 """Interface that specifies the type of objects that can contain
7 tickets. So a ticket can only contain in a collector."""
8
9 _ _parent_ _ = Field(
10 constraint = ContainerTypesConstraint(ICollector))
Тут вы добавили ограничение на поле _ _parent_ _, используя класс ContainerTypesConstraint.
Реализация
Дальше вам необходимо реализовать интефейс внутри src/tc/collector/ticket.py:
1 from zope.interface import implements
2 from zope.container.contained import Contained
3 from zope.container.btree import BTreeContainer
4
5 from tc.collector.interfaces import ITicket
6 from tc.collector.interfaces import ITicketContained
7
8
9 class Ticket(BTreeContainer, Contained):
10
11 implements(ITicket, ITicketContained)
12
13 number = u""
14 summary = u""
Конфигурация
Теперь необоходимо зарегистрировать интерфейс и класс. Откройте src/tc/collector/configure.zcml и добавьте следующее:
1 <interface
2 interface="tc.collector.interfaces.ITicket"
3 type="zope.app.content.interfaces.IContentType"
4 />
5
6 <class class="tc.collector.ticket.Ticket">
7 <implements
8 interface="zope.annotation.interfaces.IAttributeAnnotatable"
9 />
10 <implements
11 interface="zope.container.interfaces.IContentContainer"
12 />
13 <require
14 permission="zope.Public"
15 interface="tc.collector.interfaces.ITicket"
16 />
17 <require
18 permission="zope.Public"
19 set_schema="tc.collector.interfaces.ITicket"
20 />
21 </class>
Теперь вы можете добавить ссылку на @@add_ticket в src/tc/collector/collectormain.pt. Теперь шаблон будет выглядеть вот так:
Когда вы перейдете по ссылке, ожидается получение вида. Вы можете создать AddForm в src/tc/collector/views.py:
1 from tc.collector.interfaces import ITicket
2
3 from tc.collector.ticket import Ticket
4
5 class AddTicket(form.AddForm):
6
7 form_fields = form.Fields(ITicket)
8
9 def createAndAdd(self, data):
10 number = data['number']
11 summary = data['summary']
12 ticket = Ticket()
13 ticket.number = number
14 ticket.summary = summary
15 self.context[number] = ticket
16 self.request.response.redirect('.')
Вы можете зарегистрировать вид src/tc/collector/configure.zcml:
Вы можете добавить заявку перейдя по ссылке: http://localhost:8080/mycollector/@@add_ticket, вы можете передать номер заявки, например, '1' и добавить 'Test Summary' в качестве summary.
Вы можете проверить объект через отладочную оболочку:
1 jack@computer:/projects/ticketcollector$ ./bin/paster shell debug.ini
2 ...
3 Welcome to the interactive debug prompt.
4 The 'root' variable contains the ZODB root folder.
5 The 'app' variable contains the Debugger, 'app.publish(path)' simulates a request.
6 >>> root['mycollector']
7 <tc.collector.ticketcollector.Collector object at 0xa5fc96c>
8 >>> root['mycollector']['1']
9 <tc.collector.ticket.Ticket object at 0xa5ffecc>
Страница по умолчанию для заявки
У нас еще нет страницы по умолчанию для заявки. Если вы попытаетесь получить доступ к заявке по ссылке http://localhost:8080/mycollector/1, то получите ошибку NotFound:
URL: http://localhost:8080/mycollector/1 ... NotFound: Object: <tc.collector.ticketcollector.Ticket object at 0x8fe74ac>, name: u'@@index'
Эта ошибка возникает, потому что для интерфейса ITicket нет зарегистрированного вида с именем index. Этот раздел покажет, как создать вид по усолчанию для интерфейса ITicket.
Как вы уже видели в разделе "Первые шаги", вы можете создать простой вид и зарегистрировать его в ZCML.
Добавьте в src/tc/collector/views.py новый вид:
Вы можете создать файл с шаблоном src/tc/collector/ticketmain.pt со следующем содержанием:
Потом в src/tc/collector/configure.zcml:
Теперь вы можете перейти к http://localhost:8080/mycollector/1/@@index. По этому адресу вы должны увидеть номер заявки и ее краткое описание. Если вы просмотрите исходник страницы в HTML через браузер, он будет выглядеть следующим образом:
Создание списка заявок
Этот раздел объясняет как создать список заявок на главной странице коллектора с тем, чтобы получить возможность навигации по заявкам.
Для того, чтобы вивести список заявок на главной странице коллектора, вам необходимо можифицировать src/tc/collector/collectormain.pt:
1 <html>
2 <head>
3 <title>Welcome to ticket collector!</title>
4 </head>
5 <body>
6
7 Welcome to ticket collector! <br/> <br/>
8
9 <a href="@@add_ticket">Add Ticket</a> <br/> <br/>
10
11 <ol>
12 <li tal:repeat="ticket view/getTickets">
13 <a href=""
14 tal:attributes="href ticket/url"
15 tal:content="ticket/summary">Ticket Summary</a>
16 </li>
17 </ol>
18
19 </body>
20 </html>
Вам необходимо изменить TicketCollectorMainView, который определен в файле src/tc/collector/views.py:
1 class TicketCollectorMainView(form.DisplayForm):
2
3 form_fields = form.Fields(ICollector)
4
5 template = ViewPageTemplateFile("collectormain.pt")
6
7 def getTickets(self):
8 tickets = []
9 for ticket in self.context.values():
10 tickets.append({'url': ticket.number+"/@@index",
11 'summary': ticket.summary})
12 return tickets
Добавление комментариев
Эта глава не завершена
В этом разделе вы создадите объекты комментариев, которые могут быть добавлены к заявкам. В качестве первого шага вам необходимо определить интерфейс комментария. Добавьте определение интерфейса в src/tc/collector/interfaces.py:
1 from zope.interface import Interface
2
3 class IComment(Interface):
4 """Comment for Ticket"""
5
6 body = Text(
7 title=u"Additional Comment",
8 description=u"Body of the Comment.",
9 default=u"",
10 required=True)
11
12 class ICommentContained(IContained):
13 """Interface that specifies the type of objects that can contain
14 comments. A comment can only contain in a ticket."""
15
16 __parent__ = Field(
17 constraint = ContainerTypesConstraint(ITicket))
Для реализации комментария вы можете создать файл src/tc/collector/comment.py:
После этого зарегистрируйте интерфейс и класс, для этого обновите файл src/tc/collector/configure.zcml:
1 <interface
2 interface="tc.collector.interfaces.IComment"
3 type="zope.app.content.interfaces.IContentType"
4 />
5
6 <class class="tc.collector.comment.Comment">
7 <implements
8 interface="zope.annotation.interfaces.IAttributeAnnotatable"
9 />
10 <require
11 permission="zope.Public"
12 interface="tc.collector.interfaces.IComment"
13 />
14 <require
15 permission="zope.Public"
16 set_schema="tc.collector.interfaces.IComment"
17 />
18 </class>
Вам также следует добавить ItemTypePrecondition к ITicket. Откройте src/tc/collector/interfaces.py и обновите определение интерфейса:
1 class ITicket(IContainer):
2 """Ticket - the ticket content component"""
3
4 number = TextLine(
5 title=u"Number",
6 description=u"Ticket number",
7 default=u"",
8 required=True)
9
10 summary = Text(
11 title=u"Summary",
12 description=u"Ticket summary",
13 default=u"",
14 required=True)
15
16 def __setitem__(name, object):
17 """Add an ICollector object."""
18
19 __setitem__.precondition = ItemTypePrecondition(IComment)
Вы можете обновить файл с шаблоном src/tc/collector/ticketmain.pt, добавив туда новое содержимое:
1 <html>
2 <head>
3 <title>Welcome to ticket collector!</title>
4 </head>
5 <body>
6
7 You are looking at ticket number:
8 <b tal:content="context/number">number</b>
9
10 <h3>Summary</h3>
11
12 <p tal:content="context/summary">Summary goes here</p>
13
14 <a href="@@add_comment">Add Comment</a>
15
16 </body>
17 </html>
Вы можете создать форму добавления (AddForm) как показано ниже. Откройте файл src/tc/collector/views.py и добавьте в него AddComment, как показано ниже:
1 from zope.container.interfaces import INameChooser
2 from tc.collector.interfaces import IComment
3 from tc.collector.comment import Comment
4
5 class AddComment(form.AddForm):
6
7 form_fields = form.Fields(IComment)
8
9 def createAndAdd(self, data):
10 body = data['body']
11 comment = Comment()
12 comment.body = body
13 namechooser = INameChooser(self.context)
14 number = namechooser.chooseName('c', comment)
15 self.context[number] = comment
16 self.request.response.redirect('.')
Вы можете зарегистрировать вид в файле src/tc/collector/configure.zcml:
Перевод: Ростислав Дзинько
Документ находится в стадии перевода...