[gen] pod field: one of the listed templates in field.template can simply be a pointer to another template from the list. For example, template=('Item.odt', 'Item.odt.variant'). The second file is an empty file and gen will use the first one for the second template. It allows to have similar files for templates that, in the UI, are different, ie, can have different names and appear under different conditions. Note that in the default context of every template, variable 'template' contains the name of the template file. It allows the template to know if he is 'called' under the name 'Item.odt' or 'Item.odt.variant'.
This commit is contained in:
parent
71bc58a8b0
commit
194b455816
|
@ -34,6 +34,7 @@ class Pod(Field):
|
||||||
# Layout for rendering a POD field for exporting query results.
|
# Layout for rendering a POD field for exporting query results.
|
||||||
rLayouts = {'view': 'fl!'}
|
rLayouts = {'view': 'fl!'}
|
||||||
allFormats = {'.odt': ('pdf', 'doc', 'odt'), '.ods': ('xls', 'ods')}
|
allFormats = {'.odt': ('pdf', 'doc', 'odt'), '.ods': ('xls', 'ods')}
|
||||||
|
|
||||||
POD_ERROR = 'An error occurred while generating the document. Please ' \
|
POD_ERROR = 'An error occurred while generating the document. Please ' \
|
||||||
'contact the system administrator.'
|
'contact the system administrator.'
|
||||||
NO_TEMPLATE = 'Please specify a pod template in field "template".'
|
NO_TEMPLATE = 'Please specify a pod template in field "template".'
|
||||||
|
@ -119,10 +120,17 @@ class Pod(Field):
|
||||||
template=None, templateName=None, showTemplate=None,
|
template=None, templateName=None, showTemplate=None,
|
||||||
freezeTemplate=None, context=None, stylesMapping={},
|
freezeTemplate=None, context=None, stylesMapping={},
|
||||||
formats=None, getChecked=None):
|
formats=None, getChecked=None):
|
||||||
# Param "template" stores the path to the pod template(s).
|
# Param "template" stores the path to the pod template(s). If there is
|
||||||
|
# a single template, a string is expected. Else, a list or tuple of
|
||||||
|
# strings is expected. Every such path must be relative to your
|
||||||
|
# application. A pod template name Test.odt that is stored at the root
|
||||||
|
# of your app will be referred as "Test.odt" in self.template. If it is
|
||||||
|
# stored within sub-folder "pod", it will be referred as "pod/Test.odt".
|
||||||
if not template: raise Exception(Pod.NO_TEMPLATE)
|
if not template: raise Exception(Pod.NO_TEMPLATE)
|
||||||
if isinstance(template, basestring):
|
if isinstance(template, basestring):
|
||||||
self.template = [template]
|
self.template = [template]
|
||||||
|
elif isinstance(template, tuple):
|
||||||
|
self.template = list(template)
|
||||||
else:
|
else:
|
||||||
self.template = template
|
self.template = template
|
||||||
# Param "templateName", if specified, is a method that will be called
|
# Param "templateName", if specified, is a method that will be called
|
||||||
|
@ -194,7 +202,8 @@ class Pod(Field):
|
||||||
self.getChecked = getChecked
|
self.getChecked = getChecked
|
||||||
if not formats:
|
if not formats:
|
||||||
# Compute default ones
|
# Compute default ones
|
||||||
if self.template[0].endswith('.ods'):
|
ext = self.getExtension(self.template[0])
|
||||||
|
if ext == '.ods':
|
||||||
self.formats = ('xls', 'ods')
|
self.formats = ('xls', 'ods')
|
||||||
else:
|
else:
|
||||||
self.formats = ('pdf', 'doc', 'odt')
|
self.formats = ('pdf', 'doc', 'odt')
|
||||||
|
@ -207,11 +216,46 @@ class Pod(Field):
|
||||||
# field is determined by freezing.
|
# field is determined by freezing.
|
||||||
self.validable = False
|
self.validable = False
|
||||||
|
|
||||||
|
def getExtension(self, template):
|
||||||
|
'''Gets a p_template's extension (".odt" or ".ods"). Because a template
|
||||||
|
can simply be a pointer to another template (ie, "Item.odt.variant"),
|
||||||
|
the logic for getting the extension is a bit more tricky.'''
|
||||||
|
elems = os.path.splitext(template)
|
||||||
|
if elems[1] in Pod.allFormats: return elems[1]
|
||||||
|
# p_template must be a pointer to another template and has one more
|
||||||
|
# extension.
|
||||||
|
return os.path.splitext(elems[0])[1]
|
||||||
|
|
||||||
def getAllFormats(self, template):
|
def getAllFormats(self, template):
|
||||||
'''Gets all the outputy formats that are available for a given
|
'''Gets all the output formats that are available for a given
|
||||||
p_template.'''
|
p_template.'''
|
||||||
ext = os.path.splitext(template)[1]
|
return self.allFormats[self.getExtension(template)]
|
||||||
return self.allFormats[ext]
|
|
||||||
|
def setTemplateFolder(self, folder):
|
||||||
|
'''This methods adds a prefix to every template name in
|
||||||
|
self.template. This can be useful if a plug-in module needs to
|
||||||
|
replace an application template by its own templates. Here is an
|
||||||
|
example: imagine a base application has a pod field with:
|
||||||
|
|
||||||
|
self.templates = ["Item.odt", "Decision.odt"]
|
||||||
|
|
||||||
|
The plug-in module, named "PlugInApp", wants to replace it with its
|
||||||
|
own templates Item.odt, Decision.odt and Other.odt, stored in its
|
||||||
|
sub-folder "pod". Suppose the base pod field is in <podField>. The
|
||||||
|
plug-in will write:
|
||||||
|
|
||||||
|
<podField>.templates = ["Item.odt", "Decision.odt", "Other.odt"]
|
||||||
|
<podField>.setTemplateFolder('../PlugInApp/pod')
|
||||||
|
|
||||||
|
The following code is equivalent, will work, but is precisely the
|
||||||
|
kind of things we want to avoid.
|
||||||
|
|
||||||
|
<podField>.templates = ["../PlugInApp/pod/Item.odt",
|
||||||
|
"../PlugInApp/pod/Decision.odt",
|
||||||
|
"../PlugInApp/pod/Other.odt"]
|
||||||
|
'''
|
||||||
|
for i in range(len(self.template)):
|
||||||
|
self.template[i] = os.path.join(folder, self.template[i])
|
||||||
|
|
||||||
def getTemplateName(self, obj, fileName):
|
def getTemplateName(self, obj, fileName):
|
||||||
'''Gets the name of a template given its p_fileName.'''
|
'''Gets the name of a template given its p_fileName.'''
|
||||||
|
@ -225,6 +269,19 @@ class Pod(Field):
|
||||||
res = gutils.produceNiceMessage(name)
|
res = gutils.produceNiceMessage(name)
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
def getTemplatePath(self, diskFolder, template):
|
||||||
|
'''Return the absolute path to some pod p_template, by prefixing it with
|
||||||
|
the application path. p_template can be a pointer to another
|
||||||
|
template.'''
|
||||||
|
res = sutils.resolvePath(os.path.join(diskFolder, template))
|
||||||
|
if not os.path.isfile(res):
|
||||||
|
raise Exception(self.TEMPLATE_NOT_FOUND % templatePath)
|
||||||
|
# Unwrap the path if the file is simply a pointer to another one.
|
||||||
|
elems = os.path.splitext(res)
|
||||||
|
if elems[1] not in Pod.allFormats:
|
||||||
|
res = self.getTemplatePath(diskFolder, elems[0])
|
||||||
|
return res
|
||||||
|
|
||||||
def getDownloadName(self, obj, template, format, queryRelated):
|
def getDownloadName(self, obj, template, format, queryRelated):
|
||||||
'''Gets the name of the pod result as will be seen by the user that will
|
'''Gets the name of the pod result as will be seen by the user that will
|
||||||
download it. Ensure the returned name is not too long for the OS that
|
download it. Ensure the returned name is not too long for the OS that
|
||||||
|
@ -295,9 +352,7 @@ class Pod(Field):
|
||||||
tool = obj.tool
|
tool = obj.tool
|
||||||
diskFolder = tool.getDiskFolder()
|
diskFolder = tool.getDiskFolder()
|
||||||
# Get the path to the pod template.
|
# Get the path to the pod template.
|
||||||
templatePath = sutils.resolvePath(os.path.join(diskFolder, template))
|
templatePath = self.getTemplatePath(diskFolder, template)
|
||||||
if not os.path.isfile(templatePath):
|
|
||||||
raise Exception(self.TEMPLATE_NOT_FOUND % templatePath)
|
|
||||||
# Get or compute the specific POD context
|
# Get or compute the specific POD context
|
||||||
specificContext = None
|
specificContext = None
|
||||||
if callable(self.context):
|
if callable(self.context):
|
||||||
|
@ -311,7 +366,8 @@ class Pod(Field):
|
||||||
# Define parameters to give to the appy.pod renderer
|
# Define parameters to give to the appy.pod renderer
|
||||||
podContext = {'tool': tool, 'user': obj.user, 'self': obj, 'field':self,
|
podContext = {'tool': tool, 'user': obj.user, 'self': obj, 'field':self,
|
||||||
'now': obj.o.getProductConfig().DateTime(),
|
'now': obj.o.getProductConfig().DateTime(),
|
||||||
'_': obj.translate, 'projectFolder': diskFolder}
|
'_': obj.translate, 'projectFolder': diskFolder,
|
||||||
|
'template': template}
|
||||||
# If the pod document is related to a query, re-trigger it and put the
|
# If the pod document is related to a query, re-trigger it and put the
|
||||||
# result in the pod context.
|
# result in the pod context.
|
||||||
if queryData:
|
if queryData:
|
||||||
|
|
|
@ -265,6 +265,7 @@ class String(Field):
|
||||||
'view': {LINE:pxViewLine, TEXT:pxViewText, XHTML:pxViewRich,
|
'view': {LINE:pxViewLine, TEXT:pxViewText, XHTML:pxViewRich,
|
||||||
PASSWORD:pxViewLine, CAPTCHA:pxViewLine}
|
PASSWORD:pxViewLine, CAPTCHA:pxViewLine}
|
||||||
}
|
}
|
||||||
|
subPx['cell'] = subPx['view']
|
||||||
|
|
||||||
# Some predefined functions that may also be used as validators
|
# Some predefined functions that may also be used as validators
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
|
|
@ -156,7 +156,7 @@ class UserWrapper(AbstractWrapper):
|
||||||
if self.firstName and self.name:
|
if self.firstName and self.name:
|
||||||
self.title = '%s %s' % (self.name, self.firstName)
|
self.title = '%s %s' % (self.name, self.firstName)
|
||||||
else:
|
else:
|
||||||
self.title = self.login
|
self.title = self.title or self.login
|
||||||
|
|
||||||
def ensureAdminIsManager(self):
|
def ensureAdminIsManager(self):
|
||||||
'''User 'admin' must always have role 'Manager'.'''
|
'''User 'admin' must always have role 'Manager'.'''
|
||||||
|
|
|
@ -776,14 +776,19 @@ class AbstractWrapper(object):
|
||||||
def getField(self, name): return self.o.getAppyType(name)
|
def getField(self, name): return self.o.getAppyType(name)
|
||||||
|
|
||||||
def getValue(self, name, formatted=False, language=None):
|
def getValue(self, name, formatted=False, language=None):
|
||||||
'''Gets the formatted value of field p_name. If this formatting implies
|
'''Gets the possibly p_formatted value of field p_name. If this
|
||||||
translating some element, translate them in p_langue, or in the user
|
formatting implies translating something, it will be done in
|
||||||
language if not specified.'''
|
p_language, or in the user language if not specified. If the "shown"
|
||||||
|
value is required instead of the "formatted" value (see methods
|
||||||
|
getFormattedValue and getShownValue from class appy.fields.Field),
|
||||||
|
use p_formatted="shown" instead of p_formatted=True.'''
|
||||||
field = self.o.getAppyType(name)
|
field = self.o.getAppyType(name)
|
||||||
obj = self.o
|
obj = self.o
|
||||||
val = field.getValue(obj)
|
val = field.getValue(obj)
|
||||||
if not formatted: return val
|
if not formatted: return val
|
||||||
return field.getFormattedValue(obj, val, language=language)
|
method = (formatted == 'shown') and 'getShownValue' or \
|
||||||
|
'getFormattedValue'
|
||||||
|
return getattr(field, method)(obj, val, language=language)
|
||||||
|
|
||||||
def getLabel(self, name, type='field'):
|
def getLabel(self, name, type='field'):
|
||||||
'''Gets the translated label of field named p_name. If p_type is
|
'''Gets the translated label of field named p_name. If p_type is
|
||||||
|
|
Loading…
Reference in a new issue