web/formfields.py
changeset 1986 96c0e56cb0cf
parent 1977 606923dff11b
child 1988 b5c5c088bb03
equal deleted inserted replaced
1985:9c1db4e06095 1986:96c0e56cb0cf
    17 from cubicweb.common import tags, uilib
    17 from cubicweb.common import tags, uilib
    18 from cubicweb.web import INTERNAL_FIELD_VALUE
    18 from cubicweb.web import INTERNAL_FIELD_VALUE
    19 from cubicweb.web.formwidgets import (
    19 from cubicweb.web.formwidgets import (
    20     HiddenInput, TextInput, FileInput, PasswordInput, TextArea, FCKEditor,
    20     HiddenInput, TextInput, FileInput, PasswordInput, TextArea, FCKEditor,
    21     Radio, Select, DateTimePicker)
    21     Radio, Select, DateTimePicker)
       
    22 
    22 
    23 
    23 class Field(object):
    24 class Field(object):
    24     """field class is introduced to control what's displayed in forms. It makes
    25     """field class is introduced to control what's displayed in forms. It makes
    25     the link between something to edit and its display in the form. Actual
    26     the link between something to edit and its display in the form. Actual
    26     display is handled by a widget associated to the field.
    27     display is handled by a widget associated to the field.
    78         self.name = name
    79         self.name = name
    79         self.id = id or name
    80         self.id = id or name
    80         self.label = label or name
    81         self.label = label or name
    81         self.help = help
    82         self.help = help
    82         self.required = required
    83         self.required = required
    83         if widget is not None:
       
    84             self.widget = widget
       
    85         if isinstance(self.widget, type):
       
    86             self.widget = self.widget()
       
    87         self.initial = initial
    84         self.initial = initial
    88         self.choices = choices
    85         self.choices = choices
    89         self.sort = sort
    86         self.sort = sort
    90         self.internationalizable = internationalizable
    87         self.internationalizable = internationalizable
    91         self.eidparam = eidparam
    88         self.eidparam = eidparam
    92         self.role = role
    89         self.role = role
       
    90         self.init_widget(widget)
    93         # ordering number for this field instance
    91         # ordering number for this field instance
    94         self.creation_rank = Field.__creation_rank
    92         self.creation_rank = Field.__creation_rank
    95         Field.__creation_rank += 1
    93         Field.__creation_rank += 1
    96 
    94 
    97     def __unicode__(self):
    95     def __unicode__(self):
    99             self.__class__.__name__, self.name, self.label,
    97             self.__class__.__name__, self.name, self.label,
   100             self.id, self.initial, self.is_visible(), id(self))
    98             self.id, self.initial, self.is_visible(), id(self))
   101 
    99 
   102     def __repr__(self):
   100     def __repr__(self):
   103         return self.__unicode__().encode('utf-8')
   101         return self.__unicode__().encode('utf-8')
       
   102 
       
   103     def init_widget(self, widget):
       
   104         if widget is not None:
       
   105             self.widget = widget
       
   106         if isinstance(self.widget, type):
       
   107             self.widget = self.widget()
   104 
   108 
   105     def set_name(self, name):
   109     def set_name(self, name):
   106         """automatically set .id and .label when name is set"""
   110         """automatically set .id and .label when name is set"""
   107         assert name
   111         assert name
   108         self.name = name
   112         self.name = name
   175         """method called before by form_build_context to trigger potential field
   179         """method called before by form_build_context to trigger potential field
   176         initialization requiring the form instance
   180         initialization requiring the form instance
   177         """
   181         """
   178         pass
   182         pass
   179 
   183 
       
   184 
   180 class StringField(Field):
   185 class StringField(Field):
       
   186     widget = TextArea
       
   187 
   181     def __init__(self, max_length=None, **kwargs):
   188     def __init__(self, max_length=None, **kwargs):
       
   189         self.max_length = max_length # must be set before super call
   182         super(StringField, self).__init__(**kwargs)
   190         super(StringField, self).__init__(**kwargs)
   183         self.max_length = max_length
   191 
       
   192     def init_widget(self, widget):
       
   193         if widget is None:
       
   194             if self.choices:
       
   195                 self.widget = Select()
       
   196             elif self.max_length and self.max_length < 257:
       
   197                 self.widget = TextInput()
       
   198         super(StringField, self).init_widget(widget)
   184         if isinstance(self.widget, TextArea):
   199         if isinstance(self.widget, TextArea):
   185             self.init_text_area(self.widget)
   200             self.init_text_area(self.widget)
       
   201         elif isinstance(self.widget, Select):
       
   202             self.widget.attrs.setdefault('size', 1)
   186 
   203 
   187     def init_text_area(self, widget):
   204     def init_text_area(self, widget):
   188         if self.max_length < 513:
   205         if self.max_length < 513:
   189             widget.attrs.setdefault('cols', 60)
   206             widget.attrs.setdefault('cols', 60)
   190             widget.attrs.setdefault('rows', 5)
   207             widget.attrs.setdefault('rows', 5)
   340         self.max = max
   357         self.max = max
   341         if isinstance(self.widget, TextInput):
   358         if isinstance(self.widget, TextInput):
   342             self.widget.attrs.setdefault('size', 5)
   359             self.widget.attrs.setdefault('size', 5)
   343             self.widget.attrs.setdefault('maxlength', 15)
   360             self.widget.attrs.setdefault('maxlength', 15)
   344 
   361 
       
   362 
   345 class BooleanField(Field):
   363 class BooleanField(Field):
   346     widget = Radio
   364     widget = Radio
   347 
   365 
   348     def vocabulary(self, form):
   366     def vocabulary(self, form):
   349         if self.choices:
   367         if self.choices:
   378 
   396 
   379 
   397 
   380 class TimeField(DateField):
   398 class TimeField(DateField):
   381     format_prop = 'ui.datetime-format'
   399     format_prop = 'ui.datetime-format'
   382     widget = TextInput
   400     widget = TextInput
       
   401 
   383 
   402 
   384 class HiddenInitialValueField(Field):
   403 class HiddenInitialValueField(Field):
   385     def __init__(self, visible_field):
   404     def __init__(self, visible_field):
   386         name = 'edit%s-%s' % (visible_field.role[0], visible_field.name)
   405         name = 'edit%s-%s' % (visible_field.role[0], visible_field.name)
   387         super(HiddenInitialValueField, self).__init__(
   406         super(HiddenInitialValueField, self).__init__(
   468                 return RichTextField(**kwargs)
   487                 return RichTextField(**kwargs)
   469             constraints = rschema.rproperty(eschema, targetschema, 'constraints')
   488             constraints = rschema.rproperty(eschema, targetschema, 'constraints')
   470             # init StringField parameters according to constraints
   489             # init StringField parameters according to constraints
   471             for cstr in constraints:
   490             for cstr in constraints:
   472                 if isinstance(cstr, StaticVocabularyConstraint):
   491                 if isinstance(cstr, StaticVocabularyConstraint):
   473                     kwargs.setdefault('widget', Select())
       
   474                     kwargs.setdefault('choices', cstr.vocabulary)
   492                     kwargs.setdefault('choices', cstr.vocabulary)
   475                     if card in '?1':
   493                     break
   476                         if isinstance(kwargs['widget'], type):
       
   477                             kwargs['widget'] = kwargs['widget']()
       
   478                         kwargs['widget'].attrs.setdefault('size', 1)
       
   479             for cstr in constraints:
   494             for cstr in constraints:
   480                 if isinstance(cstr, SizeConstraint) and cstr.max is not None:
   495                 if isinstance(cstr, SizeConstraint) and cstr.max is not None:
   481                     if cstr.max < 257:
       
   482                         kwargs.setdefault('widget', TextInput())
       
   483                     kwargs['max_length'] = cstr.max
   496                     kwargs['max_length'] = cstr.max
   484             kwargs.setdefault('widget', TextArea())
       
   485             return StringField(**kwargs)
   497             return StringField(**kwargs)
   486         if fieldclass is FileField:
   498         if fieldclass is FileField:
   487             for metadata in ('format', 'encoding'):
   499             for metadata in ('format', 'encoding'):
   488                 metaschema = eschema.has_metadata(rschema, metadata)
   500                 metaschema = eschema.has_metadata(rschema, metadata)
   489                 if metaschema is not None:
   501                 if metaschema is not None:
   490                     kwargs['%s_field' % metadata] = guess_field(eschema, metaschema,
   502                     kwargs['%s_field' % metadata] = guess_field(eschema, metaschema,
   491                                                                 skip_meta_attr=False)
   503                                                                 skip_meta_attr=False)
   492         return fieldclass(**kwargs)
   504         return fieldclass(**kwargs)
   493     kwargs['role'] = role
   505     kwargs['role'] = role
   494     return RelationField.fromcardinality(card, **kwargs)
   506     return RelationField.fromcardinality(card, **kwargs)
       
   507 
   495 
   508 
   496 FIELDS = {
   509 FIELDS = {
   497     'Boolean':  BooleanField,
   510     'Boolean':  BooleanField,
   498     'Bytes':    FileField,
   511     'Bytes':    FileField,
   499     'Date':     DateField,
   512     'Date':     DateField,