web/form.py
branchtls-sprint
changeset 863 4fde01fc39ca
parent 849 8591d896db7e
child 864 e0947007542a
equal deleted inserted replaced
862:ee560986e211 863:4fde01fc39ca
    17 from cubicweb.view import NOINDEX, NOFOLLOW, View, EntityView, AnyRsetView
    17 from cubicweb.view import NOINDEX, NOFOLLOW, View, EntityView, AnyRsetView
    18 from cubicweb.common.registerers import accepts_registerer
    18 from cubicweb.common.registerers import accepts_registerer
    19 from cubicweb.web import stdmsgs
    19 from cubicweb.web import stdmsgs
    20 from cubicweb.web.httpcache import NoHTTPCacheManager
    20 from cubicweb.web.httpcache import NoHTTPCacheManager
    21 from cubicweb.web.controller import redirect_params
    21 from cubicweb.web.controller import redirect_params
    22 from cubicweb.web import eid_param
    22 from cubicweb.web import INTERNAL_FIELD_VALUE, eid_param
       
    23 
    23 
    24 
    24 
    25 
    25 def relation_id(eid, rtype, target, reid):
    26 def relation_id(eid, rtype, target, reid):
    26     if target == 'subject':
    27     if target == 'subject':
    27         return u'%s:%s:%s' % (eid, rtype, reid)
    28         return u'%s:%s:%s' % (eid, rtype, reid)
   218         label = self.req._(label or stdmsgs.BUTTON_OK).capitalize()
   219         label = self.req._(label or stdmsgs.BUTTON_OK).capitalize()
   219         return self.BUTTON_STR % ('defaultsubmit', label, tabindex or 2)
   220         return self.BUTTON_STR % ('defaultsubmit', label, tabindex or 2)
   220     
   221     
   221     def button_apply(self, label=None, tabindex=None):
   222     def button_apply(self, label=None, tabindex=None):
   222         label = self.req._(label or stdmsgs.BUTTON_APPLY).capitalize()
   223         label = self.req._(label or stdmsgs.BUTTON_APPLY).capitalize()
   223         return self.ACTION_SUBMIT_STR % ('__action_apply', label, self.domid, label, tabindex or 3)
   224         return self.ACTION_SUBMIT_STR % ('__action_apply', label, self.domid,
       
   225                                          label, tabindex or 3)
   224 
   226 
   225     def button_delete(self, label=None, tabindex=None):
   227     def button_delete(self, label=None, tabindex=None):
   226         label = self.req._(label or stdmsgs.BUTTON_DELETE).capitalize()
   228         label = self.req._(label or stdmsgs.BUTTON_DELETE).capitalize()
   227         return self.ACTION_SUBMIT_STR % ('__action_delete', label, self.domid, label, tabindex or 3)
   229         return self.ACTION_SUBMIT_STR % ('__action_delete', label, self.domid,
       
   230                                          label, tabindex or 3)
   228     
   231     
   229     def button_cancel(self, label=None, tabindex=None):
   232     def button_cancel(self, label=None, tabindex=None):
   230         label = self.req._(label or stdmsgs.BUTTON_CANCEL).capitalize()
   233         label = self.req._(label or stdmsgs.BUTTON_CANCEL).capitalize()
   231         return self.ACTION_SUBMIT_STR % ('__action_cancel', label, self.domid, label, tabindex or 4)
   234         return self.ACTION_SUBMIT_STR % ('__action_cancel', label, self.domid,
       
   235                                          label, tabindex or 4)
   232     
   236     
   233     def button_reset(self, label=None, tabindex=None):
   237     def button_reset(self, label=None, tabindex=None):
   234         label = self.req._(label or stdmsgs.BUTTON_CANCEL).capitalize()
   238         label = self.req._(label or stdmsgs.BUTTON_CANCEL).capitalize()
   235         return u'<input class="validateButton" type="reset" value="%s" tabindex="%s"/>' % (
   239         return u'<input class="validateButton" type="reset" value="%s" tabindex="%s"/>' % (
   236             label, tabindex or 4)
   240             label, tabindex or 4)
   382 class DateField(IntField):
   386 class DateField(IntField):
   383     
   387     
   384     def format_value(self, req, value):
   388     def format_value(self, req, value):
   385         return value and ustrftime(value, req.property_value('ui.date-format')) or u''
   389         return value and ustrftime(value, req.property_value('ui.date-format')) or u''
   386 
   390 
   387 class DateTimeField(IntField):
   391 class HiddenInitialValueField(Field):
   388 
   392     def __init__(self, visible_field, name):
   389     def format_value(self, req, value):
   393         super(HiddenInitialValueField, self).__init__(name=name,
   390         return value and ustrftime(value, req.property_value('ui.datetime-format')) or u''
   394                                                       widget=HiddenInput)
   391 
   395         self.visible_field = visible_field
   392 class FileField(IntField):
       
   393     needs_multipart = True
       
   394                  
   396                  
       
   397 class RelationField(Field):
       
   398     def __init__(self, role='subject', **kwargs):
       
   399         super(RelationField, self).__init__(**kwargs)
       
   400         self.role = role
       
   401         
   395 # forms ############
   402 # forms ############
   396 class metafieldsform(type):
   403 class metafieldsform(type):
   397     def __new__(mcs, name, bases, classdict):
   404     def __new__(mcs, name, bases, classdict):
   398         allfields = []
   405         allfields = []
   399         for base in bases:
   406         for base in bases:
   438         # on validation error, we get a dictionnary of previously submitted values
   445         # on validation error, we get a dictionnary of previously submitted values
   439         previous_values = self.req.data.get('formvalues')
   446         previous_values = self.req.data.get('formvalues')
   440         if previous_values:
   447         if previous_values:
   441             values.update(previous_values)
   448             values.update(previous_values)
   442         for field in self.fields:
   449         for field in self.fields:
   443             context[field] = {'value': self.form_field_value(field, field_values),
   450             context[field] = {'value': self.form_field_value(field, values),
   444                               'name': self.form_field_name(field),
   451                               'name': self.form_field_name(field),
   445                               'id': self.form_field_id(field),
   452                               'id': self.form_field_id(field),
   446                               }
   453                               }
   447 
   454 
   448     def form_field_value(self, field, values):
   455     def form_field_value(self, field, values):
   501         self.fields.append(TextField(name='__type', widget=HiddenInput))
   508         self.fields.append(TextField(name='__type', widget=HiddenInput))
   502         self.fields.append(TextField(name='eid', widget=HiddenInput))
   509         self.fields.append(TextField(name='eid', widget=HiddenInput))
   503         
   510         
   504     def form_render(self, entity, **values):
   511     def form_render(self, entity, **values):
   505         self.entity = entity
   512         self.entity = entity
       
   513         eschema = self.entity.e_schema
       
   514         for field in self.fields[:]:
       
   515             fieldname = field.name
       
   516             if fieldname != 'eid' and (
       
   517                 (eschema.has_subject_relation(fieldname) or
       
   518                 eschema.has_object_relation(fieldname))):
       
   519                 self.fields.append(self.build_hidden_field(field))
   506         return super(EntityFieldsForm, self).form_render(**values)
   520         return super(EntityFieldsForm, self).form_render(**values)
   507         
   521 
       
   522     def build_hidden_field(self, field):
       
   523         """returns the hidden field which will indicate the value
       
   524         before the modification
       
   525         """
       
   526         # Only RelationField has a `role` attribute, others are used
       
   527         # to describe attribute fields => role is 'subject'
       
   528         role = getattr(field, 'role', 'subject')
       
   529         if role == 'subject':
       
   530             name = 'edits-%s' % field.name
       
   531         else:
       
   532             name = 'edito-%s' % field.name
       
   533         return HiddenInitialValueField(field, name=name)
       
   534     
   508     def form_field_value(self, field, values):
   535     def form_field_value(self, field, values):
   509         """look for field's value with the following rules:
   536         """look for field's value with the following rules:
   510         1. handle special __type and eid fields
   537         1. handle special __type and eid fields
   511         2. looks in kw args given to render_form (including previously submitted
   538         2. looks in kw args given to render_form (including previously submitted
   512            form values if any)
   539            form values if any)
   518              1. looks for a default_<fieldname> attribute / method on the form
   545              1. looks for a default_<fieldname> attribute / method on the form
   519              2. use field's initial value
   546              2. use field's initial value
   520              
   547              
   521         values found in step 4 may be a callable which'll then be called.
   548         values found in step 4 may be a callable which'll then be called.
   522         """
   549         """
   523         if field.name == '__type':
   550         fieldname = field.name
       
   551         if fieldname.startswith('edits-') or fieldname.startswith('edito-'):
       
   552             value = self.form_field_value(field.visible_field, values)
       
   553             if value is None or not self.entity.has_eid():
       
   554                 value = INTERNAL_FIELD_VALUE
       
   555         elif fieldname == '__type':
   524             value = self.entity.id
   556             value = self.entity.id
   525         elif field.name == 'eid':
   557         elif fieldname == 'eid':
   526             value = self.entity.eid
   558             value = self.entity.eid
   527         elif field.name in values:
   559         elif fieldname in values:
   528             value = values[field.name]
   560             value = values[fieldname]
   529         elif field.name in self.req.form:
   561         elif fieldname in self.req.form:
   530             value = self.req.form[field.name]
   562             value = self.req.form[fieldname]
   531         else:
   563         else:
   532             if self.entity.has_eid():
   564             if self.entity.has_eid():
   533                 # use value found on the entity or field's initial value if it's
   565                 # use value found on the entity or field's initial value if it's
   534                 # not an attribute of the entity (XXX may conflicts and get
   566                 # not an attribute of the entity (XXX may conflicts and get
   535                 # undesired value)
   567                 # undesired value)
   536                 value = getattr(self.entity, field.name, field.initial)
   568                 value = getattr(self.entity, fieldname, field.initial)
   537             else:
   569             else:
   538                 defaultattr = 'default_%s' % field.name
   570                 defaultattr = 'default_%s' % fieldname
   539                 if hasattr(self.entity, defaultattr):
   571                 if hasattr(self.entity, defaultattr):
   540                     # XXX bw compat, default_<field name> on the entity
   572                     # XXX bw compat, default_<field name> on the entity
   541                     warn('found %s on %s, should be set on a specific form'
   573                     warn('found %s on %s, should be set on a specific form'
   542                          % (defaultattr, self.entity.id), DeprecationWarning)
   574                          % (defaultattr, self.entity.id), DeprecationWarning)
   543                     value = getattr(self.entity, defaultattr)
   575                     value = getattr(self.entity, defaultattr)
   590         w(u'</fieldset>')
   622         w(u'</fieldset>')
   591         w(u'</form>')
   623         w(u'</form>')
   592         return '\n'.join(data)
   624         return '\n'.join(data)
   593 
   625 
   594     def render_fields(self, w, form):
   626     def render_fields(self, w, form):
       
   627         fields = form.fields[:]
       
   628         for field in form.fields:
       
   629             if isinstance(field.widget, HiddenInput):
       
   630                 w(field.render(form))
       
   631                 fields.remove(field)
   595         w(u'<table>')
   632         w(u'<table>')
   596         for field in form.fields:
   633         for field in fields:
   597             w(u'<tr>')
   634             w(u'<tr>')
   598             w('<th>%s</th>' % self.render_label(form, field))
   635             w('<th>%s</th>' % self.render_label(form, field))
   599             w(u'<td style="width:100%;">')
   636             w(u'<td style="width:100%;">')
   600             w(field.render(form))
   637             w(field.render(form))
   601             w(u'</td></tr>')
   638             w(u'</td></tr>')