Commit 18896b2c authored by LE GAC Renaud's avatar LE GAC Renaud
Browse files

Refactor the list controller and views to ease the integration of new formats.

parent 2913e779
......@@ -5,9 +5,8 @@ import re
from gluon.dal import Field
from list_postprocessing import *
from plugin_dbui import Selector
from reporting_tools import (get_converter,
from reporting_tools import (get_converter,
get_sections,
repr_team_project)
......@@ -22,25 +21,25 @@ def index():
# get the user constraint.
# the selector fields year_start, year_end, id_lists are excluded
# from the selector query.
selector = Selector(virtdb.list_selector,
exclude_fields=('author',
'year_start',
'year_end',
selector = Selector(virtdb.list_selector,
exclude_fields=('author',
'year_start',
'year_end',
'id_lists'))
# protection
# protection
if not selector.id_lists:
return MSG_NO_LIST
return MSG_NO_LIST
# retrieve the list data
list = db.lists[selector.id_lists]
mylist = db.lists[selector.id_lists]
# retrieve the section records belonging to the list
# and add to each section the parameters query and orderby
sections = get_sections(db, selector, list)
# and add to each section the parameters query and orderby
sections = get_sections(db, selector, mylist)
# get the converter dictionary for axes labels
cvt_labels = get_converter(list)
cvt_labels = get_converter(mylist)
# retrieve the publications for each section
# organise them according to the level requirements, for example
......@@ -51,9 +50,10 @@ def index():
# format each record according to user requirements
paths_keys = []
paths_data = {}
paths_renderers = {}
for section in sections:
# retrieve the database field defining the levels of the section
# they will be used to build the path associated to each record
# This information is fully defined by the orderby directive
......@@ -61,40 +61,37 @@ def index():
for field in section.orderby:
if not isinstance(field, Field):
field = field.first
level_keys.append((field.tablename, field.name))
# retrieve the rendered associated to the section
renderer = db.renderers[section.id_renderers]
level_keys.append((field.tablename, field.name))
# add the orderby directive internal to the section
orderby = section.orderby
if section.sort_field:
li = [el for el in section.orderby]
field = db.publications[section.sort_field]
if section.direction == "DESC":
field = ~field
li.append(field)
orderby = tuple(li)
# retrieve the record
for record in db(section.query).select(orderby=orderby):
# build the list of paths -- similar to a list of directory
# example ['articles', 'articles/2012']
path = None
for i in range(len(level_keys)):
path = None
for i in range(len(level_keys)):
fieldname = level_keys[i][1]
tablename = level_keys[i][0]
node = record[tablename][fieldname]
node = str(node)
if node in cvt_labels:
node = cvt_labels[node]
if path:
path = "%s/%s" % (path, node)
else:
......@@ -102,25 +99,17 @@ def index():
if path not in paths_keys:
paths_keys.append(path)
paths_renderers[path] = section.renderer
# fill the last path with its record
if path not in paths_data:
paths_data[path] = []
# format the record according to user requirement
value = renderer.template.format(**record)
# run post processing to polish/clean the value
if renderer.postprocessing:
funcs = renderer.postprocessing.replace(' ','').split(',')
for func in funcs:
if func in globals():
value = globals()[func](value, renderer.template, record)
paths_data[path].append(value)
return dict(list=list,
paths_keys=paths_keys,
paths_data[path].append(record)
return dict(mylist=mylist,
paths_keys=paths_keys,
paths_data=paths_data,
paths_renderers=paths_renderers,
selector=selector,
team_project=repr_team_project(db, selector))
......@@ -3,33 +3,62 @@
@author: R. Le Gac
"""
from list_postprocessing import *
from gluon import current
from gluon.dal import smart_query
from gluon.html import IFRAME, URL
from gluon.storage import Storage
from plugin_dbui import decode_field, UNDEF
def format_publication(template, record, funcs=[]):
"""Build the bibliographic string for the publication.
@type template str:
@param template str:
@type record: gluon.DAL.Row
@param record
@type funcs: list
@param funcs: list of functions to polish the bibliographic reference
@rtype: str
@return: the bibliographic reference
"""
# format the record according to user requirement
value = template.format(**record)
# run post processing to polish/clean the value
if funcs:
for func in funcs:
value = func(value, template, record)
return value
def get_converter(list):
"""Get the converter dictionary for the axis label of the C{list}.
@type list: gluon.dal.Row
@param list: One row of the database table C{list}.
@rtype: dict
@return:
@return:
- C{value: "blabla, ....", value2: "foo", ....}
"""
di = {}
if list.axis_label_converters:
s = re.sub(r'" *, *', '"|', list.axis_label_converters)
for el in s.split('|'):
m = re.match(r' *(.+) *: *"(.+)"', el)
if m:
di[m.group(1)] = m.group(2)
return di
......@@ -38,102 +67,116 @@ def get_sections(db, selector, list):
@type db: gluon.dal.DAL
@param db:
@type selector: plugin_dbui.Selector
@param selector:
@type list: gluon.dal.Row
@param list: One row of the database table C{list}.
@rtype: list
@return:
@return:
- a list of rows of the C{sections} table
- each row also contains the C{query} and C{orderby}
directive taking into account C{selector} directive.
directive taking into account C{selector} directive.
- each row contains also the renderer format and post
processing functions
"""
sections = []
for el in list.sections.split(','):
# retrieve the section record
el = el.strip()
rows = db(db.sections.section == el).select()
if not rows:
continue
section = rows.first()
section = rows.first()
sections.append(section)
# query directive to extract publications for this section
# It includes foreign key constraints and user requirements
# related to team, project, authors and year
query = selector.query(db.publications)
if selector.year_start and not selector.year_end:
query = (query) & (db.publications.year == selector.year_start)
elif selector.year_start and selector.year_end:
q_start = db.publications.year >= selector.year_start
q_end = db.publications.year <= selector.year_end
q_end = db.publications.year <= selector.year_end
query = (query) & ((q_start) & (q_end))
if selector.author:
q_author = db.publications.authors.contains(selector.author)
query = (query) & (q_author)
# add to the query the directive coming from the section itself
# the publication category and dedicated conditions
if section.category_codes:
q_cat = None
codes = section.category_codes.replace(' ','').split(',')
codes = section.category_codes.replace(' ', '').split(',')
if codes:
q_cat = db.categories.code.belongs(codes)
query = (query) & (q_cat)
if section.conditions:
q_conditions = smart_query(db.publications, section.conditions)
query = (query) & (q_conditions)
section.query = query
# order by directive to order publication for this section
# taking into account directive from the list and from the section
orderby = []
for level in ('level_1', 'level_2', 'level_3', 'level_4'):
axis = 'axis_%s' % level
if not list[axis]:
continue
tablename = list[axis]
fieldname = list['granularity_%s' % level]
direction = list["direction_%s" % level]
direction = list["direction_%s" % level]
field = db[tablename][fieldname]
if direction == "DESC":
field = ~field
orderby.append(field)
orderby.append(field)
section.orderby = tuple(orderby)
# the renderer format and post processing functions
renderer = db.renderers[section.id_renderers]
section.renderer = Storage()
section.renderer.template = renderer.template
section.renderer.funcs = []
funcs = renderer.postprocessing.replace(' ', '').split(',')
for func in funcs:
if func in globals():
section.renderer.funcs.append(globals()[func])
return sections
def ref_url(name='List'):
"""Get the URL string uses to build the current request.
@note: this function is useful in view
@type name: str
@param name:
@rtype: str
@return: C{"http://..."}
"""
vars = []
for (k, v) in request.vars.iteritems():
......@@ -144,19 +187,19 @@ def ref_url(name='List'):
t = (request.env.http_host, request.env.path_info, '&'.join(vars))
url = "http://%s%s?%s" % t
return url
def repr_team_project(db, selector):
"""Build the team/project string.
@type db: gluon.dal.DAL
@param db:
@type selector: plugin_dbui.Selector
@param selector:
@rtype: unicode
@return: the format is "team" or "project" or "team/project".
"""
......
{{
from reporting_tools import format_publication
response.write(BR())
#
# HEADER
#
if list.header_flag:
if mylist.header_flag:
title = "%s %s" % (T("Publications"), team_project)
response.write(P(title, _class="my-p my-small-cap my-large"))
pass
......@@ -28,9 +31,14 @@
if key not in paths_data:
continue
renderer = paths_renderers[key]
template = renderer.template
funcs = renderer.funcs
li = []
for record in paths_data[key]:
li.append(LI(XML(record), _class="my-li"))
value = format_publication(template, record, funcs=funcs)
li.append(LI(XML(value), _class="my-li"))
pass
response.write(OL(*li, _class="my-ol", _style="{margin-left:%s%%;}" % margin))
......@@ -44,7 +52,7 @@
# Display the URL only in the first case.
#
=BR()
if list.footer_flag and request.env.request_method == 'POST':
if mylist.footer_flag and request.env.request_method == 'POST':
html_url = A("url", _href=selector.repr_url())
=P(T("Direct access to the table: "), html_url, _class="my-p")
=P(request.now.strftime("%d %b %Y %H:%M"), _class="my-p")
......
......@@ -6,10 +6,14 @@
{{
import re
import textwrap
from reporting_tools import format_publication
#
# HEADER
#
if list.header_flag:
if mylist.header_flag:
date = request.now.strftime("%d %b %Y")
response.write("\n\\begin{flushleft}\n")
......@@ -38,12 +42,18 @@
if key not in paths_data:
continue
renderer = paths_renderers[key]
template = renderer.template
funcs = renderer.funcs
margin = 1.6 * level
response.write("\n \\begin{enumerate}[leftmargin=%sem]" % margin, escape=False)
for record in paths_data[key]:
value = format_publication(template, record, funcs=funcs)
s = record.replace('<br>', '')
s = value.replace('<br>', '')
s = s.replace('<b>', '\\textbf{').replace('</b>', '}')
s = s.replace('<i>', '\emph{').replace('</i>', '}')
s = s.replace('<u>', '\underline{').replace('</u>', '}')
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment