changeset 1347:cd22cf9e8dd7

implement +lookup view for itemid/revid/... based lookup
author Thomas Waldmann <tw AT waldmann-edv DOT de>
date Mon, 07 May 2012 00:32:59 +0200
parents 62bfa171319f
children 04f567afe65f 5b88a6ae67a5
files MoinMoin/apps/frontend/views.py MoinMoin/templates/lookup.html
diffstat 2 files changed, 124 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/MoinMoin/apps/frontend/views.py	Sun May 06 17:25:16 2012 +0200
+++ b/MoinMoin/apps/frontend/views.py	Mon May 07 00:32:59 2012 +0200
@@ -39,7 +39,7 @@
 import pytz
 from babel import Locale
 
-from whoosh.query import Term, And, Or, DateRange
+from whoosh.query import Term, Prefix, And, Or, DateRange
 
 from MoinMoin import log
 logging = log.getLogger(__name__)
@@ -124,6 +124,85 @@
     return app.send_static_file('logos/favicon.ico')
 
 
+class LookupForm(Form):
+    name = String.using(label=L_('name'), optional=True)
+    name_exact = String.using(label=L_('name_exact'), optional=True)
+    itemid = String.using(label=L_('itemid'), optional=True)
+    revid = String.using(label=L_('revid'), optional=True)
+    history = Boolean.using(label=L_('search also in non-current revisions'), optional=True)
+    submit = String.using(default=L_('Lookup'), optional=True)
+
+
+@frontend.route('/+lookup', methods=['GET', 'POST'])
+def lookup():
+    """
+    lookup is like search, but it only deals with specific fields that identify
+    an item / revision. no query string parsing.
+
+    for uuid fields, it performs a prefix search, so you can just give the
+    first few digits. same is done for name_exact field.
+    if you give a complete uuid or you do a lookup via the name field, it
+    will use a simple search term.
+    for one result, it directly redirects to the item/revision found.
+    for none or multipe results, a result page is shown.
+
+    usually this is used for links with a query string, like:
+    /+lookup?itemid=123cba  (prefix match on itemid 123cba.......)
+    /+lookup?revid=c0ddcda9a092499c92920cc4a9b11704  (full uuid simple term match)
+    /+lookup?name_exact=FooBar/  (prefix match on name_exact FooBar/...)
+
+    When giving history=1 it will use the all revisions index for lookup.
+    """
+    status = 200
+    title_name = _("Lookup")
+    lookup_form = LookupForm.from_flat(request.values)
+    valid = lookup_form.validate()
+    lookup_form['submit'].set_default() # XXX from_flat() kills all values
+    if valid:
+        history = bool(request.values.get('history'))
+        idx_name = ALL_REVS if history else LATEST_REVS
+        terms = []
+        for key in [NAME, NAME_EXACT, ITEMID, REVID, ]:
+            value = lookup_form[key].value
+            if value:
+                if (key in [ITEMID, REVID, ] and len(value) < crypto.UUID_LEN
+                    or
+                    key in [NAME_EXACT]):
+                    term = Prefix(key, value)
+                else:
+                    term = Term(key, value)
+                terms.append(term)
+        if terms:
+            terms.append(Term(WIKINAME, app.cfg.interwikiname))
+            q = And(terms)
+            with flaskg.storage.indexer.ix[idx_name].searcher() as searcher:
+                flaskg.clock.start('lookup')
+                results = searcher.search(q, limit=100)
+                flaskg.clock.stop('lookup')
+                num_results = results.scored_length()
+                if num_results == 1:
+                    result = results[0]
+                    rev = result[REVID] if history else CURRENT
+                    url = url_for('.show_item', item_name=result[NAME], rev=rev)
+                    return redirect(url)
+                else:
+                    flaskg.clock.start('lookup render')
+                    html = render_template('lookup.html',
+                                           title_name=title_name,
+                                           lookup_form=lookup_form,
+                                           results=results,
+                                          )
+                    flaskg.clock.stop('lookup render')
+                    if not num_results:
+                        status = 404
+                    return Response(html, status)
+    html = render_template('lookup.html',
+                           title_name=title_name,
+                           lookup_form=lookup_form,
+                          )
+    return Response(html, status)
+
+
 @frontend.route('/+search', methods=['GET', 'POST'])
 def search():
     title_name = _("Search")
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MoinMoin/templates/lookup.html	Mon May 07 00:32:59 2012 +0200
@@ -0,0 +1,44 @@
+{% extends theme("layout.html") %}
+{% import "utils.html" as utils %}
+{% import "forms.html" as forms %}
+{% block content %}
+    {% if results is not defined %}
+    <h1>{{ _("Lookup") }}</h1>
+    {{ gen.form.open(lookup_form, id='moin-lookup-form', method='get', action=url_for('frontend.lookup')) }}
+        {{ forms.render_errors(lookup_form) }}
+        <dl>
+            {{ forms.render_field(gen, lookup_form['name'], 'text') }}
+            {{ forms.render_field(gen, lookup_form['name_exact'], 'text') }}
+            {{ forms.render_field(gen, lookup_form['itemid'], 'text') }}
+            {{ forms.render_field(gen, lookup_form['revid'], 'text') }}
+            {{ forms.render_field_without_markup(gen, lookup_form['history'], 'checkbox') }}
+        </dl>
+        {{ gen.input(lookup_form['submit'], type='submit') }}
+    {{ gen.form.close() }}
+    {% else %}
+    {% if not results %}
+    <h1>{{ _("No results") }}</h1>
+    {% else %}
+    <h1>{{ _("More than one result") }}</h1>
+    <div class="lookupresults">
+        <table>
+            {% for result in results %}
+                {% if result['wikiname'] == cfg.interwikiname %}
+                    <tr>
+                        <td class="moin-wordbreak">{{ result.pos + 1 }}
+                        <a href="{{ url_for_item(item_name=result['name'], wiki_name='Self', rev=result['revid']) }}"><b>{{ result['name'] }}</b></a>
+                        </td>
+                    </tr>
+                {% else %}
+                    <tr>
+                        <td class="moin-wordbreak">{{ result.pos + 1 }}
+                        <a class="moin-interwiki" href="{{ url_for_item(item_name=result['name'], wiki_name=result['wikiname'], rev=result['revid']) }}"><b>{{ "%s:%s" % (result['wikiname'], result['name']) }}</b></a>
+                        </td>
+                    </tr>
+                {% endif %}
+            {% endfor %}
+        </table>
+    </div>
+    {% endif %}
+    {% endif %}
+{% endblock %}