[gen] Added param Field.mustIndex, that, for indexed fields, defines (via a method) when indexation must occur or not. Indeed, in some cases, an index is required on some field but we don't want all objects to have an index value for this field at any time.

This commit is contained in:
Gaetan Delannay 2014-12-26 17:29:14 +01:00
parent 4461cbb9a8
commit 8591611aac
16 changed files with 134 additions and 110 deletions

View file

@ -138,10 +138,11 @@ class Field:
</x>''') </x>''')
def __init__(self, validator, multiplicity, default, show, page, group, def __init__(self, validator, multiplicity, default, show, page, group,
layouts, move, indexed, searchable, specificReadPermission, layouts, move, indexed, mustIndex, searchable,
specificWritePermission, width, height, maxChars, colspan, specificReadPermission, specificWritePermission, width, height,
master, masterValue, focus, historized, mapping, label, maxChars, colspan, master, masterValue, focus, historized,
sdefault, scolspan, swidth, sheight, persist, view, xml): mapping, label, sdefault, scolspan, swidth, sheight, persist,
view, xml):
# The validator restricts which values may be defined. It can be an # The validator restricts which values may be defined. It can be an
# interval (1,None), a list of string values ['choice1', 'choice2'], # interval (1,None), a list of string values ['choice1', 'choice2'],
# a regular expression, a custom function, a Selection instance, etc. # a regular expression, a custom function, a Selection instance, etc.
@ -167,6 +168,12 @@ class Field:
# If indexed is True, a database index will be set on the field for # If indexed is True, a database index will be set on the field for
# fast access. # fast access.
self.indexed = indexed self.indexed = indexed
# If "mustIndex", True by default, is specified, it must be a method
# returning a boolean value. Indexation will only occur when this value
# is True.
self.mustIndex = mustIndex
if not mustIndex and not callable(mustIndex):
raise Exception('Value for param "mustIndex" must be a method.')
# If specified "searchable", the field will be added to some global # If specified "searchable", the field will be added to some global
# index allowing to perform application-wide, keyword searches. # index allowing to perform application-wide, keyword searches.
self.searchable = searchable self.searchable = searchable
@ -605,6 +612,9 @@ class Field:
If p_forSearch is True, it will return a "string" version of the If p_forSearch is True, it will return a "string" version of the
index value suitable for a global search.''' index value suitable for a global search.'''
# Must we produce an index value?
if not self.getAttribute(obj, 'mustIndex'): return
# Start by getting the field value on p_obj
res = self.getValue(obj) res = self.getValue(obj)
# Zope catalog does not like unicode strings # Zope catalog does not like unicode strings
if isinstance(res, unicode): res = res.encode('utf-8') if isinstance(res, unicode): res = res.encode('utf-8')

View file

@ -54,12 +54,12 @@ class Action(Field):
def __init__(self, validator=None, multiplicity=(1,1), default=None, def __init__(self, validator=None, multiplicity=(1,1), default=None,
show=('view', 'result'), page='main', group=None, layouts=None, show=('view', 'result'), page='main', group=None, layouts=None,
move=0, indexed=False, searchable=False, move=0, specificReadPermission=False,
specificReadPermission=False, specificWritePermission=False, specificWritePermission=False, width=None, height=None,
width=None, height=None, maxChars=None, colspan=1, action=None, maxChars=None, colspan=1, action=None, result='computation',
result='computation', confirm=False, master=None, confirm=False, master=None, masterValue=None, focus=False,
masterValue=None, focus=False, historized=False, mapping=None, historized=False, mapping=None, label=None, icon=None,
label=None, icon=None, view=None, xml=None): view=None, xml=None):
# Can be a single method or a list/tuple of methods # Can be a single method or a list/tuple of methods
self.action = action self.action = action
# For the 'result' param: # For the 'result' param:
@ -77,7 +77,7 @@ class Action(Field):
# If no p_icon is specified, "action.png" will be used # If no p_icon is specified, "action.png" will be used
self.icon = icon or 'action' self.icon = icon or 'action'
Field.__init__(self, None, (0,1), default, show, page, group, layouts, Field.__init__(self, None, (0,1), default, show, page, group, layouts,
move, indexed, False, specificReadPermission, move, False, True, False, specificReadPermission,
specificWritePermission, width, height, None, colspan, specificWritePermission, width, height, None, colspan,
master, masterValue, focus, historized, mapping, label, master, masterValue, focus, historized, mapping, label,
None, None, None, None, False, view, xml) None, None, None, None, False, view, xml)

View file

@ -79,17 +79,18 @@ class Boolean(Field):
def __init__(self, validator=None, multiplicity=(0,1), default=None, def __init__(self, validator=None, multiplicity=(0,1), default=None,
show=True, page='main', group=None, layouts = None, move=0, show=True, page='main', group=None, layouts = None, move=0,
indexed=False, searchable=False, specificReadPermission=False, indexed=False, mustIndex=True, searchable=False,
specificWritePermission=False, width=None, height=None, specificReadPermission=False, specificWritePermission=False,
maxChars=None, colspan=1, master=None, masterValue=None, width=None, height=None, maxChars=None, colspan=1, master=None,
focus=False, historized=False, mapping=None, label=None, masterValue=None, focus=False, historized=False, mapping=None,
sdefault=False, scolspan=1, swidth=None, sheight=None, label=None, sdefault=False, scolspan=1, swidth=None,
persist=True, render='checkbox', view=None, xml=None): sheight=None, persist=True, render='checkbox', view=None,
xml=None):
# By default, a boolean is edited via a checkbox. It can also be edited # By default, a boolean is edited via a checkbox. It can also be edited
# via 2 radio buttons (p_render="radios"). # via 2 radio buttons (p_render="radios").
self.render = render self.render = render
Field.__init__(self, validator, multiplicity, default, show, page, Field.__init__(self, validator, multiplicity, default, show, page,
group, layouts, move, indexed, searchable, group, layouts, move, indexed, mustIndex, searchable,
specificReadPermission, specificWritePermission, width, specificReadPermission, specificWritePermission, width,
height, None, colspan, master, masterValue, focus, height, None, colspan, master, masterValue, focus,
historized, mapping, label, sdefault, scolspan, swidth, historized, mapping, label, sdefault, scolspan, swidth,

View file

@ -219,7 +219,7 @@ class Calendar(Field):
endDate=None, defaultDate=None, preCompute=None, endDate=None, defaultDate=None, preCompute=None,
applicableEvents=None, view=None, xml=None): applicableEvents=None, view=None, xml=None):
Field.__init__(self, validator, (0,1), default, show, page, group, Field.__init__(self, validator, (0,1), default, show, page, group,
layouts, move, False, False, specificReadPermission, layouts, move, False, True, False, specificReadPermission,
specificWritePermission, width, height, None, colspan, specificWritePermission, width, height, None, colspan,
master, masterValue, focus, False, mapping, label, None, master, masterValue, focus, False, mapping, label, None,
None, None, None, True, view, xml) None, None, None, True, view, xml)

View file

@ -32,13 +32,13 @@ class Computed(Field):
def __init__(self, validator=None, multiplicity=(0,1), default=None, def __init__(self, validator=None, multiplicity=(0,1), default=None,
show=None, page='main', group=None, layouts=None, move=0, show=None, page='main', group=None, layouts=None, move=0,
indexed=False, searchable=False, specificReadPermission=False, indexed=False, mustIndex=True, searchable=False,
specificWritePermission=False, width=None, height=None, specificReadPermission=False, specificWritePermission=False,
maxChars=None, colspan=1, method=None, formatMethod=None, width=None, height=None, maxChars=None, colspan=1, method=None,
plainText=False, master=None, masterValue=None, focus=False, formatMethod=None, plainText=False, master=None,
historized=False, mapping=None, label=None, sdefault='', masterValue=None, focus=False, historized=False, mapping=None,
scolspan=1, swidth=None, sheight=None, context=None, view=None, label=None, sdefault='', scolspan=1, swidth=None, sheight=None,
xml=None): context=None, view=None, xml=None):
# The Python method used for computing the field value, or a PX. # The Python method used for computing the field value, or a PX.
self.method = method self.method = method
# A specific method for producing the formatted value of this field. # A specific method for producing the formatted value of this field.
@ -65,7 +65,7 @@ class Computed(Field):
# If method is a PX, its context can be given in p_context. # If method is a PX, its context can be given in p_context.
self.context = context self.context = context
Field.__init__(self, None, multiplicity, default, show, page, group, Field.__init__(self, None, multiplicity, default, show, page, group,
layouts, move, indexed, searchable, layouts, move, indexed, mustIndex, searchable,
specificReadPermission, specificWritePermission, width, specificReadPermission, specificWritePermission, width,
height, None, colspan, master, masterValue, focus, height, None, colspan, master, masterValue, focus,
historized, mapping, label, sdefault, scolspan, swidth, historized, mapping, label, sdefault, scolspan, swidth,

View file

@ -165,12 +165,12 @@ class Date(Field):
startYear=time.localtime()[0]-10, startYear=time.localtime()[0]-10,
endYear=time.localtime()[0]+10, reverseYears=False, endYear=time.localtime()[0]+10, reverseYears=False,
show=True, page='main', group=None, layouts=None, move=0, show=True, page='main', group=None, layouts=None, move=0,
indexed=False, searchable=False, specificReadPermission=False, indexed=False, mustIndex=True, searchable=False,
specificWritePermission=False, width=None, height=None, specificReadPermission=False, specificWritePermission=False,
maxChars=None, colspan=1, master=None, masterValue=None, width=None, height=None, maxChars=None, colspan=1, master=None,
focus=False, historized=False, mapping=None, label=None, masterValue=None, focus=False, historized=False, mapping=None,
sdefault=None, scolspan=1, swidth=None, sheight=None, label=None, sdefault=None, scolspan=1, swidth=None,
persist=True, view=None, xml=None): sheight=None, persist=True, view=None, xml=None):
self.format = format self.format = format
self.calendar = calendar self.calendar = calendar
self.startYear = startYear self.startYear = startYear
@ -179,7 +179,7 @@ class Date(Field):
# self.startYear to self.endYear will be listed in reverse order. # self.startYear to self.endYear will be listed in reverse order.
self.reverseYears = reverseYears self.reverseYears = reverseYears
Field.__init__(self, validator, multiplicity, default, show, page, Field.__init__(self, validator, multiplicity, default, show, page,
group, layouts, move, indexed, searchable, group, layouts, move, indexed, mustIndex, searchable,
specificReadPermission, specificWritePermission, width, specificReadPermission, specificWritePermission, width,
height, None, colspan, master, masterValue, focus, height, None, colspan, master, masterValue, focus,
historized, mapping, label, sdefault, scolspan, swidth, historized, mapping, label, sdefault, scolspan, swidth,

View file

@ -344,15 +344,14 @@ class File(Field):
def __init__(self, validator=None, multiplicity=(0,1), default=None, def __init__(self, validator=None, multiplicity=(0,1), default=None,
show=True, page='main', group=None, layouts=None, move=0, show=True, page='main', group=None, layouts=None, move=0,
indexed=False, searchable=False, specificReadPermission=False, specificReadPermission=False, specificWritePermission=False,
specificWritePermission=False, width=None, height=None, width=None, height=None, maxChars=None, colspan=1, master=None,
maxChars=None, colspan=1, master=None, masterValue=None, masterValue=None, focus=False, historized=False, mapping=None,
focus=False, historized=False, mapping=None, label=None, label=None, isImage=False, sdefault='', scolspan=1,
isImage=False, sdefault='', scolspan=1, swidth=None, swidth=None, sheight=None, view=None, xml=None):
sheight=None, view=None, xml=None):
self.isImage = isImage self.isImage = isImage
Field.__init__(self, validator, multiplicity, default, show, page, Field.__init__(self, validator, multiplicity, default, show, page,
group, layouts, move, indexed, False, group, layouts, move, False, True, False,
specificReadPermission, specificWritePermission, width, specificReadPermission, specificWritePermission, width,
height, None, colspan, master, masterValue, focus, height, None, colspan, master, masterValue, focus,
historized, mapping, label, sdefault, scolspan, swidth, historized, mapping, label, sdefault, scolspan, swidth,

View file

@ -51,13 +51,13 @@ class Float(Field):
def __init__(self, validator=None, multiplicity=(0,1), default=None, def __init__(self, validator=None, multiplicity=(0,1), default=None,
show=True, page='main', group=None, layouts=None, move=0, show=True, page='main', group=None, layouts=None, move=0,
indexed=False, searchable=False, specificReadPermission=False, indexed=False, mustIndex=True, searchable=False,
specificWritePermission=False, width=5, height=None, specificReadPermission=False, specificWritePermission=False,
maxChars=13, colspan=1, master=None, masterValue=None, width=5, height=None, maxChars=13, colspan=1, master=None,
focus=False, historized=False, mapping=None, label=None, masterValue=None, focus=False, historized=False, mapping=None,
sdefault=('',''), scolspan=1, swidth=None, sheight=None, label=None, sdefault=('',''), scolspan=1, swidth=None,
persist=True, precision=None, sep=(',', '.'), tsep=' ', sheight=None, persist=True, precision=None, sep=(',', '.'),
view=None, xml=None): tsep=' ', view=None, xml=None):
# The precision is the number of decimal digits. This number is used # The precision is the number of decimal digits. This number is used
# for rendering the float, but the internal float representation is not # for rendering the float, but the internal float representation is not
# rounded. # rounded.
@ -75,7 +75,7 @@ class Float(Field):
'separator.' % sep) 'separator.' % sep)
self.tsep = tsep self.tsep = tsep
Field.__init__(self, validator, multiplicity, default, show, page, Field.__init__(self, validator, multiplicity, default, show, page,
group, layouts, move, indexed, False, group, layouts, move, indexed, mustIndex, searchable,
specificReadPermission, specificWritePermission, width, specificReadPermission, specificWritePermission, width,
height, maxChars, colspan, master, masterValue, focus, height, maxChars, colspan, master, masterValue, focus,
historized, mapping, label, sdefault, scolspan, swidth, historized, mapping, label, sdefault, scolspan, swidth,

View file

@ -26,13 +26,12 @@ class Info(Field):
def __init__(self, validator=None, multiplicity=(1,1), default=None, def __init__(self, validator=None, multiplicity=(1,1), default=None,
show='view', page='main', group=None, layouts=None, move=0, show='view', page='main', group=None, layouts=None, move=0,
indexed=False, searchable=False, specificReadPermission=False, specificReadPermission=False, specificWritePermission=False,
specificWritePermission=False, width=None, height=None, width=None, height=None, maxChars=None, colspan=1, master=None,
maxChars=None, colspan=1, master=None, masterValue=None, masterValue=None, focus=False, historized=False, mapping=None,
focus=False, historized=False, mapping=None, label=None, label=None, view=None, xml=None):
view=None, xml=None):
Field.__init__(self, None, (0,1), default, show, page, group, layouts, Field.__init__(self, None, (0,1), default, show, page, group, layouts,
move, indexed, False, specificReadPermission, move, False, True, False, specificReadPermission,
specificWritePermission, width, height, None, colspan, specificWritePermission, width, height, None, colspan,
master, masterValue, focus, historized, mapping, label, master, masterValue, focus, historized, mapping, label,
None, None, None, None, False, view, xml) None, None, None, None, False, view, xml)

View file

@ -48,14 +48,14 @@ class Integer(Field):
def __init__(self, validator=None, multiplicity=(0,1), default=None, def __init__(self, validator=None, multiplicity=(0,1), default=None,
show=True, page='main', group=None, layouts=None, move=0, show=True, page='main', group=None, layouts=None, move=0,
indexed=False, searchable=False, specificReadPermission=False, indexed=False, mustIndex=True, searchable=False,
specificWritePermission=False, width=5, height=None, specificReadPermission=False, specificWritePermission=False,
maxChars=13, colspan=1, master=None, masterValue=None, width=5, height=None, maxChars=13, colspan=1, master=None,
focus=False, historized=False, mapping=None, label=None, masterValue=None, focus=False, historized=False, mapping=None,
sdefault=('',''), scolspan=1, swidth=None, sheight=None, label=None, sdefault=('',''), scolspan=1, swidth=None,
persist=True, view=None, xml=None): sheight=None, persist=True, view=None, xml=None):
Field.__init__(self, validator, multiplicity, default, show, page, Field.__init__(self, validator, multiplicity, default, show, page,
group, layouts, move, indexed, searchable, group, layouts, move, indexed, mustIndex, searchable,
specificReadPermission, specificWritePermission, width, specificReadPermission, specificWritePermission, width,
height, maxChars, colspan, master, masterValue, focus, height, maxChars, colspan, master, masterValue, focus,
historized, mapping, label, sdefault, scolspan, swidth, historized, mapping, label, sdefault, scolspan, swidth,

View file

@ -74,14 +74,13 @@ class List(Field):
def __init__(self, fields, validator=None, multiplicity=(0,1), default=None, def __init__(self, fields, validator=None, multiplicity=(0,1), default=None,
show=True, page='main', group=None, layouts=None, move=0, show=True, page='main', group=None, layouts=None, move=0,
indexed=False, searchable=False, specificReadPermission=False, specificReadPermission=False, specificWritePermission=False,
specificWritePermission=False, width='', height=None, width='', height=None, maxChars=None, colspan=1, master=None,
maxChars=None, colspan=1, master=None, masterValue=None, masterValue=None, focus=False, historized=False, mapping=None,
focus=False, historized=False, mapping=None, label=None, label=None, subLayouts=Table('frv', width=None), widths=None,
subLayouts=Table('frv', width=None), widths=None, view=None, view=None, xml=None):
xml=None):
Field.__init__(self, validator, multiplicity, default, show, page, Field.__init__(self, validator, multiplicity, default, show, page,
group, layouts, move, indexed, False, group, layouts, move, False, True, False,
specificReadPermission, specificWritePermission, width, specificReadPermission, specificWritePermission, width,
height, None, colspan, master, masterValue, focus, height, None, colspan, master, masterValue, focus,
historized, mapping, label, None, None, None, None, historized, mapping, label, None, None, None, None,

View file

@ -51,7 +51,7 @@ class Ogone(Field):
colspan=1, master=None, masterValue=None, focus=False, colspan=1, master=None, masterValue=None, focus=False,
mapping=None, label=None, view=None, xml=None): mapping=None, label=None, view=None, xml=None):
Field.__init__(self, None, (0,1), None, show, page, group, layouts, Field.__init__(self, None, (0,1), None, show, page, group, layouts,
move, False, False,specificReadPermission, move, False, True, False,specificReadPermission,
specificWritePermission, width, height, None, colspan, specificWritePermission, width, height, None, colspan,
master, masterValue, focus, False, mapping, label, None, master, masterValue, focus, False, mapping, label, None,
None, None, None, False, view, xml) None, None, None, False, view, xml)

View file

@ -150,16 +150,15 @@ class Pod(Field):
pxEdit = pxSearch = '' pxEdit = pxSearch = ''
def __init__(self, validator=None, default=None, show=('view', 'result'), def __init__(self, validator=None, default=None, show=('view', 'result'),
page='main', group=None, layouts=None, move=0, indexed=False, page='main', group=None, layouts=None, move=0,
searchable=False, specificReadPermission=False, specificReadPermission=False, specificWritePermission=False,
specificWritePermission=False, width=None, height=None, width=None, height=None, maxChars=None, colspan=1, master=None,
maxChars=None, colspan=1, master=None, masterValue=None, masterValue=None, focus=False, historized=False, mapping=None,
focus=False, historized=False, mapping=None, label=None, label=None, template=None, templateName=None,
template=None, templateName=None, showTemplate=None, showTemplate=None, freezeTemplate=None, maxPerRow=5,
freezeTemplate=None, maxPerRow=5, context=None, context=None, stylesMapping={}, formats=None, getChecked=None,
stylesMapping={}, formats=None, getChecked=None, mailing=None, mailing=None, mailingName=None, showMailing=None,
mailingName=None, showMailing=None, mailingInfo=None, mailingInfo=None, view=None, xml=None):
view=None, xml=None):
# Param "template" stores the path to the pod template(s). If there is # 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 # a single template, a string is expected. Else, a list or tuple of
# strings is expected. Every such path must be relative to your # strings is expected. Every such path must be relative to your
@ -273,7 +272,7 @@ class Pod(Field):
# self.mailing) and that returns an instance of class Mailing (above). # self.mailing) and that returns an instance of class Mailing (above).
self.mailingInfo = mailingInfo self.mailingInfo = mailingInfo
Field.__init__(self, None, (0,1), default, show, page, group, layouts, Field.__init__(self, None, (0,1), default, show, page, group, layouts,
move, indexed, searchable, specificReadPermission, move, False, True, False, specificReadPermission,
specificWritePermission, width, height, None, colspan, specificWritePermission, width, height, None, colspan,
master, masterValue, focus, historized, mapping, label, master, masterValue, focus, historized, mapping, label,
None, None, None, None, True, view, xml) None, None, None, None, True, view, xml)

View file

@ -519,11 +519,11 @@ class Ref(Field):
afterLink=None, afterUnlink=None, back=None, show=True, afterLink=None, afterUnlink=None, back=None, show=True,
page='main', group=None, layouts=None, showHeaders=False, page='main', group=None, layouts=None, showHeaders=False,
shownInfo=None, select=None, maxPerPage=30, move=0, shownInfo=None, select=None, maxPerPage=30, move=0,
indexed=False, searchable=False, specificReadPermission=False, indexed=False, mustIndex=True, searchable=False,
specificWritePermission=False, width=None, height=5, specificReadPermission=False, specificWritePermission=False,
maxChars=None, colspan=1, master=None, masterValue=None, width=None, height=5, maxChars=None, colspan=1, master=None,
focus=False, historized=False, mapping=None, label=None, masterValue=None, focus=False, historized=False, mapping=None,
queryable=False, queryFields=None, queryNbCols=1, label=None, queryable=False, queryFields=None, queryNbCols=1,
navigable=False, changeOrder=True, numbered=False, navigable=False, changeOrder=True, numbered=False,
checkboxes=True, checkboxesDefault=None, sdefault='', checkboxes=True, checkboxesDefault=None, sdefault='',
scolspan=1, swidth=None, sheight=None, sselect=None, scolspan=1, swidth=None, sheight=None, sselect=None,
@ -710,7 +710,7 @@ class Ref(Field):
# alternative URL for the tied object that is shown within the menu. # alternative URL for the tied object that is shown within the menu.
self.menuUrlMethod = menuUrlMethod self.menuUrlMethod = menuUrlMethod
Field.__init__(self, validator, multiplicity, default, show, page, Field.__init__(self, validator, multiplicity, default, show, page,
group, layouts, move, indexed, False, group, layouts, move, indexed, mustIndex, searchable,
specificReadPermission, specificWritePermission, width, specificReadPermission, specificWritePermission, width,
height, None, colspan, master, masterValue, focus, height, None, colspan, master, masterValue, focus,
historized, mapping, label, sdefault, scolspan, swidth, historized, mapping, label, sdefault, scolspan, swidth,
@ -958,22 +958,29 @@ class Ref(Field):
def getIndexType(self): return 'ListIndex' def getIndexType(self): return 'ListIndex'
def getValidCatalogValue(self, value):
'''p_value is the new value we want to index in the catalog, for this
field, for some object. p_value as is may not be an acceptable value
for the catalog: if it it an empty list, instead of using it, the
catalog will keep the previously catalogued value! For this case,
this method produces an "empty" value that will really overwrite the
previous one. Moreover, the catalog does not like persistent
lists.'''
# The index does not like persistent lists. Moreover, I don't want to
# give to anyone access to the persistent list in the DB.
if value: return list(value)
# Ugly catalog: if I return an empty list, the previous value is kept
return ['']
def getIndexValue(self, obj, forSearch=False): def getIndexValue(self, obj, forSearch=False):
'''Value for indexing is the list of UIDs of linked objects. If '''Value for indexing is the list of UIDs of linked objects. If
p_forSearch is True, it will return a list of the linked objects' p_forSearch is True, it will return a list of the linked objects'
titles instead.''' titles instead.'''
# Must we produce an index value?
if not self.getAttribute(obj, 'mustIndex'): return
if not forSearch: if not forSearch:
res = getattr(obj.aq_base, self.name, None) res = getattr(obj.aq_base, self.name, None)
if res: return self.getValidCatalogValue(res)
# The index does not like persistent lists. Moreover, I don't
# want to give to anyone access to the persistent list in the
# DB.
res = list(res)
else:
# Ugly catalog: if I return an empty list, the previous value
# is kept.
res = ['']
return res
else: else:
# For the global search: return linked objects' titles # For the global search: return linked objects' titles
return ' '.join([o.getShownValue('title') \ return ' '.join([o.getShownValue('title') \

View file

@ -373,7 +373,7 @@ class String(Field):
def __init__(self, validator=None, multiplicity=(0,1), default=None, def __init__(self, validator=None, multiplicity=(0,1), default=None,
format=LINE, show=True, page='main', group=None, layouts=None, format=LINE, show=True, page='main', group=None, layouts=None,
move=0, indexed=False, searchable=False, move=0, indexed=False, mustIndex=True, searchable=False,
specificReadPermission=False, specificWritePermission=False, specificReadPermission=False, specificWritePermission=False,
width=None, height=None, maxChars=None, colspan=1, master=None, width=None, height=None, maxChars=None, colspan=1, master=None,
masterValue=None, focus=False, historized=False, mapping=None, masterValue=None, focus=False, historized=False, mapping=None,
@ -421,7 +421,7 @@ class String(Field):
# that can, for example, return an internationalized value. # that can, for example, return an internationalized value.
self.placeholder = placeholder self.placeholder = placeholder
Field.__init__(self, validator, multiplicity, default, show, page, Field.__init__(self, validator, multiplicity, default, show, page,
group, layouts, move, indexed, searchable, group, layouts, move, indexed, mustIndex, searchable,
specificReadPermission, specificWritePermission, width, specificReadPermission, specificWritePermission, width,
height, maxChars, colspan, master, masterValue, focus, height, maxChars, colspan, master, masterValue, focus,
historized, mapping, label, sdefault, scolspan, swidth, historized, mapping, label, sdefault, scolspan, swidth,
@ -684,12 +684,29 @@ class String(Field):
'''Extracts pure text from XHTML p_value.''' '''Extracts pure text from XHTML p_value.'''
return XhtmlTextExtractor(raiseOnError=False).parse('<p>%s</p>' % value) return XhtmlTextExtractor(raiseOnError=False).parse('<p>%s</p>' % value)
emptyStringTuple = ('',) def getValidCatalogValue(self, value, forSearch):
emptyValuesCatalogIgnored = (None, '') '''p_value is the new value we want to index in the catalog, for this
field, for some object. p_value as is may not be an acceptable value
for the catalog: if it represents some empty value, like an empty
string, None or an empty tuple, instead of using it, the catalog will
keep the previously catalogued value! For those cases, this method
produces "empty" values that will really overwrite previous ones.'''
# Ugly catalog: if I give an empty tuple as index value, it keeps the
# previous value. If I give him a tuple containing an empty string, it
# is ok.
if isinstance(value, tuple) and not value:
value = forSearch and ' ' or ('',)
# Ugly catalog: if value is an empty string or None, it keeps the
# previous index value.
elif value in (None, ''): return ' '
return value
def getIndexValue(self, obj, forSearch=False): def getIndexValue(self, obj, forSearch=False):
'''Pure text must be extracted from rich content; multilingual content '''Pure text must be extracted from rich content; multilingual content
must be concatenated.''' must be concatenated.'''
# Must we produce an index value?
if not self.getAttribute(obj, 'mustIndex'):
return self.getValidCatalogValue(None, forSearch)
isXhtml = self.format == String.XHTML isXhtml = self.format == String.XHTML
if self.isMultilingual(obj): if self.isMultilingual(obj):
res = self.getValue(obj) res = self.getValue(obj)
@ -703,14 +720,7 @@ class String(Field):
else: else:
res = Field.getIndexValue(self, obj, forSearch) res = Field.getIndexValue(self, obj, forSearch)
if res and isXhtml: res = self.extractText(res) if res and isXhtml: res = self.extractText(res)
# Ugly catalog: if I give an empty tuple as index value, it keeps the return self.getValidCatalogValue(res, forSearch)
# previous value. If I give him a tuple containing an empty string, it
# is ok.
if isinstance(res, tuple) and not res: res = self.emptyStringTuple
# Ugly catalog: if value is an empty string or None, it keeps the
# previous index value.
if res in self.emptyValuesCatalogIgnored: res = ' '
return res
def getPossibleValues(self, obj, withTranslations=False, def getPossibleValues(self, obj, withTranslations=False,
withBlankValue=False, className=None, withBlankValue=False, className=None,

View file

@ -217,7 +217,7 @@ def executeCommand(cmd):
return res return res
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
charsIgnore = u'.,:;*+=~?%^\'"<>{}[]|\t\\' charsIgnore = u'.,:;*+=~?%^\'"<>{}[]|\t\\°'
fileNameIgnore = charsIgnore + u' $£€/' fileNameIgnore = charsIgnore + u' $£€/'
extractIgnore = charsIgnore + '()' extractIgnore = charsIgnore + '()'
alphaRex = re.compile('[a-zA-Z]') alphaRex = re.compile('[a-zA-Z]')