web/formfields.py
author Sylvain Thénault <sylvain.thenault@logilab.fr>
Mon, 21 Dec 2009 20:00:18 +0100
changeset 4161 4273f5094651
parent 4160 3fbdeef9a610
child 4162 d2663bcf5306
permissions -rw-r--r--
refactor vocabulary handling to avoid having to define methods on form objects, use .choices instead even for non final relations. Details: * deprecated support of <role>_<relation>_vocabulary methods on forms * new utility functions for relations vocabulary * most logic now on the RelationField class
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
     1
"""field classes for form construction
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
     2
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
     3
:organization: Logilab
1977
606923dff11b big bunch of copyright / docstring update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1858
diff changeset
     4
:copyright: 2009 LOGILAB S.A. (Paris, FRANCE), license is LGPL v2.
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
     5
:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
1977
606923dff11b big bunch of copyright / docstring update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1858
diff changeset
     6
:license: GNU Lesser General Public License, v2.1 - http://www.gnu.org/licenses
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
     7
"""
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
     8
__docformat__ = "restructuredtext en"
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
     9
2244
52e2431e7cce missing import
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2196
diff changeset
    10
from warnings import warn
1095
6917ebe281e9 test and fix guess_field, some pylint fixes
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
    11
from datetime import datetime
6917ebe281e9 test and fix guess_field, some pylint fixes
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
    12
2312
af4d8f75c5db use xml_escape
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2244
diff changeset
    13
from logilab.mtconverter import xml_escape
4158
0e97cf2cf55b missing imports
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4156
diff changeset
    14
from logilab.common.decorators import cached
0e97cf2cf55b missing imports
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4156
diff changeset
    15
4160
3fbdeef9a610 cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4159
diff changeset
    16
from yams.schema import KNOWN_METAATTRIBUTES
2459
d088d0ff48a1 move RichString and co to yams, keeping only a small monkeypatch for cw-page-template here
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2362
diff changeset
    17
from yams.constraints import (SizeConstraint, StaticVocabularyConstraint,
d088d0ff48a1 move RichString and co to yams, keeping only a small monkeypatch for cw-page-template here
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2362
diff changeset
    18
                              FormatConstraint)
1095
6917ebe281e9 test and fix guess_field, some pylint fixes
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
    19
2678
0308dc159b96 use yams api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2568
diff changeset
    20
from cubicweb.utils import ustrftime
4023
eae23c40627a drop common subpackage
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4014
diff changeset
    21
from cubicweb import tags, uilib
4158
0e97cf2cf55b missing imports
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4156
diff changeset
    22
from cubicweb.web import INTERNAL_FIELD_VALUE, eid_param
1265
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
    23
from cubicweb.web.formwidgets import (
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
    24
    HiddenInput, TextInput, FileInput, PasswordInput, TextArea, FCKEditor,
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
    25
    Radio, Select, DateTimePicker)
1095
6917ebe281e9 test and fix guess_field, some pylint fixes
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
    26
1986
96c0e56cb0cf move widget selection's logic on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
    27
3334
8d831c02da9a fix sort of fields vocabulary: should consider option groups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3308
diff changeset
    28
def vocab_sort(vocab):
8d831c02da9a fix sort of fields vocabulary: should consider option groups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3308
diff changeset
    29
    """sort vocabulary, considering option groups"""
8d831c02da9a fix sort of fields vocabulary: should consider option groups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3308
diff changeset
    30
    result = []
8d831c02da9a fix sort of fields vocabulary: should consider option groups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3308
diff changeset
    31
    partresult = []
8d831c02da9a fix sort of fields vocabulary: should consider option groups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3308
diff changeset
    32
    for label, value in vocab:
8d831c02da9a fix sort of fields vocabulary: should consider option groups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3308
diff changeset
    33
        if value is None: # opt group start
8d831c02da9a fix sort of fields vocabulary: should consider option groups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3308
diff changeset
    34
            if partresult:
8d831c02da9a fix sort of fields vocabulary: should consider option groups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3308
diff changeset
    35
                result += sorted(partresult)
8d831c02da9a fix sort of fields vocabulary: should consider option groups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3308
diff changeset
    36
                partresult = []
8d831c02da9a fix sort of fields vocabulary: should consider option groups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3308
diff changeset
    37
            result.append( (label, value) )
8d831c02da9a fix sort of fields vocabulary: should consider option groups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3308
diff changeset
    38
        else:
8d831c02da9a fix sort of fields vocabulary: should consider option groups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3308
diff changeset
    39
            partresult.append( (label, value) )
8d831c02da9a fix sort of fields vocabulary: should consider option groups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3308
diff changeset
    40
    result += sorted(partresult)
8d831c02da9a fix sort of fields vocabulary: should consider option groups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3308
diff changeset
    41
    return result
8d831c02da9a fix sort of fields vocabulary: should consider option groups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3308
diff changeset
    42
4159
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
    43
_MARKER = object()
3334
8d831c02da9a fix sort of fields vocabulary: should consider option groups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3308
diff changeset
    44
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
    45
class Field(object):
1265
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
    46
    """field class is introduced to control what's displayed in forms. It makes
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
    47
    the link between something to edit and its display in the form. Actual
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
    48
    display is handled by a widget associated to the field.
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
    49
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
    50
    Attributes
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
    51
    ----------
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
    52
    all the attributes described below have sensible default value which may be
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
    53
    overriden by value given to field's constructor.
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
    54
1265
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
    55
    :name:
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
    56
       name of the field (basestring), should be unique in a form.
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
    57
    :id:
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
    58
       dom identifier (default to the same value as `name`), should be unique in
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
    59
       a form.
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
    60
    :label:
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
    61
       label of the field (default to the same value as `name`).
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
    62
    :help:
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
    63
       help message about this field.
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
    64
    :widget:
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
    65
       widget associated to the field. Each field class has a default widget
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
    66
       class which may be overriden per instance.
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
    67
    :required:
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
    68
       bool flag telling if the field is required or not.
4159
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
    69
    :value:
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
    70
       field's value, used when no value specified by other means. XXX explain
1265
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
    71
    :choices:
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
    72
       static vocabulary for this field. May be a list of values or a list of
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
    73
       (label, value) tuples if specified.
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
    74
    :sort:
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
    75
       bool flag telling if the vocabulary (either static vocabulary specified
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
    76
       in `choices` or dynamic vocabulary fetched from the form) should be
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
    77
       sorted on label.
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
    78
    :internationalizable:
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
    79
       bool flag telling if the vocabulary labels should be translated using the
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
    80
       current request language.
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
    81
    :eidparam:
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
    82
       bool flag telling if this field is linked to a specific entity
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
    83
    :role:
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
    84
       when the field is linked to an entity attribute or relation, tells the
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
    85
       role of the entity in the relation (eg 'subject' or 'object')
2520
8c5cf48ae9ea new fieldset attribute on field, use to group fields by the default form renderer
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2459
diff changeset
    86
    :fieldset:
8c5cf48ae9ea new fieldset attribute on field, use to group fields by the default form renderer
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2459
diff changeset
    87
       optional fieldset to which this field belongs to
3874
7d0d4a6be046 [formfields] allow fields ordering with autoform_field_kwargs
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3873
diff changeset
    88
    :order:
7d0d4a6be046 [formfields] allow fields ordering with autoform_field_kwargs
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3873
diff changeset
    89
       key used by automatic forms to sort fields
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
    90
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
    91
    """
1265
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
    92
    # default widget associated to this class of fields. May be overriden per
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
    93
    # instance
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
    94
    widget = TextInput
1265
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
    95
    # does this field requires a multipart form
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
    96
    needs_multipart = False
1265
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
    97
    # class attribute used for ordering of fields in a form
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
    98
    __creation_rank = 0
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
    99
4159
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   100
    eidparam = False
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   101
    role = None
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   102
    id = None
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   103
    help = None
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   104
    required = False
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   105
    choices = None
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   106
    sort = True
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   107
    internationalizable = False
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   108
    fieldset = None
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   109
    order = None
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   110
    value = _MARKER
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   111
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   112
    def __init__(self, name=None, label=None, widget=None, **kwargs):
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   113
        for key, val in kwargs.items():
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   114
            if key == 'initial':
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   115
                warn('[3.6] use value instead of initial', DeprecationWarning,
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   116
                     stacklevel=3)
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   117
                key = 'value'
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   118
            assert hasattr(self.__class__, key) and not key[0] == '_', key
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   119
            setattr(self, key, val)
1265
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
   120
        self.name = name
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
   121
        self.label = label or name
4159
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   122
        # has to be done after other attributes initialization
1986
96c0e56cb0cf move widget selection's logic on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   123
        self.init_widget(widget)
1265
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
   124
        # ordering number for this field instance
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
   125
        self.creation_rank = Field.__creation_rank
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
   126
        Field.__creation_rank += 1
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
   127
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   128
    def __unicode__(self):
4159
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   129
        return u'<%s name=%r eidparam=%s role=%r id=%r value=%r visible=%r @%x>' % (
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   130
            self.__class__.__name__, self.name, self.eidparam, self.role,
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   131
            self.id, self.value, self.is_visible(), id(self))
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   132
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   133
    def __repr__(self):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   134
        return self.__unicode__().encode('utf-8')
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   135
1986
96c0e56cb0cf move widget selection's logic on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   136
    def init_widget(self, widget):
96c0e56cb0cf move widget selection's logic on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   137
        if widget is not None:
96c0e56cb0cf move widget selection's logic on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   138
            self.widget = widget
2091
a7ea618e5478 don't set select widget when a vocabulary widget is already specified on the field class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2086
diff changeset
   139
        elif self.choices and not self.widget.vocabulary_widget:
a7ea618e5478 don't set select widget when a vocabulary widget is already specified on the field class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2086
diff changeset
   140
            self.widget = Select()
1986
96c0e56cb0cf move widget selection's logic on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   141
        if isinstance(self.widget, type):
96c0e56cb0cf move widget selection's logic on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   142
            self.widget = self.widget()
96c0e56cb0cf move widget selection's logic on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   143
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   144
    def set_name(self, name):
4159
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   145
        """automatically set .label when name is set"""
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   146
        assert name
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   147
        self.name = name
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   148
        if not self.label:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   149
            self.label = name
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
   150
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   151
    def is_visible(self):
1265
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
   152
        """return true if the field is not an hidden field"""
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   153
        return not isinstance(self.widget, HiddenInput)
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
   154
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   155
    def actual_fields(self, form):
1265
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
   156
        """return actual fields composing this field in case of a compound
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
   157
        field, usually simply return self
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
   158
        """
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   159
        yield self
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
   160
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   161
    def format_value(self, req, value):
1265
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
   162
        """return value suitable for display where value may be a list or tuple
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
   163
        of values
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
   164
        """
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   165
        if isinstance(value, (list, tuple)):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   166
            return [self.format_single_value(req, val) for val in value]
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   167
        return self.format_single_value(req, value)
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
   168
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   169
    def format_single_value(self, req, value):
1265
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
   170
        """return value suitable for display"""
1306
e70ad982374a bool handling
sylvain.thenault@logilab.fr
parents: 1305
diff changeset
   171
        if value is None or value is False:
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   172
            return u''
1306
e70ad982374a bool handling
sylvain.thenault@logilab.fr
parents: 1305
diff changeset
   173
        if value is True:
e70ad982374a bool handling
sylvain.thenault@logilab.fr
parents: 1305
diff changeset
   174
            return u'1'
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   175
        return unicode(value)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   176
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   177
    def get_widget(self, form):
1265
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
   178
        """return the widget instance associated to this field"""
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   179
        return self.widget
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
   180
4156
1bbb0ee42c8e drop form_field_name/form_field_id methods from form object, in favor of field.input_name(form) / field.dom_id(form)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4110
diff changeset
   181
    # cached is necessary else we get some pb on entity creation : entity.eid is
1bbb0ee42c8e drop form_field_name/form_field_id methods from form object, in favor of field.input_name(form) / field.dom_id(form)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4110
diff changeset
   182
    # modified from creation mark (eg 'X') to its actual eid (eg 123), and then
1bbb0ee42c8e drop form_field_name/form_field_id methods from form object, in favor of field.input_name(form) / field.dom_id(form)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4110
diff changeset
   183
    # `field.input_name()` won't return the right key anymore if not cached
1bbb0ee42c8e drop form_field_name/form_field_id methods from form object, in favor of field.input_name(form) / field.dom_id(form)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4110
diff changeset
   184
    # (first call to input_name done *before* eventual eid affectation).
1bbb0ee42c8e drop form_field_name/form_field_id methods from form object, in favor of field.input_name(form) / field.dom_id(form)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4110
diff changeset
   185
    @cached
1bbb0ee42c8e drop form_field_name/form_field_id methods from form object, in favor of field.input_name(form) / field.dom_id(form)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4110
diff changeset
   186
    def input_name(self, form, suffix=None):
1bbb0ee42c8e drop form_field_name/form_field_id methods from form object, in favor of field.input_name(form) / field.dom_id(form)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4110
diff changeset
   187
        """return 'qualified name' for this field"""
1bbb0ee42c8e drop form_field_name/form_field_id methods from form object, in favor of field.input_name(form) / field.dom_id(form)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4110
diff changeset
   188
        if self.eidparam:
1bbb0ee42c8e drop form_field_name/form_field_id methods from form object, in favor of field.input_name(form) / field.dom_id(form)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4110
diff changeset
   189
            if suffix is None:
1bbb0ee42c8e drop form_field_name/form_field_id methods from form object, in favor of field.input_name(form) / field.dom_id(form)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4110
diff changeset
   190
                return eid_param(self.role_name(), form.edited_entity.eid)
1bbb0ee42c8e drop form_field_name/form_field_id methods from form object, in favor of field.input_name(form) / field.dom_id(form)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4110
diff changeset
   191
            return eid_param(self.role_name() + suffix, form.edited_entity.eid)
1bbb0ee42c8e drop form_field_name/form_field_id methods from form object, in favor of field.input_name(form) / field.dom_id(form)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4110
diff changeset
   192
        if suffix is None:
1bbb0ee42c8e drop form_field_name/form_field_id methods from form object, in favor of field.input_name(form) / field.dom_id(form)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4110
diff changeset
   193
            return self.name
1bbb0ee42c8e drop form_field_name/form_field_id methods from form object, in favor of field.input_name(form) / field.dom_id(form)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4110
diff changeset
   194
        return self.name + suffix
1bbb0ee42c8e drop form_field_name/form_field_id methods from form object, in favor of field.input_name(form) / field.dom_id(form)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4110
diff changeset
   195
1bbb0ee42c8e drop form_field_name/form_field_id methods from form object, in favor of field.input_name(form) / field.dom_id(form)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4110
diff changeset
   196
    def role_name(self):
1bbb0ee42c8e drop form_field_name/form_field_id methods from form object, in favor of field.input_name(form) / field.dom_id(form)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4110
diff changeset
   197
        """return <field.name>-<field.role> if role is specified, else field.name"""
1bbb0ee42c8e drop form_field_name/form_field_id methods from form object, in favor of field.input_name(form) / field.dom_id(form)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4110
diff changeset
   198
        if self.role is not None:
1bbb0ee42c8e drop form_field_name/form_field_id methods from form object, in favor of field.input_name(form) / field.dom_id(form)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4110
diff changeset
   199
            return '%s-%s' % (self.name, self.role)
1bbb0ee42c8e drop form_field_name/form_field_id methods from form object, in favor of field.input_name(form) / field.dom_id(form)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4110
diff changeset
   200
        return self.name
1bbb0ee42c8e drop form_field_name/form_field_id methods from form object, in favor of field.input_name(form) / field.dom_id(form)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4110
diff changeset
   201
1bbb0ee42c8e drop form_field_name/form_field_id methods from form object, in favor of field.input_name(form) / field.dom_id(form)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4110
diff changeset
   202
    def dom_id(self, form):
1bbb0ee42c8e drop form_field_name/form_field_id methods from form object, in favor of field.input_name(form) / field.dom_id(form)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4110
diff changeset
   203
        """return an html dom identifier for this field"""
1bbb0ee42c8e drop form_field_name/form_field_id methods from form object, in favor of field.input_name(form) / field.dom_id(form)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4110
diff changeset
   204
        id = self.id or self.role_name()
1bbb0ee42c8e drop form_field_name/form_field_id methods from form object, in favor of field.input_name(form) / field.dom_id(form)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4110
diff changeset
   205
        if self.eidparam:
1bbb0ee42c8e drop form_field_name/form_field_id methods from form object, in favor of field.input_name(form) / field.dom_id(form)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4110
diff changeset
   206
            return eid_param(id, form.edited_entity.eid)
1bbb0ee42c8e drop form_field_name/form_field_id methods from form object, in favor of field.input_name(form) / field.dom_id(form)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4110
diff changeset
   207
        return id
1bbb0ee42c8e drop form_field_name/form_field_id methods from form object, in favor of field.input_name(form) / field.dom_id(form)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4110
diff changeset
   208
4159
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   209
    def display_value(self, form):
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   210
        """return field's *string* value to use for display
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   211
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   212
        looks in
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   213
        1. previously submitted form values if any (eg on validation error)
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   214
        2. req.form
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   215
        3. extra form args given to render_form
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   216
        4. field's typed value
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   217
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   218
        values found in 1. and 2. are expected te be already some 'display'
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   219
        value while those found in 3. and 4. are expected to be correctly typed.
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   220
        """
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   221
        qname = self.input_name(form)
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   222
        if qname in form.form_previous_values:
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   223
            return form.form_previous_values[qname]
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   224
        if qname in form._cw.form:
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   225
            return form._cw.form[qname]
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   226
        if self.name != qname and self.name in form._cw.form:
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   227
            return form._cw.form[self.name]
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   228
        for key in (self, qname):
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   229
            try:
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   230
                value = form.formvalues[key]
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   231
                break
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   232
            except:
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   233
                continue
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   234
        else:
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   235
            if self.name != qname and self.name in form.formvalues:
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   236
                value = form.formvalues[self.name]
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   237
            else:
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   238
                value = self.typed_value(form)
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   239
        if value != INTERNAL_FIELD_VALUE:
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   240
            value = self.format_value(form._cw, value)
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   241
        return value
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   242
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   243
    def typed_value(self, form, load_bytes=False):
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   244
        if self.value is not _MARKER:
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   245
            if callable(self.value):
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   246
                return self.value(form)
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   247
            return self.value
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   248
        return self._typed_value(form, load_bytes)
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   249
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   250
    def _typed_value(self, form, load_bytes=False):
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   251
        if self.eidparam:
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   252
            assert form._cw.vreg.schema.rschema(self.name).final
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   253
            entity = form.edited_entity
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   254
            if entity.has_eid() or self.name in entity:
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   255
                return getattr(entity, self.name)
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   256
        formattr = '%s_%s_default' % (self.role, self.name)
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   257
        if hasattr(form, formattr):
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   258
            warn('[3.6] %s.%s deprecated, use field.value' % (
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   259
                form.__class__.__name__, formattr), DeprecationWarning)
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   260
            return getattr(form, formattr)()
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   261
        if self.eidparam:
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   262
            return entity.e_schema.default(self.name)
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   263
        return None
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   264
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   265
    def example_format(self, req):
1265
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
   266
        """return a sample string describing what can be given as input for this
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
   267
        field
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
   268
        """
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   269
        return u''
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   270
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   271
    def render(self, form, renderer):
1265
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
   272
        """render this field, which is part of form, using the given form
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
   273
        renderer
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
   274
        """
2522
562f5dcf2345 widget.render now takes the renderer as third argument (keeping minimal bw compat)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2520
diff changeset
   275
        widget = self.get_widget(form)
3873
4d95109582c7 [web] remove widget.render backward compatibility
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3790
diff changeset
   276
        return widget.render(form, self, renderer)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   277
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   278
    def vocabulary(self, form):
1265
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
   279
        """return vocabulary for this field. This method will be called by
4161
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   280
        widgets which requires a vocabulary.
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   281
        """
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   282
        assert self.choices is not None
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   283
        if callable(self.choices):
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   284
            try:
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   285
                vocab = self.choices(form=form)
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   286
            except TypeError:
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   287
                warn('[3.3] vocabulary method (eg field.choices) should now take '
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   288
                     'the form instance as argument', DeprecationWarning)
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   289
                vocab = self.choices(req=form._cw)
1265
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
   290
        else:
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
   291
            vocab = form.form_field_vocabulary(self)
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
   292
        if self.internationalizable:
3790
34fdb8fb49d1 [B] web: weird display with internationalizable (Closes: #503071)
Julien Jehannet <julien.jehannet@logilab.fr>
parents: 3689
diff changeset
   293
            # the short-cirtcuit 'and' boolean operator is used here to permit
34fdb8fb49d1 [B] web: weird display with internationalizable (Closes: #503071)
Julien Jehannet <julien.jehannet@logilab.fr>
parents: 3689
diff changeset
   294
            # a valid empty string in vocabulary without attempting to translate
34fdb8fb49d1 [B] web: weird display with internationalizable (Closes: #503071)
Julien Jehannet <julien.jehannet@logilab.fr>
parents: 3689
diff changeset
   295
            # it by gettext (which can lead to weird strings display)
3890
d7a270f50f54 backport stable branch (one more time painfully)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3720 3874
diff changeset
   296
            vocab = [(label and form._cw._(label), value) for label, value in vocab]
1265
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
   297
        if self.sort:
3334
8d831c02da9a fix sort of fields vocabulary: should consider option groups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3308
diff changeset
   298
            vocab = vocab_sort(vocab)
1265
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
   299
        return vocab
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
   300
1307
8c3336c5ddba new form_init callback
sylvain.thenault@logilab.fr
parents: 1306
diff changeset
   301
    def form_init(self, form):
3510
bf746bf4a394 rename form_build_context to build_context, and call it from form, not renderer
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3496
diff changeset
   302
        """method called before by build_context to trigger potential field
1307
8c3336c5ddba new form_init callback
sylvain.thenault@logilab.fr
parents: 1306
diff changeset
   303
        initialization requiring the form instance
8c3336c5ddba new form_init callback
sylvain.thenault@logilab.fr
parents: 1306
diff changeset
   304
        """
8c3336c5ddba new form_init callback
sylvain.thenault@logilab.fr
parents: 1306
diff changeset
   305
        pass
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
   306
3387
a357d4147eee [forms] work-in-progress, big editcontroller refactoring: let fields/widgets process posted data
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3385
diff changeset
   307
    def process_form_value(self, form):
a357d4147eee [forms] work-in-progress, big editcontroller refactoring: let fields/widgets process posted data
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3385
diff changeset
   308
        """process posted form and return correctly typed value"""
a357d4147eee [forms] work-in-progress, big editcontroller refactoring: let fields/widgets process posted data
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3385
diff changeset
   309
        widget = self.get_widget(form)
a357d4147eee [forms] work-in-progress, big editcontroller refactoring: let fields/widgets process posted data
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3385
diff changeset
   310
        return widget.process_field_data(form, self)
a357d4147eee [forms] work-in-progress, big editcontroller refactoring: let fields/widgets process posted data
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3385
diff changeset
   311
a357d4147eee [forms] work-in-progress, big editcontroller refactoring: let fields/widgets process posted data
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3385
diff changeset
   312
    def process_posted(self, form):
a357d4147eee [forms] work-in-progress, big editcontroller refactoring: let fields/widgets process posted data
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3385
diff changeset
   313
        for field in self.actual_fields(form):
a357d4147eee [forms] work-in-progress, big editcontroller refactoring: let fields/widgets process posted data
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3385
diff changeset
   314
            if field is self:
a357d4147eee [forms] work-in-progress, big editcontroller refactoring: let fields/widgets process posted data
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3385
diff changeset
   315
                yield field.name, field.process_form_value(form)
a357d4147eee [forms] work-in-progress, big editcontroller refactoring: let fields/widgets process posted data
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3385
diff changeset
   316
            else:
a357d4147eee [forms] work-in-progress, big editcontroller refactoring: let fields/widgets process posted data
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3385
diff changeset
   317
                # recursive function: we might have compound fields
a357d4147eee [forms] work-in-progress, big editcontroller refactoring: let fields/widgets process posted data
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3385
diff changeset
   318
                # of compound fields (of compound fields of ...)
a357d4147eee [forms] work-in-progress, big editcontroller refactoring: let fields/widgets process posted data
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3385
diff changeset
   319
                for fieldname, value in field.process_posted(form):
a357d4147eee [forms] work-in-progress, big editcontroller refactoring: let fields/widgets process posted data
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3385
diff changeset
   320
                    yield fieldname, value
a357d4147eee [forms] work-in-progress, big editcontroller refactoring: let fields/widgets process posted data
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3385
diff changeset
   321
1986
96c0e56cb0cf move widget selection's logic on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   322
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   323
class StringField(Field):
1986
96c0e56cb0cf move widget selection's logic on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   324
    widget = TextArea
96c0e56cb0cf move widget selection's logic on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   325
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   326
    def __init__(self, max_length=None, **kwargs):
1986
96c0e56cb0cf move widget selection's logic on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   327
        self.max_length = max_length # must be set before super call
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   328
        super(StringField, self).__init__(**kwargs)
1986
96c0e56cb0cf move widget selection's logic on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   329
96c0e56cb0cf move widget selection's logic on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   330
    def init_widget(self, widget):
96c0e56cb0cf move widget selection's logic on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   331
        if widget is None:
96c0e56cb0cf move widget selection's logic on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   332
            if self.choices:
1988
b5c5c088bb03 if choices is set and widget not explicitly specified, use Select in base field
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1986
diff changeset
   333
                widget = Select()
1986
96c0e56cb0cf move widget selection's logic on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   334
            elif self.max_length and self.max_length < 257:
1988
b5c5c088bb03 if choices is set and widget not explicitly specified, use Select in base field
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1986
diff changeset
   335
                widget = TextInput()
2344
22b5ea0679ed [formfields] set a reasonable minimal minimum length to input/text, also set the max length if applicable (closes #344538)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 2332
diff changeset
   336
1986
96c0e56cb0cf move widget selection's logic on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   337
        super(StringField, self).init_widget(widget)
1573
d34589d35daa drop TextField, this is simply a StringField with a text area widget
sylvain.thenault@logilab.fr
parents: 1564
diff changeset
   338
        if isinstance(self.widget, TextArea):
d34589d35daa drop TextField, this is simply a StringField with a text area widget
sylvain.thenault@logilab.fr
parents: 1564
diff changeset
   339
            self.init_text_area(self.widget)
2362
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 2360
diff changeset
   340
        elif isinstance(self.widget, TextInput):
2360
1d43aa551ba9 [formwidgets,formfields] hum, this way
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 2356
diff changeset
   341
            self.init_text_input(self.widget)
1d43aa551ba9 [formwidgets,formfields] hum, this way
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 2356
diff changeset
   342
1d43aa551ba9 [formwidgets,formfields] hum, this way
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 2356
diff changeset
   343
    def init_text_input(self, widget):
1d43aa551ba9 [formwidgets,formfields] hum, this way
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 2356
diff changeset
   344
        if self.max_length:
1d43aa551ba9 [formwidgets,formfields] hum, this way
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 2356
diff changeset
   345
            widget.attrs.setdefault('size', min(45, self.max_length))
1d43aa551ba9 [formwidgets,formfields] hum, this way
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 2356
diff changeset
   346
            widget.attrs.setdefault('maxlength', self.max_length)
1573
d34589d35daa drop TextField, this is simply a StringField with a text area widget
sylvain.thenault@logilab.fr
parents: 1564
diff changeset
   347
d34589d35daa drop TextField, this is simply a StringField with a text area widget
sylvain.thenault@logilab.fr
parents: 1564
diff changeset
   348
    def init_text_area(self, widget):
d34589d35daa drop TextField, this is simply a StringField with a text area widget
sylvain.thenault@logilab.fr
parents: 1564
diff changeset
   349
        if self.max_length < 513:
d34589d35daa drop TextField, this is simply a StringField with a text area widget
sylvain.thenault@logilab.fr
parents: 1564
diff changeset
   350
            widget.attrs.setdefault('cols', 60)
d34589d35daa drop TextField, this is simply a StringField with a text area widget
sylvain.thenault@logilab.fr
parents: 1564
diff changeset
   351
            widget.attrs.setdefault('rows', 5)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   352
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   353
4159
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   354
class PasswordField(StringField):
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   355
    widget = PasswordInput
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   356
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   357
    def _typed_value(self, form, load_bytes=False):
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   358
        if self.eidparam:
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   359
            # no way to fetch actual password value with cw
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   360
            if form.edited_entity.has_eid():
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   361
                return INTERNAL_FIELD_VALUE
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   362
            return form.edited_entity.e_schema.default(self.name)
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   363
        return super(PasswordField, self)._typed_value(form, load_bytes)
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   364
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   365
1573
d34589d35daa drop TextField, this is simply a StringField with a text area widget
sylvain.thenault@logilab.fr
parents: 1564
diff changeset
   366
class RichTextField(StringField):
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   367
    widget = None
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   368
    def __init__(self, format_field=None, **kwargs):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   369
        super(RichTextField, self).__init__(**kwargs)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   370
        self.format_field = format_field
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   371
2348
acf4b6a59558 [formwidgets] ensure textarea for richstring has not ridicuously small size (close #344547)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 2347
diff changeset
   372
    def init_text_area(self, widget):
acf4b6a59558 [formwidgets] ensure textarea for richstring has not ridicuously small size (close #344547)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 2347
diff changeset
   373
        pass
acf4b6a59558 [formwidgets] ensure textarea for richstring has not ridicuously small size (close #344547)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 2347
diff changeset
   374
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   375
    def get_widget(self, form):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   376
        if self.widget is None:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   377
            if self.use_fckeditor(form):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   378
                return FCKEditor()
1573
d34589d35daa drop TextField, this is simply a StringField with a text area widget
sylvain.thenault@logilab.fr
parents: 1564
diff changeset
   379
            widget = TextArea()
d34589d35daa drop TextField, this is simply a StringField with a text area widget
sylvain.thenault@logilab.fr
parents: 1564
diff changeset
   380
            self.init_text_area(widget)
d34589d35daa drop TextField, this is simply a StringField with a text area widget
sylvain.thenault@logilab.fr
parents: 1564
diff changeset
   381
            return widget
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   382
        return self.widget
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   383
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   384
    def get_format_field(self, form):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   385
        if self.format_field:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   386
            return self.format_field
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   387
        # we have to cache generated field since it's use as key in the
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   388
        # context dictionnary
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3388
diff changeset
   389
        req = form._cw
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   390
        try:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   391
            return req.data[self]
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   392
        except KeyError:
2724
7966d87202d7 format field should inherit from parent field's eidparam
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2723
diff changeset
   393
            fkwargs = {'eidparam': self.eidparam}
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   394
            if self.use_fckeditor(form):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   395
                # if fckeditor is used and format field isn't explicitly
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   396
                # deactivated, we want an hidden field for the format
1858
69e41c88e195 connect format field to form_field_format for its initial value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1836
diff changeset
   397
                fkwargs['widget'] = HiddenInput()
4159
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   398
                fkwargs['value'] = 'text/html'
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   399
            else:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   400
                # else we want a format selector
1858
69e41c88e195 connect format field to form_field_format for its initial value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1836
diff changeset
   401
                fkwargs['widget'] = Select()
1095
6917ebe281e9 test and fix guess_field, some pylint fixes
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
   402
                fcstr = FormatConstraint()
3347
428f95118556 fix vocab param to avoid deprecation warning
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3337
diff changeset
   403
                fkwargs['choices'] = fcstr.vocabulary(form=form)
1858
69e41c88e195 connect format field to form_field_format for its initial value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1836
diff changeset
   404
                fkwargs['internationalizable'] = True
4159
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   405
                fkwargs['value'] = self.format
3385
68953ecddd2b [forms] work-in-progress: let guess_field and RichTextField.get_format_field handle eidparam of meta fields
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3384
diff changeset
   406
            fkwargs['eidparam'] = self.eidparam
1858
69e41c88e195 connect format field to form_field_format for its initial value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1836
diff changeset
   407
            field = StringField(name=self.name + '_format', **fkwargs)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   408
            req.data[self] = field
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   409
            return field
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
   410
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   411
    def actual_fields(self, form):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   412
        yield self
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   413
        format_field = self.get_format_field(form)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   414
        if format_field:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   415
            yield format_field
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
   416
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   417
    def use_fckeditor(self, form):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   418
        """return True if fckeditor should be used to edit entity's attribute named
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   419
        `attr`, according to user preferences
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   420
        """
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3388
diff changeset
   421
        if form._cw.use_fckeditor():
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   422
            return form.form_field_format(self) == 'text/html'
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   423
        return False
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   424
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   425
    def render(self, form, renderer):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   426
        format_field = self.get_format_field(form)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   427
        if format_field:
1793
fdac26e003e7 fix vertical alignment pb. with descr. format list and textarea inputs
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 1758
diff changeset
   428
            # XXX we want both fields to remain vertically aligned
2723
d38c2b01d766 don't set display: block on hidden input
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2362
diff changeset
   429
            if format_field.is_visible():
d38c2b01d766 don't set display: block on hidden input
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2362
diff changeset
   430
                format_field.widget.attrs['style'] = 'display: block'
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   431
            result = format_field.render(form, renderer)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   432
        else:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   433
            result = u''
2522
562f5dcf2345 widget.render now takes the renderer as third argument (keeping minimal bw compat)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2520
diff changeset
   434
        return result + self.get_widget(form).render(form, self, renderer)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   435
1417
06af20e663f2 remove spaces
sylvain.thenault@logilab.fr
parents: 1393
diff changeset
   436
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   437
class FileField(StringField):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   438
    widget = FileInput
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   439
    needs_multipart = True
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
   440
3496
35a67ac6efe8 support name metadata on guess_field; add name_field to FileField
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3347
diff changeset
   441
    def __init__(self, format_field=None, encoding_field=None, name_field=None,
35a67ac6efe8 support name metadata on guess_field; add name_field to FileField
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3347
diff changeset
   442
                 **kwargs):
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   443
        super(FileField, self).__init__(**kwargs)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   444
        self.format_field = format_field
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   445
        self.encoding_field = encoding_field
3496
35a67ac6efe8 support name metadata on guess_field; add name_field to FileField
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3347
diff changeset
   446
        self.name_field = name_field
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
   447
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   448
    def actual_fields(self, form):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   449
        yield self
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   450
        if self.format_field:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   451
            yield self.format_field
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   452
        if self.encoding_field:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   453
            yield self.encoding_field
3496
35a67ac6efe8 support name metadata on guess_field; add name_field to FileField
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3347
diff changeset
   454
        if self.name_field:
35a67ac6efe8 support name metadata on guess_field; add name_field to FileField
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3347
diff changeset
   455
            yield self.name_field
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   456
4159
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   457
    def _typed_value(self, form, load_bytes=False):
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   458
        if self.eidparam:
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   459
            if form.edited_entity.has_eid():
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   460
                if load_bytes:
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   461
                    return getattr(form.edited_entity, self.name)
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   462
                # don't actually load data
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   463
                # XXX value should reflect if some file is already attached
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   464
                # * try to display name metadata
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   465
                # * check length(data) / data != null
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   466
                return True
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   467
            return False
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   468
        return super(FileField, self)._typed_value(form, load_bytes)
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   469
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   470
    def render(self, form, renderer):
2522
562f5dcf2345 widget.render now takes the renderer as third argument (keeping minimal bw compat)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2520
diff changeset
   471
        wdgs = [self.get_widget(form).render(form, self, renderer)]
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   472
        if self.format_field or self.encoding_field:
4156
1bbb0ee42c8e drop form_field_name/form_field_id methods from form object, in favor of field.input_name(form) / field.dom_id(form)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4110
diff changeset
   473
            divid = '%s-advanced' % self.input_name(form)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   474
            wdgs.append(u'<a href="%s" title="%s"><img src="%s" alt="%s"/></a>' %
2312
af4d8f75c5db use xml_escape
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2244
diff changeset
   475
                        (xml_escape(uilib.toggle_action(divid)),
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3388
diff changeset
   476
                         form._cw._('show advanced fields'),
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3388
diff changeset
   477
                         xml_escape(form._cw.build_url('data/puce_down.png')),
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3388
diff changeset
   478
                         form._cw._('show advanced fields')))
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   479
            wdgs.append(u'<div id="%s" class="hidden">' % divid)
3496
35a67ac6efe8 support name metadata on guess_field; add name_field to FileField
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3347
diff changeset
   480
            if self.name_field:
35a67ac6efe8 support name metadata on guess_field; add name_field to FileField
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3347
diff changeset
   481
                wdgs.append(self.render_subfield(form, self.name_field, renderer))
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   482
            if self.format_field:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   483
                wdgs.append(self.render_subfield(form, self.format_field, renderer))
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   484
            if self.encoding_field:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   485
                wdgs.append(self.render_subfield(form, self.encoding_field, renderer))
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
   486
            wdgs.append(u'</div>')
4159
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   487
        if not self.required and self.display_value(form):
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   488
            # trick to be able to delete an uploaded file
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   489
            wdgs.append(u'<br/>')
4156
1bbb0ee42c8e drop form_field_name/form_field_id methods from form object, in favor of field.input_name(form) / field.dom_id(form)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4110
diff changeset
   490
            wdgs.append(tags.input(name=self.input_name(form, u'__detach'),
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   491
                                   type=u'checkbox'))
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3388
diff changeset
   492
            wdgs.append(form._cw._('detach attached file'))
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   493
        return u'\n'.join(wdgs)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   494
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   495
    def render_subfield(self, form, field, renderer):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   496
        return (renderer.render_label(form, field)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   497
                + field.render(form, renderer)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   498
                + renderer.render_help(form, field)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   499
                + u'<br/>')
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   500
3387
a357d4147eee [forms] work-in-progress, big editcontroller refactoring: let fields/widgets process posted data
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3385
diff changeset
   501
    def process_form_value(self, form):
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3388
diff changeset
   502
        posted = form._cw.form
4156
1bbb0ee42c8e drop form_field_name/form_field_id methods from form object, in favor of field.input_name(form) / field.dom_id(form)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4110
diff changeset
   503
        if self.input_name(form, u'__detach') in posted:
3387
a357d4147eee [forms] work-in-progress, big editcontroller refactoring: let fields/widgets process posted data
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3385
diff changeset
   504
            # drop current file value
a357d4147eee [forms] work-in-progress, big editcontroller refactoring: let fields/widgets process posted data
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3385
diff changeset
   505
            value = None
4156
1bbb0ee42c8e drop form_field_name/form_field_id methods from form object, in favor of field.input_name(form) / field.dom_id(form)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4110
diff changeset
   506
        else:
1bbb0ee42c8e drop form_field_name/form_field_id methods from form object, in favor of field.input_name(form) / field.dom_id(form)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4110
diff changeset
   507
            value = posted.get(self.input_name(form))
3387
a357d4147eee [forms] work-in-progress, big editcontroller refactoring: let fields/widgets process posted data
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3385
diff changeset
   508
        # no need to check value when nor explicit detach nor new file
a357d4147eee [forms] work-in-progress, big editcontroller refactoring: let fields/widgets process posted data
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3385
diff changeset
   509
        # submitted, since it will think the attribute is not modified
a357d4147eee [forms] work-in-progress, big editcontroller refactoring: let fields/widgets process posted data
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3385
diff changeset
   510
        elif value:
a357d4147eee [forms] work-in-progress, big editcontroller refactoring: let fields/widgets process posted data
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3385
diff changeset
   511
            filename, _, stream = value
a357d4147eee [forms] work-in-progress, big editcontroller refactoring: let fields/widgets process posted data
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3385
diff changeset
   512
            # value is a  3-uple (filename, mimetype, stream)
a357d4147eee [forms] work-in-progress, big editcontroller refactoring: let fields/widgets process posted data
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3385
diff changeset
   513
            value = Binary(stream.read())
a357d4147eee [forms] work-in-progress, big editcontroller refactoring: let fields/widgets process posted data
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3385
diff changeset
   514
            if not val.getvalue(): # usually an unexistant file
a357d4147eee [forms] work-in-progress, big editcontroller refactoring: let fields/widgets process posted data
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3385
diff changeset
   515
                value = None
a357d4147eee [forms] work-in-progress, big editcontroller refactoring: let fields/widgets process posted data
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3385
diff changeset
   516
            else:
a357d4147eee [forms] work-in-progress, big editcontroller refactoring: let fields/widgets process posted data
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3385
diff changeset
   517
                value.filename = filename
a357d4147eee [forms] work-in-progress, big editcontroller refactoring: let fields/widgets process posted data
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3385
diff changeset
   518
        return value
a357d4147eee [forms] work-in-progress, big editcontroller refactoring: let fields/widgets process posted data
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3385
diff changeset
   519
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
   520
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   521
class EditableFileField(FileField):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   522
    editable_formats = ('text/plain', 'text/html', 'text/rest')
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
   523
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   524
    def render(self, form, renderer):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   525
        wdgs = [super(EditableFileField, self).render(form, renderer)]
4159
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   526
        if self.format(form) in self.editable_formats:
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   527
            data = self.typed_value(form, load_bytes=True)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   528
            if data:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   529
                encoding = form.form_field_encoding(self)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   530
                try:
4159
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   531
                    form.formvalues[self] = unicode(data.getvalue(), encoding)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   532
                except UnicodeError:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   533
                    pass
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   534
                else:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   535
                    if not self.required:
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3388
diff changeset
   536
                        msg = form._cw._(
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   537
                            'You can either submit a new file using the browse button above'
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   538
                            ', or choose to remove already uploaded file by checking the '
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   539
                            '"detach attached file" check-box, or edit file content online '
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   540
                            'with the widget below.')
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   541
                    else:
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3388
diff changeset
   542
                        msg = form._cw._(
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   543
                            'You can either submit a new file using the browse button above'
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   544
                            ', or edit file content online with the widget below.')
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   545
                    wdgs.append(u'<p><b>%s</b></p>' % msg)
2522
562f5dcf2345 widget.render now takes the renderer as third argument (keeping minimal bw compat)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2520
diff changeset
   546
                    wdgs.append(TextArea(setdomid=False).render(form, self, renderer))
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   547
                    # XXX restore form context?
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   548
        return '\n'.join(wdgs)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   549
3387
a357d4147eee [forms] work-in-progress, big editcontroller refactoring: let fields/widgets process posted data
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3385
diff changeset
   550
    def process_form_value(self, form):
4156
1bbb0ee42c8e drop form_field_name/form_field_id methods from form object, in favor of field.input_name(form) / field.dom_id(form)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4110
diff changeset
   551
        value = form._cw.form.get(self.input_name(form))
3387
a357d4147eee [forms] work-in-progress, big editcontroller refactoring: let fields/widgets process posted data
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3385
diff changeset
   552
        if isinstance(value, unicode):
a357d4147eee [forms] work-in-progress, big editcontroller refactoring: let fields/widgets process posted data
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3385
diff changeset
   553
            # file modified using a text widget
a357d4147eee [forms] work-in-progress, big editcontroller refactoring: let fields/widgets process posted data
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3385
diff changeset
   554
            encoding = form.form_field_encoding(self)
a357d4147eee [forms] work-in-progress, big editcontroller refactoring: let fields/widgets process posted data
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3385
diff changeset
   555
            return Binary(value.encode(encoding))
a357d4147eee [forms] work-in-progress, big editcontroller refactoring: let fields/widgets process posted data
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3385
diff changeset
   556
        return super(EditableFileField, self).process_form_value(form)
a357d4147eee [forms] work-in-progress, big editcontroller refactoring: let fields/widgets process posted data
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3385
diff changeset
   557
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
   558
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   559
class IntField(Field):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   560
    def __init__(self, min=None, max=None, **kwargs):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   561
        super(IntField, self).__init__(**kwargs)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   562
        self.min = min
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   563
        self.max = max
1758
d46f59e5efd3 some widget adjustments
sylvain.thenault@logilab.fr
parents: 1738
diff changeset
   564
        if isinstance(self.widget, TextInput):
d46f59e5efd3 some widget adjustments
sylvain.thenault@logilab.fr
parents: 1738
diff changeset
   565
            self.widget.attrs.setdefault('size', 5)
d46f59e5efd3 some widget adjustments
sylvain.thenault@logilab.fr
parents: 1738
diff changeset
   566
            self.widget.attrs.setdefault('maxlength', 15)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   567
3387
a357d4147eee [forms] work-in-progress, big editcontroller refactoring: let fields/widgets process posted data
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3385
diff changeset
   568
    def process_form_value(self, form):
a357d4147eee [forms] work-in-progress, big editcontroller refactoring: let fields/widgets process posted data
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3385
diff changeset
   569
        return int(Field.process_form_value(self, form))
1986
96c0e56cb0cf move widget selection's logic on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   570
4160
3fbdeef9a610 cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4159
diff changeset
   571
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   572
class BooleanField(Field):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   573
    widget = Radio
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
   574
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   575
    def vocabulary(self, form):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   576
        if self.choices:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   577
            return self.choices
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3388
diff changeset
   578
        return [(form._cw._('yes'), '1'), (form._cw._('no'), '')]
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   579
3387
a357d4147eee [forms] work-in-progress, big editcontroller refactoring: let fields/widgets process posted data
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3385
diff changeset
   580
    def process_form_value(self, form):
a357d4147eee [forms] work-in-progress, big editcontroller refactoring: let fields/widgets process posted data
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3385
diff changeset
   581
        return bool(Field.process_form_value(self, form))
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   582
4160
3fbdeef9a610 cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4159
diff changeset
   583
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
   584
class FloatField(IntField):
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   585
    def format_single_value(self, req, value):
1095
6917ebe281e9 test and fix guess_field, some pylint fixes
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
   586
        formatstr = req.property_value('ui.float-format')
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   587
        if value is None:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   588
            return u''
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   589
        return formatstr % float(value)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   590
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   591
    def render_example(self, req):
2086
be76ce00a05e fix TimeField format_prop, use format_single_value directly in render_example
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1989
diff changeset
   592
        return self.format_single_value(req, 1.234)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   593
3387
a357d4147eee [forms] work-in-progress, big editcontroller refactoring: let fields/widgets process posted data
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3385
diff changeset
   594
    def process_form_value(self, form):
a357d4147eee [forms] work-in-progress, big editcontroller refactoring: let fields/widgets process posted data
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3385
diff changeset
   595
        return float(Field.process_form_value(self, form))
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   596
4160
3fbdeef9a610 cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4159
diff changeset
   597
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   598
class DateField(StringField):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   599
    format_prop = 'ui.date-format'
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   600
    widget = DateTimePicker
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
   601
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   602
    def format_single_value(self, req, value):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   603
        return value and ustrftime(value, req.property_value(self.format_prop)) or u''
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   604
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   605
    def render_example(self, req):
2086
be76ce00a05e fix TimeField format_prop, use format_single_value directly in render_example
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1989
diff changeset
   606
        return self.format_single_value(req, datetime.now())
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   607
3387
a357d4147eee [forms] work-in-progress, big editcontroller refactoring: let fields/widgets process posted data
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3385
diff changeset
   608
    def process_form_value(self, form):
a357d4147eee [forms] work-in-progress, big editcontroller refactoring: let fields/widgets process posted data
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3385
diff changeset
   609
        # widget is supposed to return a date as a correctly formatted string
a357d4147eee [forms] work-in-progress, big editcontroller refactoring: let fields/widgets process posted data
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3385
diff changeset
   610
        date = Field.process_form_value(self, form)
a357d4147eee [forms] work-in-progress, big editcontroller refactoring: let fields/widgets process posted data
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3385
diff changeset
   611
        # but for some widgets, it might be simpler to return date objects
a357d4147eee [forms] work-in-progress, big editcontroller refactoring: let fields/widgets process posted data
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3385
diff changeset
   612
        # directly, so handle that case :
a357d4147eee [forms] work-in-progress, big editcontroller refactoring: let fields/widgets process posted data
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3385
diff changeset
   613
        if isinstance(date, basestring):
a357d4147eee [forms] work-in-progress, big editcontroller refactoring: let fields/widgets process posted data
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3385
diff changeset
   614
            date = form.parse_date(wdgdate, 'Date')
a357d4147eee [forms] work-in-progress, big editcontroller refactoring: let fields/widgets process posted data
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3385
diff changeset
   615
        return date
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   616
4160
3fbdeef9a610 cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4159
diff changeset
   617
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   618
class DateTimeField(DateField):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   619
    format_prop = 'ui.datetime-format'
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   620
3387
a357d4147eee [forms] work-in-progress, big editcontroller refactoring: let fields/widgets process posted data
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3385
diff changeset
   621
    def process_form_value(self, form):
a357d4147eee [forms] work-in-progress, big editcontroller refactoring: let fields/widgets process posted data
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3385
diff changeset
   622
        # widget is supposed to return a date as a correctly formatted string
a357d4147eee [forms] work-in-progress, big editcontroller refactoring: let fields/widgets process posted data
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3385
diff changeset
   623
        date = Field.process_form_value(self, form)
a357d4147eee [forms] work-in-progress, big editcontroller refactoring: let fields/widgets process posted data
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3385
diff changeset
   624
        # but for some widgets, it might be simpler to return date objects
a357d4147eee [forms] work-in-progress, big editcontroller refactoring: let fields/widgets process posted data
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3385
diff changeset
   625
        # directly, so handle that case :
a357d4147eee [forms] work-in-progress, big editcontroller refactoring: let fields/widgets process posted data
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3385
diff changeset
   626
        if isinstance(date, basestring):
4101
7fa86fa51229 [mq]: fix_typo_and_forms
Arthur Lutz <arthur.lutz@logilab.fr>
parents: 4069
diff changeset
   627
            date = form.parse_datetime(date, 'Datetime')
3387
a357d4147eee [forms] work-in-progress, big editcontroller refactoring: let fields/widgets process posted data
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3385
diff changeset
   628
        return date
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   629
4160
3fbdeef9a610 cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4159
diff changeset
   630
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   631
class TimeField(DateField):
2086
be76ce00a05e fix TimeField format_prop, use format_single_value directly in render_example
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1989
diff changeset
   632
    format_prop = 'ui.time-format'
1758
d46f59e5efd3 some widget adjustments
sylvain.thenault@logilab.fr
parents: 1738
diff changeset
   633
    widget = TextInput
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   634
3387
a357d4147eee [forms] work-in-progress, big editcontroller refactoring: let fields/widgets process posted data
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3385
diff changeset
   635
    def process_form_value(self, form):
a357d4147eee [forms] work-in-progress, big editcontroller refactoring: let fields/widgets process posted data
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3385
diff changeset
   636
        # widget is supposed to return a date as a correctly formatted string
a357d4147eee [forms] work-in-progress, big editcontroller refactoring: let fields/widgets process posted data
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3385
diff changeset
   637
        time = Field.process_form_value(self, form)
a357d4147eee [forms] work-in-progress, big editcontroller refactoring: let fields/widgets process posted data
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3385
diff changeset
   638
        # but for some widgets, it might be simpler to return time objects
a357d4147eee [forms] work-in-progress, big editcontroller refactoring: let fields/widgets process posted data
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3385
diff changeset
   639
        # directly, so handle that case :
a357d4147eee [forms] work-in-progress, big editcontroller refactoring: let fields/widgets process posted data
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3385
diff changeset
   640
        if isinstance(time, basestring):
a357d4147eee [forms] work-in-progress, big editcontroller refactoring: let fields/widgets process posted data
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3385
diff changeset
   641
            time = form.parse_time(wdgdate, 'Time')
a357d4147eee [forms] work-in-progress, big editcontroller refactoring: let fields/widgets process posted data
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3385
diff changeset
   642
        return time
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
   643
4161
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   644
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   645
# relation vocabulary helper functions #########################################
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   646
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   647
def relvoc_linkedto(entity, rtype, role):
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   648
    # first see if its specified by __linkto form parameters
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   649
    linkedto = entity.linked_to(rtype, role)
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   650
    if linkedto:
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   651
        buildent = entity._cw.entity_from_eid
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   652
        return [(buildent(eid).view('combobox'), eid) for eid in linkedto]
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   653
    return []
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   654
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   655
def relvoc_init(entity, rtype, role, required=False):
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   656
    # it isn't, check if the entity provides a method to get correct values
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   657
    vocab = []
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   658
    if not required:
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   659
        vocab.append(('', INTERNAL_FIELD_VALUE))
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   660
    # vocabulary doesn't include current values, add them
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   661
    if entity.has_eid():
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   662
        rset = entity.related(rtype, role)
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   663
        vocab += [(e.view('combobox'), e.eid) for e in rset.entities()]
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   664
    return vocab
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   665
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   666
def relvoc_unrelated(entity, rtype, role, limit=None):
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   667
    if isinstance(rtype, basestring):
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   668
        rtype = entity._cw.vreg.schema.rschema(rtype)
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   669
    if entity.has_eid():
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   670
        done = set(row[0] for row in entity.related(rtype, role))
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   671
    else:
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   672
        done = None
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   673
    result = []
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   674
    rsetsize = None
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   675
    for objtype in rtype.targets(entity.e_schema, role):
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   676
        if limit is not None:
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   677
            rsetsize = limit - len(result)
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   678
        result += _relvoc_unrelated(entity, rtype, objtype, role, rsetsize, done)
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   679
        if limit is not None and len(result) >= limit:
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   680
            break
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   681
    return result
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   682
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   683
def _relvoc_unrelated(entity, rtype, targettype, role, limit, done):
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   684
    """return unrelated entities for a given relation and target entity type
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   685
    for use in vocabulary
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   686
    """
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   687
    if done is None:
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   688
        done = set()
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   689
    res = []
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   690
    for entity in entity.unrelated(rtype, targettype, role, limit).entities():
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   691
        if entity.eid in done:
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   692
            continue
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   693
        done.add(entity.eid)
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   694
        res.append((entity.view('combobox'), entity.eid))
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   695
    return res
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   696
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   697
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   698
class RelationField(Field):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   699
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   700
    @staticmethod
1095
6917ebe281e9 test and fix guess_field, some pylint fixes
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
   701
    def fromcardinality(card, **kwargs):
1738
2cfd50c8a415 should not override potential explicit widget
sylvain.thenault@logilab.fr
parents: 1709
diff changeset
   702
        kwargs.setdefault('widget', Select(multiple=card in '*+'))
2cfd50c8a415 should not override potential explicit widget
sylvain.thenault@logilab.fr
parents: 1709
diff changeset
   703
        return RelationField(**kwargs)
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
   704
4161
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   705
    def choices(self, form, limit=None):
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1108
diff changeset
   706
        entity = form.edited_entity
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   707
        # first see if its specified by __linkto form parameters
4161
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   708
        linkedto = relvoc_linkedto(entity, self.name, self.role)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   709
        if linkedto:
4161
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   710
            return linkedto
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   711
        # it isn't, check if the entity provides a method to get correct values
4161
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   712
        vocab = relvoc_init(entity, self.name, self.role, self.required)
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   713
        method = '%s_%s_vocabulary' % (self.role, self.name)
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   714
        try:
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   715
            vocab += getattr(form, method)(rtype, limit)
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   716
            warn('[3.6] found %s on %s, should override field.choices instead (need tweaks)'
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   717
                 % (method, form), DeprecationWarning)
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   718
        except AttributeError:
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   719
            vocab += relvoc_unrelated(entity, self.name, self.role, limit)
1562
e6d2c07c0c58 [forms/widgets] fix relation field not sorting its vocabulary, revert hack on Select widget
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 1505
diff changeset
   720
        if self.sort:
3334
8d831c02da9a fix sort of fields vocabulary: should consider option groups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3308
diff changeset
   721
            vocab = vocab_sort(vocab)
1562
e6d2c07c0c58 [forms/widgets] fix relation field not sorting its vocabulary, revert hack on Select widget
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 1505
diff changeset
   722
        return vocab
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
   723
4159
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   724
    def form_init(self, form):
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   725
        if not self.display_value(form):
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   726
            value = form.edited_entity.linked_to(self.name, self.role)
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   727
            if value:
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   728
                searchedvalues = ['%s:%s:%s' % (self.name, eid, self.role)
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   729
                                  for eid in value]
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   730
                # remove associated __linkto hidden fields
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   731
                for field in form.root_form.fields_by_name('__linkto'):
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   732
                    if field.value in searchedvalues:
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   733
                        form.root_form.remove_field(field)
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   734
                form.formvalues[self] = value
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   735
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   736
    def _typed_value(self, form, load_bytes=False):
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   737
        entity = form.edited_entity
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   738
        # non final relation field
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   739
        if entity.has_eid() or entity.relation_cached(self.name, self.role):
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   740
            return [r[0] for r in entity.related(self.name, self.role)]
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   741
        return ()
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   742
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   743
    def format_single_value(self, req, value):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   744
        return value
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   745
4110
8728d8c95985 [mq]: fix_for_forms
Arthur Lutz <arthur.lutz@logilab.fr>
parents: 4101
diff changeset
   746
    def process_form_value(self, form):
8728d8c95985 [mq]: fix_for_forms
Arthur Lutz <arthur.lutz@logilab.fr>
parents: 4101
diff changeset
   747
        """process posted form and return correctly typed value"""
8728d8c95985 [mq]: fix_for_forms
Arthur Lutz <arthur.lutz@logilab.fr>
parents: 4101
diff changeset
   748
        widget = self.get_widget(form)
8728d8c95985 [mq]: fix_for_forms
Arthur Lutz <arthur.lutz@logilab.fr>
parents: 4101
diff changeset
   749
        value = widget.process_field_data(form, self)
8728d8c95985 [mq]: fix_for_forms
Arthur Lutz <arthur.lutz@logilab.fr>
parents: 4101
diff changeset
   750
        if value is None:
8728d8c95985 [mq]: fix_for_forms
Arthur Lutz <arthur.lutz@logilab.fr>
parents: 4101
diff changeset
   751
            return ()
8728d8c95985 [mq]: fix_for_forms
Arthur Lutz <arthur.lutz@logilab.fr>
parents: 4101
diff changeset
   752
        elif not isinstance(value, list):
8728d8c95985 [mq]: fix_for_forms
Arthur Lutz <arthur.lutz@logilab.fr>
parents: 4101
diff changeset
   753
            return (value,)
8728d8c95985 [mq]: fix_for_forms
Arthur Lutz <arthur.lutz@logilab.fr>
parents: 4101
diff changeset
   754
        return value
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   755
2523
1d245fbbeb90 some new field/widgets classes: CompoundField, IntervalWidget, HorizontalLayoutWidget
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2522
diff changeset
   756
class CompoundField(Field):
1d245fbbeb90 some new field/widgets classes: CompoundField, IntervalWidget, HorizontalLayoutWidget
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2522
diff changeset
   757
    def __init__(self, fields, *args, **kwargs):
1d245fbbeb90 some new field/widgets classes: CompoundField, IntervalWidget, HorizontalLayoutWidget
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2522
diff changeset
   758
        super(CompoundField, self).__init__(*args, **kwargs)
1d245fbbeb90 some new field/widgets classes: CompoundField, IntervalWidget, HorizontalLayoutWidget
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2522
diff changeset
   759
        self.fields = fields
1d245fbbeb90 some new field/widgets classes: CompoundField, IntervalWidget, HorizontalLayoutWidget
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2522
diff changeset
   760
2549
3d8c62e5e2d4 [R forms] use a subfields(form) method to get a chance to adapt to context
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2523
diff changeset
   761
    def subfields(self, form):
3d8c62e5e2d4 [R forms] use a subfields(form) method to get a chance to adapt to context
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2523
diff changeset
   762
        return self.fields
2568
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2549
diff changeset
   763
2523
1d245fbbeb90 some new field/widgets classes: CompoundField, IntervalWidget, HorizontalLayoutWidget
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2522
diff changeset
   764
    def actual_fields(self, form):
1d245fbbeb90 some new field/widgets classes: CompoundField, IntervalWidget, HorizontalLayoutWidget
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2522
diff changeset
   765
        return [self] + list(self.fields)
1d245fbbeb90 some new field/widgets classes: CompoundField, IntervalWidget, HorizontalLayoutWidget
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2522
diff changeset
   766
1d245fbbeb90 some new field/widgets classes: CompoundField, IntervalWidget, HorizontalLayoutWidget
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2522
diff changeset
   767
1453
a9841184be7c guess_field now takes an entity schema as first argument, not an entity class
sylvain.thenault@logilab.fr
parents: 1437
diff changeset
   768
def guess_field(eschema, rschema, role='subject', skip_meta_attr=True, **kwargs):
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   769
    """return the most adapated widget to edit the relation
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   770
    'subjschema rschema objschema' according to information found in the schema
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   771
    """
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   772
    fieldclass = None
4014
24f7d7eb4c23 yams api update
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3890
diff changeset
   773
    rdef = eschema.rdef(rschema, role)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   774
    if role == 'subject':
4014
24f7d7eb4c23 yams api update
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3890
diff changeset
   775
        targetschema = rdef.object
3689
deb13e88e037 follow yams 0.25 api changes to improve performance
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3575
diff changeset
   776
        if rschema.final:
4069
5d149ba65dd0 fix guess_field to handle non internationalizable definition
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 4044
diff changeset
   777
            if rdef.get('internationalizable'):
2095
897732d3ee5a avoid overriding specified values when guessing field
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2091
diff changeset
   778
                kwargs.setdefault('internationalizable', True)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   779
    else:
4014
24f7d7eb4c23 yams api update
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3890
diff changeset
   780
        targetschema = rdef.subject
4044
3876c894e018 card referenced later
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4023
diff changeset
   781
    card = rdef.role_cardinality(role)
3876c894e018 card referenced later
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4023
diff changeset
   782
    kwargs['required'] = card in '1+'
1095
6917ebe281e9 test and fix guess_field, some pylint fixes
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
   783
    kwargs['name'] = rschema.type
3308
88f5f89d8d1b fix generated label for object relation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3299
diff changeset
   784
    if role == 'object':
3574
f179ccbd13e6 [forms] fix generated label for fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3563
diff changeset
   785
        kwargs.setdefault('label', (eschema.type, rschema.type + '_object'))
3308
88f5f89d8d1b fix generated label for object relation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3299
diff changeset
   786
    else:
3574
f179ccbd13e6 [forms] fix generated label for fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3563
diff changeset
   787
        kwargs.setdefault('label', (eschema.type, rschema.type))
3385
68953ecddd2b [forms] work-in-progress: let guess_field and RichTextField.get_format_field handle eidparam of meta fields
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3384
diff changeset
   788
    kwargs['eidparam'] = True
4014
24f7d7eb4c23 yams api update
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3890
diff changeset
   789
    kwargs.setdefault('help', rdef.description)
3689
deb13e88e037 follow yams 0.25 api changes to improve performance
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3575
diff changeset
   790
    if rschema.final:
1104
58f27c3c0167 more guess_field tests and fixes
sylvain.thenault@logilab.fr
parents: 1101
diff changeset
   791
        if skip_meta_attr and rschema in eschema.meta_attributes():
1095
6917ebe281e9 test and fix guess_field, some pylint fixes
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
   792
            return None
6917ebe281e9 test and fix guess_field, some pylint fixes
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
   793
        fieldclass = FIELDS[targetschema]
6917ebe281e9 test and fix guess_field, some pylint fixes
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
   794
        if fieldclass is StringField:
1104
58f27c3c0167 more guess_field tests and fixes
sylvain.thenault@logilab.fr
parents: 1101
diff changeset
   795
            if eschema.has_metadata(rschema, 'format'):
58f27c3c0167 more guess_field tests and fixes
sylvain.thenault@logilab.fr
parents: 1101
diff changeset
   796
                # use RichTextField instead of StringField if the attribute has
58f27c3c0167 more guess_field tests and fixes
sylvain.thenault@logilab.fr
parents: 1101
diff changeset
   797
                # a "format" metadata. But getting information from constraints
58f27c3c0167 more guess_field tests and fixes
sylvain.thenault@logilab.fr
parents: 1101
diff changeset
   798
                # may be useful anyway...
4014
24f7d7eb4c23 yams api update
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3890
diff changeset
   799
                for cstr in rdef.constraints:
1104
58f27c3c0167 more guess_field tests and fixes
sylvain.thenault@logilab.fr
parents: 1101
diff changeset
   800
                    if isinstance(cstr, StaticVocabularyConstraint):
58f27c3c0167 more guess_field tests and fixes
sylvain.thenault@logilab.fr
parents: 1101
diff changeset
   801
                        raise Exception('rich text field with static vocabulary')
58f27c3c0167 more guess_field tests and fixes
sylvain.thenault@logilab.fr
parents: 1101
diff changeset
   802
                return RichTextField(**kwargs)
1574
0c6dbb774f54 drop text field usage
sylvain.thenault@logilab.fr
parents: 1573
diff changeset
   803
            # init StringField parameters according to constraints
4014
24f7d7eb4c23 yams api update
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3890
diff changeset
   804
            for cstr in rdef.constraints:
1574
0c6dbb774f54 drop text field usage
sylvain.thenault@logilab.fr
parents: 1573
diff changeset
   805
                if isinstance(cstr, StaticVocabularyConstraint):
1577
25b46db3cb81 should set field's choices
sylvain.thenault@logilab.fr
parents: 1574
diff changeset
   806
                    kwargs.setdefault('choices', cstr.vocabulary)
1986
96c0e56cb0cf move widget selection's logic on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   807
                    break
4014
24f7d7eb4c23 yams api update
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3890
diff changeset
   808
            for cstr in rdef.constraints:
1574
0c6dbb774f54 drop text field usage
sylvain.thenault@logilab.fr
parents: 1573
diff changeset
   809
                if isinstance(cstr, SizeConstraint) and cstr.max is not None:
0c6dbb774f54 drop text field usage
sylvain.thenault@logilab.fr
parents: 1573
diff changeset
   810
                    kwargs['max_length'] = cstr.max
0c6dbb774f54 drop text field usage
sylvain.thenault@logilab.fr
parents: 1573
diff changeset
   811
            return StringField(**kwargs)
1104
58f27c3c0167 more guess_field tests and fixes
sylvain.thenault@logilab.fr
parents: 1101
diff changeset
   812
        if fieldclass is FileField:
4160
3fbdeef9a610 cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4159
diff changeset
   813
            for metadata in KNOWN_METAATTRIBUTES:
1104
58f27c3c0167 more guess_field tests and fixes
sylvain.thenault@logilab.fr
parents: 1101
diff changeset
   814
                metaschema = eschema.has_metadata(rschema, metadata)
58f27c3c0167 more guess_field tests and fixes
sylvain.thenault@logilab.fr
parents: 1101
diff changeset
   815
                if metaschema is not None:
1453
a9841184be7c guess_field now takes an entity schema as first argument, not an entity class
sylvain.thenault@logilab.fr
parents: 1437
diff changeset
   816
                    kwargs['%s_field' % metadata] = guess_field(eschema, metaschema,
1104
58f27c3c0167 more guess_field tests and fixes
sylvain.thenault@logilab.fr
parents: 1101
diff changeset
   817
                                                                skip_meta_attr=False)
1095
6917ebe281e9 test and fix guess_field, some pylint fixes
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
   818
        return fieldclass(**kwargs)
6917ebe281e9 test and fix guess_field, some pylint fixes
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
   819
    kwargs['role'] = role
6917ebe281e9 test and fix guess_field, some pylint fixes
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
   820
    return RelationField.fromcardinality(card, **kwargs)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   821
1986
96c0e56cb0cf move widget selection's logic on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   822
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   823
FIELDS = {
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   824
    'Boolean':  BooleanField,
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   825
    'Bytes':    FileField,
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   826
    'Date':     DateField,
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   827
    'Datetime': DateTimeField,
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   828
    'Int':      IntField,
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   829
    'Float':    FloatField,
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   830
    'Decimal':  StringField,
4159
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   831
    'Password': PasswordField,
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   832
    'String' :  StringField,
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   833
    'Time':     TimeField,
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   834
    }