[gen] Added wrapper.createFrom, similar to wrapper.create, but allows to create an object with data from another object (kind of 'duplicate' functionality).
This commit is contained in:
parent
400158a0a1
commit
4d12293dc8
|
@ -533,6 +533,11 @@ class Field:
|
||||||
return self.default
|
return self.default
|
||||||
return value
|
return value
|
||||||
|
|
||||||
|
def getCopyValue(self, obj):
|
||||||
|
'''Gets the value of this field on p_obj as with m_getValue above. But
|
||||||
|
if this value is mutable, get a copy of it.'''
|
||||||
|
return self.getValue(obj)
|
||||||
|
|
||||||
def getFormattedValue(self, obj, value, showChanges=False, language=None):
|
def getFormattedValue(self, obj, value, showChanges=False, language=None):
|
||||||
'''p_value is a real p_obj(ect) value from a field from this type. This
|
'''p_value is a real p_obj(ect) value from a field from this type. This
|
||||||
method returns a pretty, string-formatted version, for displaying
|
method returns a pretty, string-formatted version, for displaying
|
||||||
|
|
|
@ -331,6 +331,7 @@ class File(Field):
|
||||||
name = requestName or self.name
|
name = requestName or self.name
|
||||||
return obj.REQUEST.get('%s_file' % name)
|
return obj.REQUEST.get('%s_file' % name)
|
||||||
|
|
||||||
|
def getCopyValue(self, obj): raise Exception('Not implemented yet.')
|
||||||
def getDefaultLayouts(self): return {'view':'l-f','edit':'lrv-f'}
|
def getDefaultLayouts(self): return {'view':'l-f','edit':'lrv-f'}
|
||||||
|
|
||||||
def isEmptyValue(self, obj, value):
|
def isEmptyValue(self, obj, value):
|
||||||
|
|
|
@ -786,6 +786,14 @@ class Ref(Field):
|
||||||
if someObjects: return res
|
if someObjects: return res
|
||||||
return res.objects
|
return res.objects
|
||||||
|
|
||||||
|
def getCopyValue(self, obj):
|
||||||
|
'''Here, as "value ready-to-copy", we return the list of tied object
|
||||||
|
UIDs, because m_store on the destination object can store tied
|
||||||
|
objects based on such a list.'''
|
||||||
|
res = getattr(obj.aq_base, self.name, ())
|
||||||
|
# Return a copy: it can be dangerous to give the real database value.
|
||||||
|
if res: return list(res)
|
||||||
|
|
||||||
def getPossibleValues(self, obj, startNumber=None, someObjects=False,
|
def getPossibleValues(self, obj, startNumber=None, someObjects=False,
|
||||||
removeLinked=False):
|
removeLinked=False):
|
||||||
'''This method returns the list of all objects that can be selected
|
'''This method returns the list of all objects that can be selected
|
||||||
|
|
|
@ -155,6 +155,7 @@ class String(Field):
|
||||||
multilingual=len(languages) > 1;
|
multilingual=len(languages) > 1;
|
||||||
mLayout=multilingual and field.getLanguagesLayout('view');
|
mLayout=multilingual and field.getLanguagesLayout('view');
|
||||||
mayAjaxEdit=not showChanges and field.inlineEdit and \
|
mayAjaxEdit=not showChanges and field.inlineEdit and \
|
||||||
|
(layoutType != 'cell') and \
|
||||||
zobj.mayEdit(field.writePermission)">
|
zobj.mayEdit(field.writePermission)">
|
||||||
<x if="field.isSelect">
|
<x if="field.isSelect">
|
||||||
<span if="not value" class="smaller">-</span>
|
<span if="not value" class="smaller">-</span>
|
||||||
|
@ -518,6 +519,13 @@ class String(Field):
|
||||||
value = list(value)
|
value = list(value)
|
||||||
return value
|
return value
|
||||||
|
|
||||||
|
def getCopyValue(self, obj):
|
||||||
|
'''If the value is mutable (ie, a dict for a multilingual field), return
|
||||||
|
a copy of it instead of the value stored in the database.'''
|
||||||
|
res = self.getValue(obj)
|
||||||
|
if isinstance(res, dict): res = res.copy()
|
||||||
|
return res
|
||||||
|
|
||||||
def valueIsInRequest(self, obj, request, name):
|
def valueIsInRequest(self, obj, request, name):
|
||||||
languages = self.getAttribute(obj, 'languages')
|
languages = self.getAttribute(obj, 'languages')
|
||||||
if len(languages) == 1:
|
if len(languages) == 1:
|
||||||
|
|
|
@ -356,18 +356,10 @@ class FieldDescriptor:
|
||||||
group = self.appyType.group
|
group = self.appyType.group
|
||||||
if group and not group.label:
|
if group and not group.label:
|
||||||
group.generateLabels(self.generator.labels, self.classDescr, set())
|
group.generateLabels(self.generator.labels, self.classDescr, set())
|
||||||
# Manage things which are specific to String types
|
# Generate type-specific i18n labels
|
||||||
if self.appyType.type == 'String': self.walkString()
|
if not self.appyType.label:
|
||||||
# Manage things which are specific to Boolean types
|
method = 'walk%s' % self.appyType.type
|
||||||
if self.appyType.type == 'Boolean': self.walkBoolean()
|
if hasattr(self, method): getattr(self, method)()
|
||||||
# Manage things which are specific to Actions
|
|
||||||
elif self.appyType.type == 'Action': self.walkAction()
|
|
||||||
# Manage things which are specific to Ref types
|
|
||||||
elif self.appyType.type == 'Ref': self.walkRef()
|
|
||||||
# Manage things which are specific to List types
|
|
||||||
elif self.appyType.type == 'List': self.walkList()
|
|
||||||
# Manage things which are specific to Calendar types
|
|
||||||
elif self.appyType.type == 'Calendar': self.walkCalendar()
|
|
||||||
|
|
||||||
def generate(self):
|
def generate(self):
|
||||||
'''Generates the i18n labels for this type.'''
|
'''Generates the i18n labels for this type.'''
|
||||||
|
|
|
@ -144,9 +144,9 @@ class ZopeInstaller:
|
||||||
# Re-index index "SearchableText", wrongly defined for Appy < 0.8.3.
|
# Re-index index "SearchableText", wrongly defined for Appy < 0.8.3.
|
||||||
stIndex = catalog.Indexes['SearchableText']
|
stIndex = catalog.Indexes['SearchableText']
|
||||||
if stIndex.indexSize() == 0:
|
if stIndex.indexSize() == 0:
|
||||||
self.logger.info('Reindexing SearchableText...')
|
self.logger.info('reindexing SearchableText...')
|
||||||
catalog.reindexIndex('SearchableText', self.app.REQUEST)
|
catalog.reindexIndex('SearchableText', self.app.REQUEST)
|
||||||
self.logger.info('Done.')
|
self.logger.info('done.')
|
||||||
|
|
||||||
def installBaseObjects(self):
|
def installBaseObjects(self):
|
||||||
'''Creates the tool and the base data folder if they do not exist.'''
|
'''Creates the tool and the base data folder if they do not exist.'''
|
||||||
|
@ -236,7 +236,7 @@ class ZopeInstaller:
|
||||||
for message in poFile.messages:
|
for message in poFile.messages:
|
||||||
setattr(translation, message.id, message.getMessage())
|
setattr(translation, message.id, message.getMessage())
|
||||||
done.append(translation.id)
|
done.append(translation.id)
|
||||||
appyTool.log('Translation(s) %s updated (%s messages).' % \
|
appyTool.log('translation(s) %s updated (%s messages).' % \
|
||||||
(', '.join(done), len(poFile.messages)))
|
(', '.join(done), len(poFile.messages)))
|
||||||
|
|
||||||
# Execute custom installation code if any.
|
# Execute custom installation code if any.
|
||||||
|
|
|
@ -715,9 +715,10 @@ class AbstractWrapper(object):
|
||||||
def appy(self): return self
|
def appy(self): return self
|
||||||
|
|
||||||
def __setattr__(self, name, value):
|
def __setattr__(self, name, value):
|
||||||
appyType = self.o.getAppyType(name)
|
field = self.o.getAppyType(name)
|
||||||
if not appyType: raise Exception('Attribute "%s" does not exist.' %name)
|
if not field:
|
||||||
appyType.store(self.o, value)
|
raise AttributeError('Attribute "%s" does not exist.' % name)
|
||||||
|
field.store(self.o, value)
|
||||||
|
|
||||||
def __getattribute__(self, name):
|
def __getattribute__(self, name):
|
||||||
'''Gets the attribute named p_name. Lot of cheating here.'''
|
'''Gets the attribute named p_name. Lot of cheating here.'''
|
||||||
|
@ -844,13 +845,23 @@ class AbstractWrapper(object):
|
||||||
reverse=reverse)
|
reverse=reverse)
|
||||||
refs._p_changed = 1
|
refs._p_changed = 1
|
||||||
|
|
||||||
def create(self, fieldNameOrClass, noSecurity=False, **kwargs):
|
def create(self, fieldNameOrClass, noSecurity=False,
|
||||||
'''If p_fieldNameOrClass is the name of a field, this method allows to
|
raiseOnWrongAttribute=True, **kwargs):
|
||||||
create an object and link it to the current one (self) through
|
'''This method creates a new instance of a gen-class.
|
||||||
reference field named p_fieldName.
|
|
||||||
If p_fieldNameOrClass is a class from the gen-application, it must
|
If p_fieldNameOrClass is the name of a field, the created object will
|
||||||
correspond to a root class and this method allows to create a
|
be linked to p_self via this field. If p_fieldNameOrClass is a class
|
||||||
root object in the application folder.'''
|
from the gen-application, it must correspond to a root class: the
|
||||||
|
created object will be stored in the main application folder (and no
|
||||||
|
link will exist between it and p_self).
|
||||||
|
|
||||||
|
p_kwargs allow to specify values for object fields.
|
||||||
|
If p_noSecurity is True, security checks will not be performed.
|
||||||
|
|
||||||
|
If p_raiseOnWrongAttribute is True, if a value from p_kwargs does not
|
||||||
|
correspond to a field on the created object, an AttributeError will
|
||||||
|
be raised. Else, the value will be silently ignored.
|
||||||
|
'''
|
||||||
isField = isinstance(fieldNameOrClass, basestring)
|
isField = isinstance(fieldNameOrClass, basestring)
|
||||||
tool = self.tool.o
|
tool = self.tool.o
|
||||||
# Determine the class of the object to create
|
# Determine the class of the object to create
|
||||||
|
@ -867,11 +878,6 @@ class AbstractWrapper(object):
|
||||||
del kwargs['id']
|
del kwargs['id']
|
||||||
else:
|
else:
|
||||||
objId = tool.generateUid(portalType)
|
objId = tool.generateUid(portalType)
|
||||||
# Determine if object must be created from external data
|
|
||||||
externalData = None
|
|
||||||
if kwargs.has_key('_data'):
|
|
||||||
externalData = kwargs['_data']
|
|
||||||
del kwargs['_data']
|
|
||||||
# Where must I create the object?
|
# Where must I create the object?
|
||||||
if not isField:
|
if not isField:
|
||||||
folder = tool.getPath('/data')
|
folder = tool.getPath('/data')
|
||||||
|
@ -886,17 +892,33 @@ class AbstractWrapper(object):
|
||||||
appyObj = zopeObj.appy()
|
appyObj = zopeObj.appy()
|
||||||
# Set object attributes
|
# Set object attributes
|
||||||
for attrName, attrValue in kwargs.iteritems():
|
for attrName, attrValue in kwargs.iteritems():
|
||||||
setattr(appyObj, attrName, attrValue)
|
try:
|
||||||
|
setattr(appyObj, attrName, attrValue)
|
||||||
|
except AttributeError, ae:
|
||||||
|
if raiseOnWrongAttribute: raise ae
|
||||||
if isField:
|
if isField:
|
||||||
# Link the object to this one
|
# Link the object to this one
|
||||||
appyType.linkObject(self, appyObj)
|
appyType.linkObject(self, appyObj)
|
||||||
# Call custom initialization
|
# Call custom initialization
|
||||||
if externalData: param = externalData
|
if hasattr(appyObj, 'onEdit'): appyObj.onEdit(True)
|
||||||
else: param = True
|
|
||||||
if hasattr(appyObj, 'onEdit'): appyObj.onEdit(param)
|
|
||||||
zopeObj.reindex()
|
zopeObj.reindex()
|
||||||
return appyObj
|
return appyObj
|
||||||
|
|
||||||
|
def createFrom(self, fieldNameOrClass, other, noSecurity=False):
|
||||||
|
'''Similar to m_create above, excepted that we will use another object
|
||||||
|
(p_other) as base for filling in data for the object to create.'''
|
||||||
|
# Get the field values to set from p_other and store it in a dict.
|
||||||
|
# p_other may not be of the same class as p_self.
|
||||||
|
params = {}
|
||||||
|
for field in other.fields:
|
||||||
|
# Skip the added attribute "state"
|
||||||
|
if field.name == 'state': continue
|
||||||
|
# Skip back references.
|
||||||
|
if (field.type == 'Ref') and field.isBack: continue
|
||||||
|
params[field.name] = field.getCopyValue(other.o)
|
||||||
|
return self.create(fieldNameOrClass, noSecurity=noSecurity,
|
||||||
|
raiseOnWrongAttribute=False, **params)
|
||||||
|
|
||||||
def freeze(self, fieldName, template=None, format='pdf', noSecurity=True,
|
def freeze(self, fieldName, template=None, format='pdf', noSecurity=True,
|
||||||
freezeOdtOnError=True):
|
freezeOdtOnError=True):
|
||||||
'''This method freezes the content of pod field named p_fieldName, for
|
'''This method freezes the content of pod field named p_fieldName, for
|
||||||
|
|
Loading…
Reference in a new issue