work in progress: cybertools.reporter
git-svn-id: svn://svn.cy55.de/Zope3/src/cybertools/trunk@1748 fd906abe-77d9-0310-91a1-e0d9ade77398
This commit is contained in:
parent
36f0f335ce
commit
a0a52ab055
7 changed files with 170 additions and 105 deletions
|
@ -1,19 +1,54 @@
|
||||||
Quickstart Instructions
|
====================================
|
||||||
=======================
|
A Basic API for Reports and Listings
|
||||||
|
====================================
|
||||||
|
|
||||||
($Id$)
|
($Id$)
|
||||||
|
|
||||||
TO DO...
|
TO DO...
|
||||||
|
|
||||||
>>> from zope.app import zapi
|
>>> from zope import component
|
||||||
>>> from zope.app.testing import ztapi
|
|
||||||
>>> from zope.interface import directlyProvides
|
>>> from zope.interface import directlyProvides
|
||||||
|
|
||||||
A Basic API for Reports and Listings
|
|
||||||
====================================
|
Listings
|
||||||
|
========
|
||||||
|
|
||||||
|
>>> from cybertools.reporter.data import DataSource
|
||||||
|
>>> from cybertools.reporter.resultset import ResultSet
|
||||||
|
>>> from cybertools.reporter.interfaces import IResultSet
|
||||||
|
|
||||||
|
Let's start with the Person class from the cybertools.organize package - we will
|
||||||
|
then provide a listing of persons...
|
||||||
|
|
||||||
|
>>> from cybertools.organize.party import Person
|
||||||
|
|
||||||
|
>>> from datetime import date
|
||||||
|
>>> pdata = ((u'John', u'Smith', '1956-08-01'),
|
||||||
|
... (u'David', u'Waters', '1972-12-24'),
|
||||||
|
... (u'Carla', u'Myers', '1981-10-11'))
|
||||||
|
>>> persons = DataSource([Person(f, s, date(*[int(d) for d in b.split('-')]))
|
||||||
|
... for f, s, b in pdata])
|
||||||
|
|
||||||
|
>>> component.provideAdapter(ResultSet)
|
||||||
|
>>> rset = IResultSet(persons)
|
||||||
|
|
||||||
|
>>> len(list(rset.rows))
|
||||||
|
3
|
||||||
|
|
||||||
|
For the browser presentation we can also use a browser view providing
|
||||||
|
the result set with extended attributes:
|
||||||
|
|
||||||
|
>>> #rsView = component.getMultiAdapter((context, TestRequest()), IBrowserView)
|
||||||
|
|
||||||
|
The reporter package also includes facilities for sorting the rows in a
|
||||||
|
result set and splitting a result into batches.
|
||||||
|
|
||||||
|
Sorting
|
||||||
|
-------
|
||||||
|
|
||||||
|
|
||||||
Batching
|
Batching
|
||||||
--------
|
========
|
||||||
|
|
||||||
We'll use a fairly simple Iterable:
|
We'll use a fairly simple Iterable:
|
||||||
|
|
||||||
|
@ -48,43 +83,4 @@ We are now ready to use the corresponding browser view:
|
||||||
'navOnClick': "dojo.io.updateNode(...); return false;",
|
'navOnClick': "dojo.io.updateNode(...); return false;",
|
||||||
'title': 5}
|
'title': 5}
|
||||||
|
|
||||||
The real reporting stuff
|
|
||||||
------------------------
|
|
||||||
|
|
||||||
>>> from cybertools.reporter.data import DataSource
|
|
||||||
>>> from cybertools.reporter.interfaces import IResultSet
|
|
||||||
|
|
||||||
>>> from cybertools.reporter.example.interfaces import IContactsDataSource
|
|
||||||
>>> from cybertools.reporter.example.contact import Contacts
|
|
||||||
|
|
||||||
Let's start with the Person class from the example package - we will
|
|
||||||
then provide a listing of persons...
|
|
||||||
|
|
||||||
>>> from cybertools.organize.party import Person
|
|
||||||
|
|
||||||
>>> from datetime import date
|
|
||||||
>>> pdata = ((u'John', u'Smith', '1956-08-01'),
|
|
||||||
... (u'David', u'Waters', '1972-12-24'),
|
|
||||||
... (u'Carla', u'Myers', '1981-10-11'))
|
|
||||||
>>> persons = DataSource([Person(f, s, date(*[int(d) for d in b.split('-')]))
|
|
||||||
... for f, s, b in pdata])
|
|
||||||
>>> directlyProvides(persons, IContactsDataSource)
|
|
||||||
|
|
||||||
>>> ztapi.provideAdapter(IContactsDataSource, IResultSet, Contacts)
|
|
||||||
>>> rset = IResultSet(persons)
|
|
||||||
|
|
||||||
>>> len(rset)
|
|
||||||
3
|
|
||||||
|
|
||||||
For the browser presentation we can also use a browser view providing
|
|
||||||
the result set with extended attributes:
|
|
||||||
|
|
||||||
>>> #rsView = zapi.getMultiAdapter((context, TestRequest()), IBrowserView)
|
|
||||||
|
|
||||||
The reporter package also includes facilities for sorting the rows in a
|
|
||||||
result set and splitting a result into batches.
|
|
||||||
|
|
||||||
Sorting
|
|
||||||
-------
|
|
||||||
|
|
||||||
|
|
||||||
|
|
41
reporter/browser/macros.pt
Normal file
41
reporter/browser/macros.pt
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
<!-- $Id$ -->
|
||||||
|
|
||||||
|
<metal:detail define-macro="detail">
|
||||||
|
<h2 tal:content="item/title">Something</h2><br />
|
||||||
|
<table>
|
||||||
|
<tr tal:repeat="cell item/cells">
|
||||||
|
<td><span tal:content="cell/title"
|
||||||
|
i18n:translate="" />Fieldname:</td>
|
||||||
|
<td tal:content="cell/text">Value</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</metal:detail>
|
||||||
|
|
||||||
|
|
||||||
|
<metal:listing define-macro="listing"
|
||||||
|
tal:define="result item/resultSet">
|
||||||
|
<h2 tal:content="item/title">Something</h2><br />
|
||||||
|
<table class="listing">
|
||||||
|
<tr>
|
||||||
|
<th tal:repeat="field result/schema"
|
||||||
|
tal:content="field/title"
|
||||||
|
i18n:translate="">Fieldname</th>
|
||||||
|
</tr>
|
||||||
|
<tal:items repeat="row result/rows">
|
||||||
|
<tal:item define="class python: repeat['row'].odd() and 'even' or 'odd'">
|
||||||
|
<tr tal:attributes="class class">
|
||||||
|
<td valign="top"
|
||||||
|
repeat="cell row/cells">
|
||||||
|
<a href="#"
|
||||||
|
tal:omit-tag="not: cell/url"
|
||||||
|
tal:attributes="href cell/url;
|
||||||
|
title cell/urlTitle">
|
||||||
|
<span tal:replace="cell/text">Value</span>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tal:item>
|
||||||
|
</tal:items>
|
||||||
|
</table>
|
||||||
|
</metal:listing>
|
||||||
|
|
65
reporter/browser/report.py
Normal file
65
reporter/browser/report.py
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
#
|
||||||
|
# Copyright (c) 2007 Helmut Merz helmutm@cy55.de
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 2 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software
|
||||||
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
#
|
||||||
|
|
||||||
|
"""
|
||||||
|
View classes for reports.
|
||||||
|
|
||||||
|
$Id$
|
||||||
|
"""
|
||||||
|
|
||||||
|
from zope import interface, component
|
||||||
|
from zope.app.pagetemplate import ViewPageTemplateFile
|
||||||
|
from zope.cachedescriptors.property import Lazy
|
||||||
|
|
||||||
|
from loops.browser.common import BaseView
|
||||||
|
|
||||||
|
|
||||||
|
reportMacros = ViewPageTemplateFile('macros.pt')
|
||||||
|
|
||||||
|
|
||||||
|
class DetailView(BaseView):
|
||||||
|
|
||||||
|
template = reportMacros
|
||||||
|
|
||||||
|
@Lazy
|
||||||
|
def macro(self):
|
||||||
|
return self.template.macros('detail')
|
||||||
|
|
||||||
|
@Lazy
|
||||||
|
def resultSet(self):
|
||||||
|
result = ResultSet()
|
||||||
|
return result
|
||||||
|
|
||||||
|
@Lazy
|
||||||
|
def cells(self):
|
||||||
|
return self.resultSet.rows.next()
|
||||||
|
|
||||||
|
|
||||||
|
class ListingView(BaseView):
|
||||||
|
|
||||||
|
template = reportMacros
|
||||||
|
|
||||||
|
@Lazy
|
||||||
|
def macro(self):
|
||||||
|
return self.template.macros('listing')
|
||||||
|
|
||||||
|
@Lazy
|
||||||
|
def resultSet(self):
|
||||||
|
result = ResultSet()
|
||||||
|
return result
|
||||||
|
|
|
@ -1,4 +0,0 @@
|
||||||
"""
|
|
||||||
$Id$
|
|
||||||
"""
|
|
||||||
|
|
|
@ -1,31 +0,0 @@
|
||||||
#
|
|
||||||
# Copyright (c) 2006 Helmut Merz helmutm@cy55.de
|
|
||||||
#
|
|
||||||
# This program is free software; you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU General Public License as published by
|
|
||||||
# the Free Software Foundation; either version 2 of the License, or
|
|
||||||
# (at your option) any later version.
|
|
||||||
#
|
|
||||||
# This program is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License
|
|
||||||
# along with this program; if not, write to the Free Software
|
|
||||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
#
|
|
||||||
|
|
||||||
"""
|
|
||||||
Interfaces for an example for the cybertools.reporter package. This is
|
|
||||||
based on the cybertools.contact package
|
|
||||||
|
|
||||||
$Id$
|
|
||||||
"""
|
|
||||||
|
|
||||||
from zope.interface import Interface
|
|
||||||
|
|
||||||
class IContactsDataSource(Interface):
|
|
||||||
""" A data source marker interface for a collection of contacts.
|
|
||||||
"""
|
|
||||||
|
|
|
@ -36,7 +36,7 @@ class IBatch(Interface):
|
||||||
iterable = Attribute(u'The iterable this batch belongs to')
|
iterable = Attribute(u'The iterable this batch belongs to')
|
||||||
|
|
||||||
start = Attribute(u'The current start index of the batch in the parent iterable')
|
start = Attribute(u'The current start index of the batch in the parent iterable')
|
||||||
|
|
||||||
def __getitem__(idx):
|
def __getitem__(idx):
|
||||||
""" Return the item at index idx on the current page.
|
""" Return the item at index idx on the current page.
|
||||||
"""
|
"""
|
||||||
|
@ -74,38 +74,37 @@ class IResultSet(Interface):
|
||||||
(fields, cells).
|
(fields, cells).
|
||||||
"""
|
"""
|
||||||
|
|
||||||
schema = zope.schema.Iterable(title=u'Schema',
|
schema = Attribute(u'Collection of field specifications from zope.schema.')
|
||||||
description=u'Collection of field specifications based '
|
rows = Attribute(u'Sequence of row objects.')
|
||||||
'on the interfaces defined by zope.schema.')
|
|
||||||
rows = zope.schema.Iterable(title=u'Rows',
|
view = Attribute(u'The view the result set was created for.')
|
||||||
description=u'Sequence of row objects')
|
|
||||||
|
|
||||||
|
|
||||||
class IRow(Interface):
|
class IRow(Interface):
|
||||||
""" A sequence of cells containing the real data objects.
|
""" A sequence of cells containing the real data objects.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
cells = zope.schema.Dict(zope.schema.ASCIILine(),
|
cells = Attribute(u'Mapping of data elements addressed by field names.')
|
||||||
title=u'Cells',
|
|
||||||
description=u'Mapping of data elements addressed by a name '
|
value = Attribute(u'The object that is the base of this row.')
|
||||||
'that is the key to the mapping.')
|
|
||||||
|
|
||||||
resultSet = Attribute('The result set this row belongs to.')
|
resultSet = Attribute('The result set this row belongs to.')
|
||||||
|
schema = Attribute(u'The schema of the result set this row belongs to')
|
||||||
|
|
||||||
|
|
||||||
class ICell(Interface):
|
class ICell(Interface):
|
||||||
""" A single cell of a listing or table.
|
""" A single cell of a listing or table.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
text = zope.schema.Text(title=u'Text',
|
text = Attribute(u'Text to be displayed.')
|
||||||
description=u'Text to be displayed')
|
value = Attribute(u'The real object, often identical to text.')
|
||||||
value = zope.schema.Object(Interface,
|
token = Attribute(u'May be used to identify a cell within '
|
||||||
title=u'Value',
|
'the result set, e.g. in forms.')
|
||||||
description=u'The real object, often identical to text.')
|
url = Attribute(u'An optional URL for a link to place on the cell.')
|
||||||
token = zope.schema.ASCIILine(title=u'Token',
|
# string:${view/url}/.target${row/uniqueId}
|
||||||
description=u'May be used to identify a cell within'
|
urlTitle = Attribute(u'Optional title for this link.')
|
||||||
'the result set, e.g. in forms')
|
|
||||||
|
|
||||||
|
title = Attribute('The title of the schema field this cell belongs to.')
|
||||||
row = Attribute('The row this cell belongs to.')
|
row = Attribute('The row this cell belongs to.')
|
||||||
|
|
||||||
def sortKey():
|
def sortKey():
|
||||||
|
|
|
@ -27,8 +27,8 @@ $Id$
|
||||||
|
|
||||||
from zope.component import adapts
|
from zope.component import adapts
|
||||||
from zope.interface import implements
|
from zope.interface import implements
|
||||||
|
from cybertools.reporter.interfaces import IDataSource
|
||||||
from cybertools.reporter.interfaces import IResultSet, IRow, ICell
|
from cybertools.reporter.interfaces import IResultSet, IRow, ICell
|
||||||
from cybertools.reporter.example.interfaces import IContactsDataSource
|
|
||||||
|
|
||||||
|
|
||||||
class Cell(object):
|
class Cell(object):
|
||||||
|
@ -69,10 +69,10 @@ class Row(object):
|
||||||
for f in schema.fields])
|
for f in schema.fields])
|
||||||
|
|
||||||
|
|
||||||
class Contacts(object):
|
class ResultSet(object):
|
||||||
|
|
||||||
implements(IResultSet)
|
implements(IResultSet)
|
||||||
adapts(IContactsDataSource)
|
adapts(IDataSource)
|
||||||
|
|
||||||
def __init__(self, context):
|
def __init__(self, context):
|
||||||
self.context = context
|
self.context = context
|
||||||
|
@ -84,7 +84,6 @@ class Contacts(object):
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def rows(self):
|
def rows(self):
|
||||||
return [Row(o, self) for o in iter(self.context)]
|
for o in iter(self.context):
|
||||||
|
yield Row(o, self)
|
||||||
|
|
||||||
def __len__(self):
|
|
||||||
return len(self.rows)
|
|
Loading…
Add table
Reference in a new issue