From 88cd4f7c467129fa67147063ef1028b5b37e365b Mon Sep 17 00:00:00 2001 From: Gaetan Delannay Date: Fri, 17 Sep 2010 09:27:14 +0200 Subject: [PATCH] Optimized performance while rendering references and computed fields and allowed computed fields to be shown asynchronously. --- gen/__init__.py | 49 +++++++++++++++++++--------- gen/plone25/mixins/__init__.py | 25 ++++---------- gen/plone25/model.py | 2 +- gen/plone25/skin/page.pt | 8 ++++- gen/plone25/skin/widgets/computed.pt | 23 +++++++++++-- gen/plone25/skin/widgets/show.pt | 5 +-- 6 files changed, 72 insertions(+), 40 deletions(-) diff --git a/gen/__init__.py b/gen/__init__.py index df5adf4..87177be 100644 --- a/gen/__init__.py +++ b/gen/__init__.py @@ -265,7 +265,7 @@ class Type: editDefault, show, page, group, layouts, move, indexed, searchable, specificReadPermission, specificWritePermission, width, height, colspan, master, masterValue, focus, - historized): + historized, sync): # The validator restricts which values may be defined. It can be an # interval (1,None), a list of string values ['choice1', 'choice2'], # a regular expression, a custom function, a Selection instance, etc. @@ -349,6 +349,9 @@ class Type: # If we must keep track of changes performed on a field, "historized" # must be set to True. self.historized = historized + # self.sync below determines if the field representations will be + # retrieved in a synchronous way by the browser or not (Ajax). + self.sync = self.formatSync(sync) self.id = id(self) self.type = self.__class__.__name__ self.pythonType = None # The True corresponding Python type @@ -450,6 +453,16 @@ class Type: else: return self.pageShow + def formatSync(self, sync): + '''Creates a dictionary indicating, for every layout type, if the field + value must be retrieved synchronously or not.''' + if isinstance(sync, bool): + sync = {'edit': sync, 'view': sync, 'cell': sync} + for layoutType in ('edit', 'view', 'cell'): + if layoutType not in sync: + sync[layoutType] = False + return sync + def formatLayouts(self, layouts): '''Standardizes the given p_layouts. .''' # First, get the layouts as a dictionary, if p_layouts is None or @@ -651,7 +664,7 @@ class Integer(Type): editDefault, show, page, group, layouts, move, indexed, searchable, specificReadPermission, specificWritePermission, width, height, colspan, master, - masterValue, focus, historized) + masterValue, focus, historized, True) self.pythonType = long def validateValue(self, obj, value): @@ -690,7 +703,7 @@ class Float(Type): editDefault, show, page, group, layouts, move, indexed, False, specificReadPermission, specificWritePermission, width, height, colspan, master, masterValue, focus, - historized) + historized, True) self.pythonType = float def getFormattedValue(self, obj, value): @@ -851,7 +864,7 @@ class String(Type): editDefault, show, page, group, layouts, move, indexed, searchable, specificReadPermission, specificWritePermission, width, height, colspan, master, - masterValue, focus, historized) + masterValue, focus, historized, True) self.isSelect = self.isSelection() # Default width and height vary according to String format if width == None: @@ -1016,14 +1029,13 @@ class Boolean(Type): editDefault, show, page, group, layouts, move, indexed, searchable, specificReadPermission, specificWritePermission, width, height, colspan, master, - masterValue, focus, historized) + masterValue, focus, historized, True) self.pythonType = bool def getDefaultLayouts(self): return {'view': 'l;f!_', 'edit': Table('f;lrv;=', width=None)} def getFormattedValue(self, obj, value): - if value in nullValues: return '' if value: res = obj.translate('yes', domain='plone') else: res = obj.translate('no', domain='plone') return res @@ -1057,7 +1069,7 @@ class Date(Type): editDefault, show, page, group, layouts, move, indexed, searchable, specificReadPermission, specificWritePermission, width, height, colspan, master, - masterValue, focus, historized) + masterValue, focus, historized, True) def getCss(self, layoutType): if layoutType == 'edit': return ('jscalendar/calendar-system.css',) @@ -1110,7 +1122,7 @@ class File(Type): editDefault, show, page, group, layouts, move, indexed, False, specificReadPermission, specificWritePermission, width, height, colspan, master, masterValue, focus, - historized) + historized, True) def getValue(self, obj): value = Type.getValue(self, obj) @@ -1209,12 +1221,14 @@ class Ref(Type): # filter the list of available tied objects. self.select = select # Maximum number of referenced objects shown at once. - self.maxPerPage = maxPerPage + self.maxPerPage = maxPerPage + # Specifies sync + sync = {'view': False, 'edit':True} Type.__init__(self, validator, multiplicity, index, default, optional, editDefault, show, page, group, layouts, move, indexed, False, specificReadPermission, specificWritePermission, width, height, colspan, master, masterValue, focus, - historized) + historized, sync) self.validable = self.link def getDefaultLayouts(self): return {'view': 'l-f', 'edit': 'lrv-f'} @@ -1273,7 +1287,7 @@ class Computed(Type): searchable=False, specificReadPermission=False, specificWritePermission=False, width=None, height=None, colspan=1, method=None, plainText=True, master=None, - masterValue=None, focus=False, historized=False): + masterValue=None, focus=False, historized=False, sync=True): # The Python method used for computing the field value self.method = method # Does field computation produce plain text or XHTML? @@ -1281,7 +1295,8 @@ class Computed(Type): Type.__init__(self, None, multiplicity, index, default, optional, False, show, page, group, layouts, move, indexed, False, specificReadPermission, specificWritePermission, width, - height, colspan, master, masterValue, focus, historized) + height, colspan, master, masterValue, focus, historized, + sync) self.validable = False def getValue(self, obj): @@ -1297,7 +1312,7 @@ class Computed(Type): res = str(e) return res - def getFormattedValue(self, obj, value): return self.getValue(obj) + def getFormattedValue(self, obj, value): return value class Action(Type): '''An action is a workflow-independent Python method that can be triggered @@ -1325,7 +1340,8 @@ class Action(Type): Type.__init__(self, None, (0,1), index, default, optional, False, show, page, group, layouts, move, indexed, False, specificReadPermission, specificWritePermission, width, - height, colspan, master, masterValue, focus, historized) + height, colspan, master, masterValue, focus, historized, + False) self.validable = False def getDefaultLayouts(self): return {'view': 'l-f', 'edit': 'lrv-f'} @@ -1377,7 +1393,8 @@ class Info(Type): Type.__init__(self, None, (0,1), index, default, optional, False, show, page, group, layouts, move, indexed, False, specificReadPermission, specificWritePermission, width, - height, colspan, master, masterValue, focus, historized) + height, colspan, master, masterValue, focus, historized, + False) self.validable = False class Pod(Type): @@ -1407,7 +1424,7 @@ class Pod(Type): False, show, page, group, layouts, move, indexed, searchable, specificReadPermission, specificWritePermission, width, height, colspan, master, - masterValue, focus, historized) + masterValue, focus, historized, False) self.validable = False # Workflow-specific types ------------------------------------------------------ diff --git a/gen/plone25/mixins/__init__.py b/gen/plone25/mixins/__init__.py index 248ef2d..fbeede2 100644 --- a/gen/plone25/mixins/__init__.py +++ b/gen/plone25/mixins/__init__.py @@ -300,25 +300,14 @@ class AbstractMixin: '''Returns the method named p_methodName.''' return getattr(self, methodName, None) - def getFieldValue(self, name, useParamValue=False, value=None, - formatted=True): - '''Returns the value of field named p_name for this object (p_self). + def getFieldValue(self, name): + '''Returns the database value of field named p_name for p_self.''' + return self.getAppyType(name).getValue(self) - If p_useParamValue is True, the method uses p_value instead of the - real field value (useful for rendering a value from the object - history, for example). - - If p_formatted is False, it will return the true database - (or default) value. Else, it will produce a nice, string and - potentially translated value.''' - appyType = self.getAppyType(name) - # Which value will we use ? - if not useParamValue: - value = appyType.getValue(self) - # Return the value as is if it is None or forMasterId - if not formatted: return value - # Return the formatted value else - return appyType.getFormattedValue(self, value) + def getFormattedFieldValue(self, name, value): + '''Gets a nice, string representation of p_value which is a value from + field named p_name.''' + return self.getAppyType(name).getFormattedValue(self, value) def _appy_getRefs(self, fieldName, ploneObjects=False, noListIfSingleObj=False, startNumber=None): diff --git a/gen/plone25/model.py b/gen/plone25/model.py index fe7758f..e53169c 100644 --- a/gen/plone25/model.py +++ b/gen/plone25/model.py @@ -22,7 +22,7 @@ class ModelClass: _appy_notinit = ('id', 'type', 'pythonType', 'slaves', 'phase', 'pageShow', 'isSelect', 'hasLabel', 'hasDescr', 'hasHelp', 'master_css', 'layouts', 'required', 'filterable', - 'validable', 'backd', 'isBack') + 'validable', 'backd', 'isBack', 'sync') @classmethod def _appy_addField(klass, fieldName, fieldType, classDescr): diff --git a/gen/plone25/skin/page.pt b/gen/plone25/skin/page.pt index fb60a66..0aa3571 100644 --- a/gen/plone25/skin/page.pt +++ b/gen/plone25/skin/page.pt @@ -157,6 +157,12 @@ } askAjaxChunk(hookId, 'GET', objectUrl, 'widgets/ref', 'viewContent',params); } + function askComputedField(hookId, objectUrl, fieldName) { + // Sends an Ajax request for getting the content of a computed field + var params = {'fieldName': fieldName}; + askAjaxChunk(hookId, 'GET', objectUrl, 'widgets/computed', 'viewContent', + params); + } // Function used by checkbox widgets for having radio-button-like behaviour function toggleCheckbox(visibleCheckbox, hiddenBoolean) { @@ -455,7 +461,7 @@ - diff --git a/gen/plone25/skin/widgets/computed.pt b/gen/plone25/skin/widgets/computed.pt index 23a0a8e..e0acae4 100644 --- a/gen/plone25/skin/widgets/computed.pt +++ b/gen/plone25/skin/widgets/computed.pt @@ -1,7 +1,26 @@ View macro for a Computed. - - + + + + + +
+ +
+
+
+ +Ajax-called view content of a non sync Computed field. + + Edit macro for a Computed. diff --git a/gen/plone25/skin/widgets/show.pt b/gen/plone25/skin/widgets/show.pt index ae172b2..c2717c7 100644 --- a/gen/plone25/skin/widgets/show.pt +++ b/gen/plone25/skin/widgets/show.pt @@ -54,8 +54,9 @@ tal:define="contextMacro python: portal.skyn.widgets; layout python: widget['layouts'][layoutType]; name widget/name; - value python: contextObj.getFieldValue(name); - rawValue python: contextObj.getFieldValue(name, formatted=False); + sync python: widget['sync'][layoutType]; + rawValue python: sync and contextObj.getFieldValue(name) or None; + value python: sync and contextObj.getFormattedFieldValue(name, rawValue) or None; requestValue python: request.get(name, None); inRequest python: request.has_key(name); errors errors | python: ();