appy.gen: bugfixes in Ref fields, IE CSS and master/slave relationships.
This commit is contained in:
parent
e821307b4c
commit
4b44f8d565
|
@ -23,11 +23,11 @@ emptyTuple = ()
|
||||||
labelTypes = ('label', 'descr', 'help')
|
labelTypes = ('label', 'descr', 'help')
|
||||||
|
|
||||||
def initMasterValue(v):
|
def initMasterValue(v):
|
||||||
'''Standardizes p_v as a list.'''
|
'''Standardizes p_v as a list of strings.'''
|
||||||
if not v: res = []
|
if not v: res = []
|
||||||
elif type(v) not in sequenceTypes: res = [v]
|
elif type(v) not in sequenceTypes: res = [v]
|
||||||
else: res = v
|
else: res = v
|
||||||
return res
|
return [str(v) for v in res]
|
||||||
|
|
||||||
# Descriptor classes used for refining descriptions of elements in types
|
# Descriptor classes used for refining descriptions of elements in types
|
||||||
# (pages, groups,...) ----------------------------------------------------------
|
# (pages, groups,...) ----------------------------------------------------------
|
||||||
|
@ -1809,6 +1809,43 @@ class Ref(Type):
|
||||||
elif nbOfRefs > maxRef:
|
elif nbOfRefs > maxRef:
|
||||||
return obj.translate('max_ref_violated')
|
return obj.translate('max_ref_violated')
|
||||||
|
|
||||||
|
def linkObject(self, obj, value, back=False):
|
||||||
|
'''This method links p_value (which can be a list of objects) to p_obj
|
||||||
|
through this Ref field.'''
|
||||||
|
# p_value can be a list of objects
|
||||||
|
if type(value) in sequenceTypes:
|
||||||
|
for v in value: self.linkObject(obj, v, back=back)
|
||||||
|
return
|
||||||
|
# Gets the list of referred objects (=list of uids), or create it.
|
||||||
|
obj = obj.o
|
||||||
|
refs = getattr(obj, self.name, None)
|
||||||
|
if refs == None:
|
||||||
|
refs = obj.getProductConfig().PersistentList()
|
||||||
|
setattr(obj, self.name, refs)
|
||||||
|
# Insert p_value into it.
|
||||||
|
uid = value.o.UID()
|
||||||
|
if uid not in refs:
|
||||||
|
refs.append(uid)
|
||||||
|
# Update the back reference
|
||||||
|
if not back: self.back.linkObject(value, obj, back=True)
|
||||||
|
|
||||||
|
def unlinkObject(self, obj, value, back=False):
|
||||||
|
'''This method unlinks p_value (which can be a list of objects) from
|
||||||
|
p_obj through this Ref field.'''
|
||||||
|
# p_value can be a list of objects
|
||||||
|
if type(value) in sequenceTypes:
|
||||||
|
for v in value: self.unlinkObject(obj, v, back=back)
|
||||||
|
return
|
||||||
|
obj = obj.o
|
||||||
|
refs = getattr(obj, self.name, None)
|
||||||
|
if not refs: return
|
||||||
|
# Unlink p_value
|
||||||
|
uid = value.o.UID()
|
||||||
|
if uid in refs:
|
||||||
|
refs.remove(uid)
|
||||||
|
# Update the back reference
|
||||||
|
if not back: self.back.unlinkObject(value, obj, back=True)
|
||||||
|
|
||||||
def store(self, obj, value):
|
def store(self, obj, value):
|
||||||
'''Stores on p_obj, the p_value, which can be:
|
'''Stores on p_obj, the p_value, which can be:
|
||||||
* None;
|
* None;
|
||||||
|
@ -1817,25 +1854,31 @@ class Ref(Type):
|
||||||
of UIDs come from Ref fields with link:True edited through the web;
|
of UIDs come from Ref fields with link:True edited through the web;
|
||||||
* a Zope object;
|
* a Zope object;
|
||||||
* a Appy object;
|
* a Appy object;
|
||||||
* a list of Appy or Zope objects.
|
* a list of Appy or Zope objects.'''
|
||||||
'''
|
# Standardize p_value into a list of Zope objects
|
||||||
# Standardize p_value into a list of uids
|
objects = value
|
||||||
uids = value
|
if not objects: objects = []
|
||||||
if not uids: uids = []
|
if type(objects) not in sequenceTypes: objects = [objects]
|
||||||
if type(uids) not in sequenceTypes: uids = [uids]
|
tool = obj.getTool()
|
||||||
for i in range(len(uids)):
|
for i in range(len(objects)):
|
||||||
if not isinstance(uids[i], basestring):
|
if isinstance(objects[i], basestring):
|
||||||
# Get the UID from the Zope or Appy object
|
# We have a UID here
|
||||||
uids[i] = uids[i].o.UID()
|
objects[i] = tool.getObject(objects[i])
|
||||||
# Update the list of referred uids.
|
else:
|
||||||
|
# Be sure to have a Zope object
|
||||||
|
objects[i] = objects[i].o
|
||||||
|
uids = [o.UID() for o in objects]
|
||||||
|
# Unlink objects that are not referred anymore
|
||||||
refs = getattr(obj, self.name, None)
|
refs = getattr(obj, self.name, None)
|
||||||
if refs == None:
|
if refs:
|
||||||
refs = obj.getProductConfig().PersistentList(uids)
|
i = len(refs)-1
|
||||||
setattr(obj, self.name, refs)
|
while i >= 0:
|
||||||
else:
|
if refs[i] not in uids:
|
||||||
# Empty the list and fill it with uids
|
# Object having this UID must unlink p_obj
|
||||||
del refs[:]
|
self.back.unlinkObject(tool.getObject(refs[i]), obj)
|
||||||
for uid in uids: refs.append(uid)
|
i -= 1
|
||||||
|
# Link new objects
|
||||||
|
self.linkObject(obj, objects)
|
||||||
|
|
||||||
def clone(self, forTool=True):
|
def clone(self, forTool=True):
|
||||||
'''Produces a clone of myself.'''
|
'''Produces a clone of myself.'''
|
||||||
|
|
|
@ -84,7 +84,7 @@ class BaseMixin:
|
||||||
for field in self.getAllAppyTypes():
|
for field in self.getAllAppyTypes():
|
||||||
if field.type != 'Ref': continue
|
if field.type != 'Ref': continue
|
||||||
for obj in field.getValue(self):
|
for obj in field.getValue(self):
|
||||||
obj.unlink(field.back.name, self, back=True)
|
field.back.unlinkObject(obj, self, back=True)
|
||||||
# Delete the object
|
# Delete the object
|
||||||
self.getParentNode().manage_delObjects([self.id])
|
self.getParentNode().manage_delObjects([self.id])
|
||||||
|
|
||||||
|
|
|
@ -10,10 +10,12 @@ p { margin: 0;}
|
||||||
acronym {cursor: help;}
|
acronym {cursor: help;}
|
||||||
input[type=image] { border: 0; background: none; }
|
input[type=image] { border: 0; background: none; }
|
||||||
input[type=checkbox] { border: 0; background: none; cursor: pointer;}
|
input[type=checkbox] { border: 0; background: none; cursor: pointer;}
|
||||||
|
input[type=radio] { border: 0; background: none; cursor: pointer;}
|
||||||
input[type=button] { border: 1px solid #cccccc; background-color: #f8f8f8;
|
input[type=button] { border: 1px solid #cccccc; background-color: #f8f8f8;
|
||||||
cursor: pointer;}
|
cursor: pointer;}
|
||||||
input[type=submit] { border: 1px solid #cccccc; background-color: #f8f8f8;
|
input[type=submit] { border: 1px solid #cccccc; background-color: #f8f8f8;
|
||||||
cursor: pointer; }
|
cursor: pointer; }
|
||||||
|
input[type=password] { border: 1px solid #cccccc; background-color: #f8f8f8;}
|
||||||
input[type=text] { border: 1px solid #cccccc; background-color: #f8f8f8;
|
input[type=text] { border: 1px solid #cccccc; background-color: #f8f8f8;
|
||||||
font-family: Lucida,Helvetica,Arial,sans-serif;
|
font-family: Lucida,Helvetica,Arial,sans-serif;
|
||||||
margin-bottom: 1px}
|
margin-bottom: 1px}
|
||||||
|
@ -48,8 +50,8 @@ img {border: 0;}
|
||||||
.phase { border-style: dashed; border-width: thin; padding: 0 0.6em 0 1em; }
|
.phase { border-style: dashed; border-width: thin; padding: 0 0.6em 0 1em; }
|
||||||
.content { padding: 14px 3px 9px 15px;}
|
.content { padding: 14px 3px 9px 15px;}
|
||||||
.grey { display: none; position: absolute; left: 0px; top: 0px;
|
.grey { display: none; position: absolute; left: 0px; top: 0px;
|
||||||
width:100%; height:100%; background:grey; opacity:0.5;
|
background:grey; opacity:0.5; -moz-opacity:0.5; -khtml-opacity:0.5;
|
||||||
-moz-opacity:0.5; -khtml-opacity:0.5; filter:alpha(Opacity=50);}
|
filter:alpha(Opacity=50);}
|
||||||
.popup { display: none; position: absolute; top: 30%; left: 35%;
|
.popup { display: none; position: absolute; top: 30%; left: 35%;
|
||||||
width: 350px; z-index : 100; background: white; padding: 8px;
|
width: 350px; z-index : 100; background: white; padding: 8px;
|
||||||
border: 1px solid grey; }
|
border: 1px solid grey; }
|
||||||
|
|
|
@ -248,7 +248,11 @@ function getSlaves(master) {
|
||||||
// Gets all the slaves of master.
|
// Gets all the slaves of master.
|
||||||
allSlaves = document.getElementsByName('slave');
|
allSlaves = document.getElementsByName('slave');
|
||||||
res = [];
|
res = [];
|
||||||
slavePrefix = 'slave_' + master.attributes['name'].value + '_';
|
masterName = master.attributes['name'].value;
|
||||||
|
if (master.type == 'checkbox') {
|
||||||
|
masterName = masterName.substr(0, masterName.length-8);
|
||||||
|
}
|
||||||
|
slavePrefix = 'slave_' + masterName + '_';
|
||||||
for (var i=0; i < slaves.length; i++){
|
for (var i=0; i < slaves.length; i++){
|
||||||
cssClasses = slaves[i].className.split(' ');
|
cssClasses = slaves[i].className.split(' ');
|
||||||
for (var j=0; j < cssClasses.length; j++) {
|
for (var j=0; j < cssClasses.length; j++) {
|
||||||
|
@ -381,13 +385,15 @@ function openPopup(popupId, msg) {
|
||||||
// Open the popup
|
// Open the popup
|
||||||
var popup = document.getElementById(popupId);
|
var popup = document.getElementById(popupId);
|
||||||
// Put it at the right place on the screen
|
// Put it at the right place on the screen
|
||||||
var scrollTop = window.pageYOffset || document.documentElement.scrollTop || 0;
|
var scrollTop = document.body.scrollTop || window.pageYOffset || 0;
|
||||||
popup.style.top = (scrollTop + 150) + 'px';
|
popup.style.top = (scrollTop + 150) + 'px';
|
||||||
popup.style.display = "block";
|
popup.style.display = "block";
|
||||||
// Show the greyed zone
|
// Show the greyed zone
|
||||||
var greyed = document.getElementById('grey');
|
var greyed = document.getElementById('grey');
|
||||||
greyed.style.top = scrollTop + 'px';
|
greyed.style.top = scrollTop + 'px';
|
||||||
greyed.style.display = "block";
|
greyed.style.display = "block";
|
||||||
|
greyed.style.height = document.body.clientHeight;
|
||||||
|
greyed.style.width = document.body.clientWidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
function closePopup(popupId) {
|
function closePopup(popupId) {
|
||||||
|
|
|
@ -75,7 +75,7 @@
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<h1 tal:content="python: tool.translate('import_title')"></h1><br/>
|
<h1 tal:content="python: tool.translate('import_title')"></h1><br/>
|
||||||
<table cellpadding="0" cellspacing="0" class="listing nosort" width="100%">
|
<table class="list" width="100%">
|
||||||
<tr>
|
<tr>
|
||||||
<th tal:repeat="columnHeader python: importElems[0]">
|
<th tal:repeat="columnHeader python: importElems[0]">
|
||||||
<img tal:condition="python: repeat['columnHeader'].number() == 1"
|
<img tal:condition="python: repeat['columnHeader'].number() == 1"
|
||||||
|
@ -107,7 +107,7 @@
|
||||||
<span tal:condition="alreadyImported" tal:replace="python: tool.translate('import_already')"/>
|
<span tal:condition="alreadyImported" tal:replace="python: tool.translate('import_already')"/>
|
||||||
</td>
|
</td>
|
||||||
<td align="center">
|
<td align="center">
|
||||||
<input type="checkbox" checked="checked" class="noborder" id="cbElem" name="cbElem"
|
<input type="checkbox" checked="checked" id="cbElem" name="cbElem"
|
||||||
tal:attributes="value python: row[0]" tal:condition="not: alreadyImported"/>
|
tal:attributes="value python: row[0]" tal:condition="not: alreadyImported"/>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
|
@ -7,11 +7,10 @@
|
||||||
<tal:comment replace="nothing">Edit macro for an Boolean.</tal:comment>
|
<tal:comment replace="nothing">Edit macro for an Boolean.</tal:comment>
|
||||||
<metal:edit define-macro="edit">
|
<metal:edit define-macro="edit">
|
||||||
<input type="checkbox"
|
<input type="checkbox"
|
||||||
tal:attributes="name python: name + '_visible';
|
tal:attributes="name python: name + '_visible'; id name;
|
||||||
id name;
|
|
||||||
checked python:contextObj.checkboxChecked(name, rawValue);
|
checked python:contextObj.checkboxChecked(name, rawValue);
|
||||||
onClick python:'toggleCheckbox(\'%s\', \'%s_hidden\');;updateSlaves(this)' % (name, name);
|
onClick python:'toggleCheckbox(\'%s\', \'%s_hidden\');;updateSlaves(this)' % (name, name);
|
||||||
class python: 'noborder %s' % masterCss"/>
|
class masterCss"/>
|
||||||
<input tal:attributes="name name;
|
<input tal:attributes="name name;
|
||||||
id string:${name}_hidden;
|
id string:${name}_hidden;
|
||||||
value python: test(contextObj.checkboxChecked(name, rawValue), 'True', 'False')"
|
value python: test(contextObj.checkboxChecked(name, rawValue), 'True', 'False')"
|
||||||
|
@ -28,15 +27,15 @@
|
||||||
tal:define="typedWidget python:'%s*bool' % widgetName">
|
tal:define="typedWidget python:'%s*bool' % widgetName">
|
||||||
<label tal:attributes="for widgetName" tal:content="python: tool.translate(widget['labelId'])"></label><br>
|
<label tal:attributes="for widgetName" tal:content="python: tool.translate(widget['labelId'])"></label><br>
|
||||||
<tal:yes define="valueId python:'%s_yes' % name">
|
<tal:yes define="valueId python:'%s_yes' % name">
|
||||||
<input type="radio" class="noborder" value="True" tal:attributes="name typedWidget; id valueId"/>
|
<input type="radio" value="True" tal:attributes="name typedWidget; id valueId"/>
|
||||||
<label tal:attributes="for valueId" i18n:translate="yes" i18n:domain="plone"></label>
|
<label tal:attributes="for valueId" i18n:translate="yes" i18n:domain="plone"></label>
|
||||||
</tal:yes>
|
</tal:yes>
|
||||||
<tal:no define="valueId python:'%s_no' % name">
|
<tal:no define="valueId python:'%s_no' % name">
|
||||||
<input type="radio" class="noborder" value="False" tal:attributes="name typedWidget; id valueId"/>
|
<input type="radio" value="False" tal:attributes="name typedWidget; id valueId"/>
|
||||||
<label tal:attributes="for valueId" i18n:translate="no" i18n:domain="plone"></label>
|
<label tal:attributes="for valueId" i18n:translate="no" i18n:domain="plone"></label>
|
||||||
</tal:no>
|
</tal:no>
|
||||||
<tal:whatever define="valueId python:'%s_whatever' % name">
|
<tal:whatever define="valueId python:'%s_whatever' % name">
|
||||||
<input type="radio" class="noborder" value="" tal:attributes="name typedWidget; id valueId" checked="checked"/>
|
<input type="radio" value="" tal:attributes="name typedWidget; id valueId" checked="checked"/>
|
||||||
<label tal:attributes="for valueId" tal:content="python: tool.translate('whatever')"></label>
|
<label tal:attributes="for valueId" tal:content="python: tool.translate('whatever')"></label>
|
||||||
</tal:whatever><br/>
|
</tal:whatever><br/>
|
||||||
</metal:search>
|
</metal:search>
|
||||||
|
|
|
@ -81,7 +81,7 @@
|
||||||
<metal:search define-macro="search"
|
<metal:search define-macro="search"
|
||||||
tal:define="years python:range(widget['startYear'], widget['endYear']+1)">
|
tal:define="years python:range(widget['startYear'], widget['endYear']+1)">
|
||||||
<label tal:content="python: tool.translate(widget['labelId'])"></label>
|
<label tal:content="python: tool.translate(widget['labelId'])"></label>
|
||||||
<table cellpadding="0" cellspacing="0">
|
<table>
|
||||||
<tal:comment replace="nothing">From</tal:comment>
|
<tal:comment replace="nothing">From</tal:comment>
|
||||||
<tr tal:define="yearFromName python: '%s*date' % widgetName;
|
<tr tal:define="yearFromName python: '%s*date' % widgetName;
|
||||||
monthFromName python: '%s_from_month' % name;
|
monthFromName python: '%s_from_month' % name;
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
</tal:showFile>
|
</tal:showFile>
|
||||||
<tal:editButtons condition="python: value and value.size">
|
<tal:editButtons condition="python: value and value.size">
|
||||||
<tal:comment replace="nothing">Keep the file untouched.</tal:comment>
|
<tal:comment replace="nothing">Keep the file untouched.</tal:comment>
|
||||||
<input class="noborder" type="radio" value="nochange"
|
<input type="radio" value="nochange"
|
||||||
tal:attributes="checked python:test(value.size!=0, 'checked', None);
|
tal:attributes="checked python:test(value.size!=0, 'checked', None);
|
||||||
name string:${name}_delete;
|
name string:${name}_delete;
|
||||||
id string:${name}_nochange;
|
id string:${name}_nochange;
|
||||||
|
@ -33,7 +33,7 @@
|
||||||
<br/>
|
<br/>
|
||||||
<tal:comment replace="nothing">Delete the file.</tal:comment>
|
<tal:comment replace="nothing">Delete the file.</tal:comment>
|
||||||
<tal:delete condition="not: widget/required">
|
<tal:delete condition="not: widget/required">
|
||||||
<input class="noborder" type="radio" value="delete"
|
<input type="radio" value="delete"
|
||||||
tal:attributes="name string:${name}_delete;
|
tal:attributes="name string:${name}_delete;
|
||||||
id string:${name}_delete;
|
id string:${name}_delete;
|
||||||
onclick string:document.getElementById('${name}_file').disabled=true;"/>
|
onclick string:document.getElementById('${name}_file').disabled=true;"/>
|
||||||
|
@ -42,7 +42,7 @@
|
||||||
<br/>
|
<br/>
|
||||||
</tal:delete>
|
</tal:delete>
|
||||||
<tal:comment replace="nothing">Replace with a new file.</tal:comment>
|
<tal:comment replace="nothing">Replace with a new file.</tal:comment>
|
||||||
<input class="noborder" type="radio" value=""
|
<input type="radio" value=""
|
||||||
tal:attributes="checked python:test(value.size==0, 'checked', None);
|
tal:attributes="checked python:test(value.size==0, 'checked', None);
|
||||||
name string:${name}_delete;
|
name string:${name}_delete;
|
||||||
id string:${name}_upload;
|
id string:${name}_upload;
|
||||||
|
|
|
@ -101,7 +101,7 @@
|
||||||
id slaveId; name slaveId">
|
id slaveId; name slaveId">
|
||||||
<tal:comment replace="nothing">First row: the tabs.</tal:comment>
|
<tal:comment replace="nothing">First row: the tabs.</tal:comment>
|
||||||
<tr valign="middle"><td style="border-bottom: 1px solid #ff8040">
|
<tr valign="middle"><td style="border-bottom: 1px solid #ff8040">
|
||||||
<table cellpadding="0" cellspacing="0" style="position:relative; bottom:-1px;">
|
<table style="position:relative; bottom:-1px;">
|
||||||
<tr valign="middle">
|
<tr valign="middle">
|
||||||
<tal:tab repeat="widgetRow widget/widgets">
|
<tal:tab repeat="widgetRow widget/widgets">
|
||||||
<tal:id define="tabId python:'tab_%s_%d_%d' % (widget['name'], repeat['widgetRow'].number(), len(widget['widgets']))">
|
<tal:id define="tabId python:'tab_%s_%d_%d' % (widget['name'], repeat['widgetRow'].number(), len(widget['widgets']))">
|
||||||
|
|
|
@ -90,9 +90,9 @@
|
||||||
orName python: '%s_or' % operName;
|
orName python: '%s_or' % operName;
|
||||||
andName python: '%s_and' % operName;"
|
andName python: '%s_and' % operName;"
|
||||||
condition="python: widget['multiplicity'][1]!=1">
|
condition="python: widget['multiplicity'][1]!=1">
|
||||||
<input type="radio" class="noborder" tal:attributes="name operName; id orName" checked="checked" value="or"/>
|
<input type="radio" tal:attributes="name operName; id orName" checked="checked" value="or"/>
|
||||||
<label tal:attributes="for orName" tal:content="python: tool.translate('search_or')"></label>
|
<label tal:attributes="for orName" tal:content="python: tool.translate('search_or')"></label>
|
||||||
<input type="radio" class="noborder" tal:attributes="name operName; id andName" value="and"/>
|
<input type="radio" tal:attributes="name operName; id andName" value="and"/>
|
||||||
<label tal:attributes="for andName" tal:content="python: tool.translate('search_and')"></label><br/>
|
<label tal:attributes="for andName" tal:content="python: tool.translate('search_and')"></label><br/>
|
||||||
</tal:operator>
|
</tal:operator>
|
||||||
<tal:comment replace="nothing">The list of values</tal:comment>
|
<tal:comment replace="nothing">The list of values</tal:comment>
|
||||||
|
|
|
@ -86,53 +86,15 @@ class AbstractWrapper(object):
|
||||||
|
|
||||||
def getField(self, name): return self.o.getAppyType(name)
|
def getField(self, name): return self.o.getAppyType(name)
|
||||||
|
|
||||||
def link(self, fieldName, obj, back=False):
|
def link(self, fieldName, obj):
|
||||||
'''This method links p_obj (which can be a list of objects) to this one
|
'''This method links p_obj (which can be a list of objects) to this one
|
||||||
through reference field p_fieldName. As this method is recursive and
|
through reference field p_fieldName.'''
|
||||||
can be called to update the corresponding back reference, param
|
return self.getField(fieldName).linkObject(self.o, obj)
|
||||||
p_back is there, but, you, as Appy developer, should never set it
|
|
||||||
to True.'''
|
|
||||||
# p_objs can be a list of objects
|
|
||||||
if type(obj) in sequenceTypes:
|
|
||||||
for o in obj: self.link(fieldName, o, back=back)
|
|
||||||
return
|
|
||||||
# Gets the list of referred objects (=list of uids), or create it.
|
|
||||||
selfO = self.o
|
|
||||||
refs = getattr(selfO, fieldName, None)
|
|
||||||
if refs == None:
|
|
||||||
refs = selfO.getProductConfig().PersistentList()
|
|
||||||
setattr(selfO, fieldName, refs)
|
|
||||||
# Insert p_obj into it.
|
|
||||||
uid = obj.o.UID()
|
|
||||||
if uid not in refs:
|
|
||||||
refs.append(uid)
|
|
||||||
# Update the back reference
|
|
||||||
if not back:
|
|
||||||
backName = selfO.getAppyType(fieldName).back.attribute
|
|
||||||
obj.appy().link(backName, self, back=True)
|
|
||||||
|
|
||||||
def unlink(self, fieldName, obj, back=False):
|
def unlink(self, fieldName, obj):
|
||||||
'''This method unlinks p_obj (which can be a list of objects) from this
|
'''This method unlinks p_obj (which can be a list of objects) from this
|
||||||
one through reference field p_fieldName. As this method is recursive
|
one through reference field p_fieldName.'''
|
||||||
and can be called to update the corresponding back reference, param
|
return self.getField(fieldName).unlinkObject(self.o, obj)
|
||||||
p_back is there, but, you, as Appy developer, should never set it
|
|
||||||
to True.'''
|
|
||||||
# p_objs can be a list of objects
|
|
||||||
if type(obj) in sequenceTypes:
|
|
||||||
for o in obj: self.unlink(fieldName, o, back=back)
|
|
||||||
return
|
|
||||||
# Get the list of referred objects
|
|
||||||
selfO = self.o
|
|
||||||
refs = getattr(selfO, fieldName, None)
|
|
||||||
if not refs: return
|
|
||||||
# Unlink the object
|
|
||||||
uid = obj.o.UID()
|
|
||||||
if uid in refs:
|
|
||||||
refs.remove(uid)
|
|
||||||
# Update the back reference
|
|
||||||
if not back:
|
|
||||||
backName = selfO.getAppyType(fieldName).back.attribute
|
|
||||||
obj.appy().unlink(backName, self, back=True)
|
|
||||||
|
|
||||||
def sort(self, fieldName, sortKey='title', reverse=False):
|
def sort(self, fieldName, sortKey='title', reverse=False):
|
||||||
'''Sorts referred elements linked to p_self via p_fieldName according
|
'''Sorts referred elements linked to p_self via p_fieldName according
|
||||||
|
@ -194,8 +156,7 @@ class AbstractWrapper(object):
|
||||||
setattr(appyObj, attrName, attrValue)
|
setattr(appyObj, attrName, attrValue)
|
||||||
if isField:
|
if isField:
|
||||||
# Link the object to this one
|
# Link the object to this one
|
||||||
self.link(fieldName, ploneObj)
|
appyType.linkObject(self.o, ploneObj)
|
||||||
self.o.reindexObject()
|
|
||||||
# Call custom initialization
|
# Call custom initialization
|
||||||
if externalData: param = externalData
|
if externalData: param = externalData
|
||||||
else: param = True
|
else: param = True
|
||||||
|
|
Loading…
Reference in a new issue