[Zope3-checkins] CVS: Zope3/lib/python/Zope/App/index/text - control.py:1.1 configure.zcml:1.4 control.pt:1.7 interfaces.py:1.6
Guido van Rossum
guido@python.org
Mon, 9 Dec 2002 14:47:17 -0500
Update of /cvs-repository/Zope3/lib/python/Zope/App/index/text
In directory cvs.zope.org:/tmp/cvs-serv6296
Modified Files:
configure.zcml control.pt interfaces.py
Added Files:
control.py
Log Message:
Moved all the view-specific code to a separate vew module, control.py.
Batching now works. (The default batch size is 2, for testing.)
=== Added File Zope3/lib/python/Zope/App/index/text/control.py ===
##############################################################################
#
# Copyright (c) 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""Control view for the text index.
XXX longer description goes here.
$Id: control.py,v 1.1 2002/12/09 19:47:16 gvanrossum Exp $
"""
from __future__ import generators
from Zope.ComponentArchitecture import getService, queryAdapter
from Zope.Exceptions import NotFoundError
from Zope.Publisher.Browser.IBrowserView import IBrowserView
from Zope.App.Traversing import locationAsUnicode
from Zope.App.DublinCore.IZopeDublinCore import IZopeDublinCore
from Zope.App.index.text.interfaces import IQueryView
class ControlView(object):
__implements__ = IBrowserView, IQueryView
default_start = 0 # Don't change -- always start at first batch
default_count = 2 # Default batch size -- tune as you please
def __init__(self, context, request):
self.index = self.context = context
self.request = request
self.hub = getService(context, "ObjectHub")
def nextBatch(self):
start = int(self.request.get('start', self.default_start))
count = int(self.request.get('count', self.default_count))
return start + count
def prevBatch(self):
start = int(self.request.get('start', self.default_start))
count = int(self.request.get('count', self.default_count))
return start - count
def query(self, start=None):
queryText = self.request.get('queryText', '')
if start is None:
start = int(self.request.get('start', self.default_start))
count = int(self.request.get('count', self.default_count))
results, total = self.index.query(queryText, start, count)
nresults = len(results)
first = start + 1
last = first + len(results) - 1
result = {
'results': list(self._resultIterator(results)),
'nresults': nresults,
'first': first,
'last': last,
'total': total,
}
if start > 0:
prev = max(0, start - count)
result['prev'] = prev
if last < total:
next = start + count
result['next'] = next
return result
def _resultIterator(self, results):
for hubid, score in results:
yield self._cookInfo(hubid, score)
def _cookInfo(self, hubid, score):
location = locationAsUnicode(self.hub.getLocation(hubid))
scoreLabel = "%.1f%%" % (100.0 * score)
result = {
'location': location,
'score': score,
'scoreLabel': scoreLabel,
}
try:
object = self.hub.getObject(hubid)
except NotFoundError:
pass
else:
dc = queryAdapter(object, IZopeDublinCore, context=self.index)
if dc is not None:
title = dc.title
result['title'] = title
return result
=== Zope3/lib/python/Zope/App/index/text/configure.zcml 1.3 => 1.4 ===
--- Zope3/lib/python/Zope/App/index/text/configure.zcml:1.3 Wed Dec 4 16:38:02 2002
+++ Zope3/lib/python/Zope/App/index/text/configure.zcml Mon Dec 9 14:47:16 2002
@@ -32,8 +32,12 @@
<browser:view
for="Zope.TextIndex.TextIndexInterfaces.IStatistics"
- permission="Zope.View"
+ permission="Zope.ManageServices"
name="control.html"
- template="control.pt" />
+ factory=".control.ControlView">
+
+ <browser:page name="index.html" template="control.pt" />
+
+ </browser:view>
</zopeConfigure>
=== Zope3/lib/python/Zope/App/index/text/control.pt 1.6 => 1.7 ===
--- Zope3/lib/python/Zope/App/index/text/control.pt:1.6 Fri Dec 6 09:49:11 2002
+++ Zope3/lib/python/Zope/App/index/text/control.pt Mon Dec 9 14:47:16 2002
@@ -29,11 +29,11 @@
</span>
<div>
- Documents: <span tal:replace="context/documentCount" />
+ Documents: <span tal:replace="context/documentCount" />
</div>
<div>
- Words: <span tal:replace="context/wordCount" />
+ Words: <span tal:replace="context/wordCount" />
</div>
<form method="POST">
@@ -52,34 +52,37 @@
<form method="GET">
<input type="text" name="queryText" value=""
tal:attributes="value request/queryText|nothing" />
- <input type="submit" value="Query" name="callQuery" />
+ <input type="submit" value="Query" />
</form>
<div tal:condition="request/queryText|nothing" tal:omit-tag="">
- <span tal:define="
- result_tuple python:context.query(request['queryText'],0,100);
- total python:result_tuple[1];
- result_list python:result_tuple[0]"
- tal:omit-tag=""
- tal:on-error="string:invalid query"
- >
- Search results: <span tal:replace="total" />
- <div tal:repeat="match_tuple result_list">
- <span tal:define="
- hubid python:match_tuple[0];
- score python:match_tuple[1];
- location python:context.hubid2location(hubid);
- title python:context.hubid2title(hubid) or '(no title)';
- ">
- Location:
- <a href="location"
- tal:attributes="href location"
- tal:content="location">location</a>
- Title: <span tal:replace="title" />
- Score: <span tal:replace="score" />
- </span>
- </div>
- </span>
+ <div tal:define="result view/query" tal:omit-tag="">
+ <div tal:condition="not:result/total">
+ No hits. Please try another query.
+ </div>
+ <div tal:condition="result/total">
+ <div tal:content="
+ string:Hits ${result/first}-${result/last} of ${result/total}:"
+ />
+ <div tal:repeat="info result/results">
+ title=<span tal:replace="info/title" />;
+ url=<a href="location"
+ tal:attributes="href info/location"
+ tal:content="info/location">url</a>;
+ score=<span tal:replace="info/scoreLabel" />
+ </div>
+ </div>
+ <span tal:condition="exists:result/prev">
+ <a href="next"
+ tal:attributes="href
+ string:?queryText=${request/queryText}&start=${view/prevBatch}"><-- PREVIOUS BATCH</a>
+ </span>
+ <span tal:condition="exists:result/next">
+ <a href="next"
+ tal:attributes="href
+ string:?queryText=${request/queryText}&start=${view/nextBatch}">NEXT BATCH --></a>
+ </span>
+ </div>
</div>
</div>
=== Zope3/lib/python/Zope/App/index/text/interfaces.py 1.5 => 1.6 ===
--- Zope3/lib/python/Zope/App/index/text/interfaces.py:1.5 Fri Dec 6 09:49:11 2002
+++ Zope3/lib/python/Zope/App/index/text/interfaces.py Mon Dec 9 14:47:16 2002
@@ -47,17 +47,42 @@
def isSubscribed():
"""Return whether we are currently subscribed."""
- # XXX The following are blatant view helpers. Need refactoring.
+class IQueryView(Interface):
- def hubid2location(hubid):
- """Return a location string given a hubid."""
+ """Interface providing a query method that can be invoked from ZPT.
- def hubid2object(hubid):
- """Return an object given a hubid."""
+ XXX How to express that this is a browser interface?"""
- def hubid2title(hubid):
- """Return the Dublin Core title of the object from the hubid.
+ def query():
+ """Perform a batched query, based on request fields.
- Return '' if there is no object or if it isn't adaptable to
- IZopeDublinCore.
+ These request fields are used as input:
+
+ start -- batch start (0-based); defaults to 0
+ count -- batch size; defaults to 10
+ queryText -- query expression; must be given
+
+ Return a dict with fields:
+
+ results -- a list containing the requested batch
+ nresults -- number of items in results
+ first -- 1-based ordinal this batch's first item
+ last -- 1-based ordinal of if this batch's last item
+ next -- 0-based ordinal of next batch; not set if no next batch
+ prev -- 0-based ordinal of previous batch; not set if no prev batch
+ count -- requested batch size
+ total -- total number of matches (all batches together)
+
+ Each item in the results set has the following string fields:
+
+ location -- location of the object (usable as URL within the site)
+ title -- Dublin Core title of the object; not present if no title
+ score -- score, as a float in the range [0.0 ... 1.0]
+ scoreLabel -- score, formatted as a percentage and rounded to 0.1%
"""
+
+ def nextBatch():
+ """Return the start for the next batch."""
+
+ def prevBatch():
+ """Return the start for the previous batch."""