web/formfields.py
author Sylvain Thénault <sylvain.thenault@logilab.fr>
Thu, 18 Feb 2010 10:54:50 +0100
branchstable
changeset 4624 1b46d5ece0d5
parent 4583 356f08325072
child 4628 2f23148d0870
permissions -rw-r--r--
turn default logging threshold to warning (we usually want them), and log 'no schema for eid' pb using warning instead of error, so we see them in logs but not during migration
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
4443
83ff2bb898a5 start documenting forms
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4395
diff changeset
     1
"""Fields are used to control what's displayed in forms. It makes the link
83ff2bb898a5 start documenting forms
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4395
diff changeset
     2
between something to edit and its display in the form. Actual display is handled
83ff2bb898a5 start documenting forms
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4395
diff changeset
     3
by a widget associated to the field.
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
     4
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
     5
:organization: Logilab
4215
9fbc39453012 [forms] make it easier to override StringField's mininum size
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 4212
diff changeset
     6
:copyright: 2009-2010 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
     7
: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
     8
: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
     9
"""
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
    10
__docformat__ = "restructuredtext en"
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
    11
2244
52e2431e7cce missing import
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2196
diff changeset
    12
from warnings import warn
1095
6917ebe281e9 test and fix guess_field, some pylint fixes
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
    13
from datetime import datetime
6917ebe281e9 test and fix guess_field, some pylint fixes
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
    14
2312
af4d8f75c5db use xml_escape
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2244
diff changeset
    15
from logilab.mtconverter import xml_escape
4481
56440a1f816a hidden usage of datetime function which has been moved to lgc
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4443
diff changeset
    16
from logilab.common.date import ustrftime
4158
0e97cf2cf55b missing imports
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4156
diff changeset
    17
from logilab.common.decorators import cached
0e97cf2cf55b missing imports
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4156
diff changeset
    18
4160
3fbdeef9a610 cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4159
diff changeset
    19
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
    20
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
    21
                              FormatConstraint)
1095
6917ebe281e9 test and fix guess_field, some pylint fixes
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
    22
4481
56440a1f816a hidden usage of datetime function which has been moved to lgc
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4443
diff changeset
    23
from cubicweb import Binary, tags, uilib
4368
d752ad901f14 cleanup module namespace but only importing the formwidgets module
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4359
diff changeset
    24
from cubicweb.web import INTERNAL_FIELD_VALUE, ProcessFormError, eid_param, \
d752ad901f14 cleanup module namespace but only importing the formwidgets module
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4359
diff changeset
    25
     formwidgets as fw
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
4251
3c6569be1f86 fix pb with bytes field processing: currently when an existing file is edited
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4241
diff changeset
    28
class UnmodifiedField(Exception):
3c6569be1f86 fix pb with bytes field processing: currently when an existing file is edited
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4241
diff changeset
    29
    """raise this when a field has not actually been edited and you want to skip
3c6569be1f86 fix pb with bytes field processing: currently when an existing file is edited
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4241
diff changeset
    30
    it
3c6569be1f86 fix pb with bytes field processing: currently when an existing file is edited
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4241
diff changeset
    31
    """
3c6569be1f86 fix pb with bytes field processing: currently when an existing file is edited
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4241
diff changeset
    32
3c6569be1f86 fix pb with bytes field processing: currently when an existing file is edited
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4241
diff changeset
    33
3334
8d831c02da9a fix sort of fields vocabulary: should consider option groups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3308
diff changeset
    34
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
    35
    """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
    36
    result = []
8d831c02da9a fix sort of fields vocabulary: should consider option groups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3308
diff changeset
    37
    partresult = []
8d831c02da9a fix sort of fields vocabulary: should consider option groups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3308
diff changeset
    38
    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
    39
        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
    40
            if partresult:
8d831c02da9a fix sort of fields vocabulary: should consider option groups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3308
diff changeset
    41
                result += sorted(partresult)
8d831c02da9a fix sort of fields vocabulary: should consider option groups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3308
diff changeset
    42
                partresult = []
8d831c02da9a fix sort of fields vocabulary: should consider option groups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3308
diff changeset
    43
            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
    44
        else:
8d831c02da9a fix sort of fields vocabulary: should consider option groups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3308
diff changeset
    45
            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
    46
    result += sorted(partresult)
8d831c02da9a fix sort of fields vocabulary: should consider option groups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3308
diff changeset
    47
    return result
8d831c02da9a fix sort of fields vocabulary: should consider option groups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3308
diff changeset
    48
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
    49
_MARKER = object()
3334
8d831c02da9a fix sort of fields vocabulary: should consider option groups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3308
diff changeset
    50
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
    51
class Field(object):
4443
83ff2bb898a5 start documenting forms
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4395
diff changeset
    52
    """This class is the abstract base class for all fields. It hold a bunch
83ff2bb898a5 start documenting forms
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4395
diff changeset
    53
    of attributes which may be used for fine control of the behaviour of a
83ff2bb898a5 start documenting forms
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4395
diff changeset
    54
    concret field.
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
4443
83ff2bb898a5 start documenting forms
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4395
diff changeset
    56
    All the attributes described below have sensible default value which may be
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
    57
    overriden by value given to field's constructor.
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
    58
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
    59
    :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
    60
       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
    61
    :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
    62
       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
    63
       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
    64
    :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
    65
       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
    66
    :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
    67
       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
    68
    :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
    69
       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
    70
       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
    71
    :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
    72
       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
    73
    :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
    74
       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
    75
    :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
    76
       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
    77
       (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
    78
    :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
    79
       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
    80
       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
    81
       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
    82
    :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
    83
       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
    84
       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
    85
    :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
    86
       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
    87
    :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
    88
       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
    89
       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
    90
    :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
    91
       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
    92
    :order:
7d0d4a6be046 [formfields] allow fields ordering with autoform_field_kwargs
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3873
diff changeset
    93
       key used by automatic forms to sort fields
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
    94
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
    95
    """
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
    96
    # 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
    97
    # instance
4368
d752ad901f14 cleanup module namespace but only importing the formwidgets module
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4359
diff changeset
    98
    widget = fw.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
    99
    # does this field requires a multipart form
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   100
    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
   101
    # 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
   102
    __creation_rank = 0
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   103
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
   104
    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
   105
    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
   106
    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
   107
    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
   108
    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
   109
    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
   110
    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
   111
    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
   112
    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
   113
    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
   114
    value = _MARKER
4546
f8ac61376b2b provides a fallback_on_none_attribute field attribute, allowing to specify default value for attributes of *existing* entities
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4544
diff changeset
   115
    fallback_on_none_attribute = False
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
   116
4377
0e9cf6593382 fix label handling: when label is explicitly set to None, don't try to guess it
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4374
diff changeset
   117
    def __init__(self, name=None, label=_MARKER, widget=None, **kwargs):
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
   118
        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
   119
            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
   120
                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
   121
                     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
   122
                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
   123
            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
   124
            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
   125
        self.name = name
4377
0e9cf6593382 fix label handling: when label is explicitly set to None, don't try to guess it
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4374
diff changeset
   126
        if label is _MARKER:
0e9cf6593382 fix label handling: when label is explicitly set to None, don't try to guess it
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4374
diff changeset
   127
            label = name or _MARKER
0e9cf6593382 fix label handling: when label is explicitly set to None, don't try to guess it
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4374
diff changeset
   128
        self.label = label
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
        # 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
   130
        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
   131
        # 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
   132
        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
   133
        Field.__creation_rank += 1
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
   134
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   135
    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
   136
        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
   137
            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
   138
            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
   139
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   140
    def __repr__(self):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   141
        return self.__unicode__().encode('utf-8')
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   142
1986
96c0e56cb0cf move widget selection's logic on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   143
    def init_widget(self, widget):
96c0e56cb0cf move widget selection's logic on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   144
        if widget is not None:
96c0e56cb0cf move widget selection's logic on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   145
            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
   146
        elif self.choices and not self.widget.vocabulary_widget:
4368
d752ad901f14 cleanup module namespace but only importing the formwidgets module
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4359
diff changeset
   147
            self.widget = fw.Select()
1986
96c0e56cb0cf move widget selection's logic on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   148
        if isinstance(self.widget, type):
96c0e56cb0cf move widget selection's logic on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   149
            self.widget = self.widget()
96c0e56cb0cf move widget selection's logic on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   150
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   151
    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
   152
        """automatically set .label when name is set"""
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   153
        assert name
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   154
        self.name = name
4377
0e9cf6593382 fix label handling: when label is explicitly set to None, don't try to guess it
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4374
diff changeset
   155
        if self.label is _MARKER:
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   156
            self.label = name
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
   157
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   158
    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
   159
        """return true if the field is not an hidden field"""
4368
d752ad901f14 cleanup module namespace but only importing the formwidgets module
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4359
diff changeset
   160
        return not isinstance(self.widget, fw.HiddenInput)
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
   161
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   162
    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
   163
        """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
   164
        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
   165
        """
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   166
        yield self
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
   167
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   168
    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
   169
        """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
   170
        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
   171
        """
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   172
        if isinstance(value, (list, tuple)):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   173
            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
   174
        return self.format_single_value(req, value)
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
   175
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   176
    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
   177
        """return value suitable for display"""
1306
e70ad982374a bool handling
sylvain.thenault@logilab.fr
parents: 1305
diff changeset
   178
        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
   179
            return u''
1306
e70ad982374a bool handling
sylvain.thenault@logilab.fr
parents: 1305
diff changeset
   180
        if value is True:
e70ad982374a bool handling
sylvain.thenault@logilab.fr
parents: 1305
diff changeset
   181
            return u'1'
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   182
        return unicode(value)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   183
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   184
    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
   185
        """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
   186
        return self.widget
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
   187
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
   188
    # 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
   189
    # 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
   190
    # `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
   191
    # (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
   192
    @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
   193
    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
   194
        """return 'qualified name' for this field"""
4302
8bedd7506d6e cleaner input_name implementation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4273
diff changeset
   195
        name = self.role_name()
8bedd7506d6e cleaner input_name implementation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4273
diff changeset
   196
        if suffix is not None:
8bedd7506d6e cleaner input_name implementation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4273
diff changeset
   197
            name += suffix
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
   198
        if self.eidparam:
4302
8bedd7506d6e cleaner input_name implementation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4273
diff changeset
   199
            return eid_param(name, form.edited_entity.eid)
8bedd7506d6e cleaner input_name implementation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4273
diff changeset
   200
        return name
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
   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 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
   203
        """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
   204
        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
   205
            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
   206
        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
   207
4303
35e814dce815 dom_id now accepts a suffix argument as input_name
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4302
diff changeset
   208
    def dom_id(self, form, suffix=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
   209
        """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
   210
        id = self.id or self.role_name()
4303
35e814dce815 dom_id now accepts a suffix argument as input_name
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4302
diff changeset
   211
        if suffix is not None:
35e814dce815 dom_id now accepts a suffix argument as input_name
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4302
diff changeset
   212
            id += suffix
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
   213
        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
   214
            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
   215
        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
   216
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
   217
    def typed_value(self, form, load_bytes=False):
4369
6d3dae46ee95 fix typed_value implementation w/ eidparam field which are actual entity's relation and have .value set for their initial value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4368
diff changeset
   218
        if self.eidparam and self.role is not None:
6d3dae46ee95 fix typed_value implementation w/ eidparam field which are actual entity's relation and have .value set for their initial value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4368
diff changeset
   219
            entity = form.edited_entity
6d3dae46ee95 fix typed_value implementation w/ eidparam field which are actual entity's relation and have .value set for their initial value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4368
diff changeset
   220
            if form._cw.vreg.schema.rschema(self.name).final:
6d3dae46ee95 fix typed_value implementation w/ eidparam field which are actual entity's relation and have .value set for their initial value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4368
diff changeset
   221
                if entity.has_eid() or self.name in entity:
4546
f8ac61376b2b provides a fallback_on_none_attribute field attribute, allowing to specify default value for attributes of *existing* entities
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4544
diff changeset
   222
                    value = getattr(entity, self.name)
f8ac61376b2b provides a fallback_on_none_attribute field attribute, allowing to specify default value for attributes of *existing* entities
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4544
diff changeset
   223
                    if value is not None or not self.fallback_on_none_attribute:
f8ac61376b2b provides a fallback_on_none_attribute field attribute, allowing to specify default value for attributes of *existing* entities
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4544
diff changeset
   224
                        return value
4369
6d3dae46ee95 fix typed_value implementation w/ eidparam field which are actual entity's relation and have .value set for their initial value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4368
diff changeset
   225
            elif entity.has_eid() or entity.relation_cached(self.name, self.role):
4546
f8ac61376b2b provides a fallback_on_none_attribute field attribute, allowing to specify default value for attributes of *existing* entities
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4544
diff changeset
   226
                value = [r[0] for r in entity.related(self.name, self.role)]
f8ac61376b2b provides a fallback_on_none_attribute field attribute, allowing to specify default value for attributes of *existing* entities
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4544
diff changeset
   227
                if value or not self.fallback_on_none_attribute:
f8ac61376b2b provides a fallback_on_none_attribute field attribute, allowing to specify default value for attributes of *existing* entities
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4544
diff changeset
   228
                    return value
4369
6d3dae46ee95 fix typed_value implementation w/ eidparam field which are actual entity's relation and have .value set for their initial value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4368
diff changeset
   229
        return self.initial_typed_value(form, load_bytes)
6d3dae46ee95 fix typed_value implementation w/ eidparam field which are actual entity's relation and have .value set for their initial value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4368
diff changeset
   230
6d3dae46ee95 fix typed_value implementation w/ eidparam field which are actual entity's relation and have .value set for their initial value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4368
diff changeset
   231
    def initial_typed_value(self, form, load_bytes):
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
   232
        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
   233
            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
   234
                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
   235
            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
   236
        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
   237
        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
   238
            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
   239
                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
   240
            return getattr(form, formattr)()
4369
6d3dae46ee95 fix typed_value implementation w/ eidparam field which are actual entity's relation and have .value set for their initial value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4368
diff changeset
   241
        if self.eidparam and self.role is not None:
6d3dae46ee95 fix typed_value implementation w/ eidparam field which are actual entity's relation and have .value set for their initial value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4368
diff changeset
   242
            if form._cw.vreg.schema.rschema(self.name).final:
6d3dae46ee95 fix typed_value implementation w/ eidparam field which are actual entity's relation and have .value set for their initial value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4368
diff changeset
   243
                return form.edited_entity.e_schema.default(self.name)
6d3dae46ee95 fix typed_value implementation w/ eidparam field which are actual entity's relation and have .value set for their initial value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4368
diff changeset
   244
            return ()
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
   245
        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
   246
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   247
    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
   248
        """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
   249
        field
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
   250
        """
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   251
        return u''
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   252
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   253
    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
   254
        """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
   255
        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
   256
        """
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
   257
        widget = self.get_widget(form)
3873
4d95109582c7 [web] remove widget.render backward compatibility
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3790
diff changeset
   258
        return widget.render(form, self, renderer)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   259
4388
15c6607c4bda [forms] propagate aguments given to .vocabulary to .choices if it's a callable.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4386
diff changeset
   260
    def vocabulary(self, form, **kwargs):
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
   261
        """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
   262
        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
   263
        """
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   264
        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
   265
        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
   266
            try:
4338
0eb7efcbcee1 to ease overriding of field.choices using *function* (set using autoform_field_kwargs), give the field as named argument
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4304
diff changeset
   267
                if getattr(self.choices, 'im_self', None) is self:
4388
15c6607c4bda [forms] propagate aguments given to .vocabulary to .choices if it's a callable.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4386
diff changeset
   268
                    vocab = self.choices(form=form, **kwargs)
4338
0eb7efcbcee1 to ease overriding of field.choices using *function* (set using autoform_field_kwargs), give the field as named argument
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4304
diff changeset
   269
                else:
4388
15c6607c4bda [forms] propagate aguments given to .vocabulary to .choices if it's a callable.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4386
diff changeset
   270
                    vocab = self.choices(form=form, field=self, **kwargs)
4161
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   271
            except TypeError:
4338
0eb7efcbcee1 to ease overriding of field.choices using *function* (set using autoform_field_kwargs), give the field as named argument
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4304
diff changeset
   272
                try:
4388
15c6607c4bda [forms] propagate aguments given to .vocabulary to .choices if it's a callable.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4386
diff changeset
   273
                    vocab = self.choices(form=form, **kwargs)
4499
4f741341d96f avoid to see the same warning twice, one for 3.6 another for 3.3
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4495
diff changeset
   274
                    warn('[3.6]  %s: choices should now take '
4f741341d96f avoid to see the same warning twice, one for 3.6 another for 3.3
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4495
diff changeset
   275
                         'the form and field as named arguments' % self,
4f741341d96f avoid to see the same warning twice, one for 3.6 another for 3.3
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4495
diff changeset
   276
                         DeprecationWarning)
4338
0eb7efcbcee1 to ease overriding of field.choices using *function* (set using autoform_field_kwargs), give the field as named argument
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4304
diff changeset
   277
                except TypeError:
0eb7efcbcee1 to ease overriding of field.choices using *function* (set using autoform_field_kwargs), give the field as named argument
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4304
diff changeset
   278
                    warn('[3.3]  %s: choices should now take '
4386
cf8842b69379 [forms] fix backward compat for field.choices arguments
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4382
diff changeset
   279
                         'the form and field as named arguments' % self,
cf8842b69379 [forms] fix backward compat for field.choices arguments
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4382
diff changeset
   280
                         DeprecationWarning)
4388
15c6607c4bda [forms] propagate aguments given to .vocabulary to .choices if it's a callable.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4386
diff changeset
   281
                    vocab = self.choices(req=form._cw, **kwargs)
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
   282
        else:
4170
c325c62cec8e crecord introduced junk...
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4168
diff changeset
   283
            vocab = self.choices
c325c62cec8e crecord introduced junk...
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4168
diff changeset
   284
        if vocab and not isinstance(vocab[0], (list, tuple)):
c325c62cec8e crecord introduced junk...
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4168
diff changeset
   285
            vocab = [(x, x) for x 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
   286
        if self.internationalizable:
3790
34fdb8fb49d1 [B] web: weird display with internationalizable (Closes: #503071)
Julien Jehannet <julien.jehannet@logilab.fr>
parents: 3689
diff changeset
   287
            # 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
   288
            # 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
   289
            # 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
   290
            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
   291
        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
   292
            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
   293
        return vocab
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
   294
4162
d2663bcf5306 replace form_field_[encoding|vocabulary] methods on form by encoding|vocabylary(form) methods on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4161
diff changeset
   295
    def format(self, form):
d2663bcf5306 replace form_field_[encoding|vocabulary] methods on form by encoding|vocabylary(form) methods on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4161
diff changeset
   296
        """return MIME type used for the given (text or bytes) field"""
d2663bcf5306 replace form_field_[encoding|vocabulary] methods on form by encoding|vocabylary(form) methods on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4161
diff changeset
   297
        if self.eidparam and self.role == 'subject':
d2663bcf5306 replace form_field_[encoding|vocabulary] methods on form by encoding|vocabylary(form) methods on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4161
diff changeset
   298
            entity = form.edited_entity
d2663bcf5306 replace form_field_[encoding|vocabulary] methods on form by encoding|vocabylary(form) methods on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4161
diff changeset
   299
            if entity.e_schema.has_metadata(self.name, 'format') and (
d2663bcf5306 replace form_field_[encoding|vocabulary] methods on form by encoding|vocabylary(form) methods on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4161
diff changeset
   300
                entity.has_eid() or '%s_format' % self.name in entity):
d2663bcf5306 replace form_field_[encoding|vocabulary] methods on form by encoding|vocabylary(form) methods on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4161
diff changeset
   301
                return form.edited_entity.attr_metadata(self.name, 'format')
d2663bcf5306 replace form_field_[encoding|vocabulary] methods on form by encoding|vocabylary(form) methods on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4161
diff changeset
   302
        return form._cw.property_value('ui.default-text-format')
d2663bcf5306 replace form_field_[encoding|vocabulary] methods on form by encoding|vocabylary(form) methods on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4161
diff changeset
   303
d2663bcf5306 replace form_field_[encoding|vocabulary] methods on form by encoding|vocabylary(form) methods on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4161
diff changeset
   304
    def encoding(self, form):
d2663bcf5306 replace form_field_[encoding|vocabulary] methods on form by encoding|vocabylary(form) methods on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4161
diff changeset
   305
        """return encoding used for the given (text) field"""
d2663bcf5306 replace form_field_[encoding|vocabulary] methods on form by encoding|vocabylary(form) methods on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4161
diff changeset
   306
        if self.eidparam:
d2663bcf5306 replace form_field_[encoding|vocabulary] methods on form by encoding|vocabylary(form) methods on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4161
diff changeset
   307
            entity = form.edited_entity
d2663bcf5306 replace form_field_[encoding|vocabulary] methods on form by encoding|vocabylary(form) methods on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4161
diff changeset
   308
            if entity.e_schema.has_metadata(self.name, 'encoding') and (
d2663bcf5306 replace form_field_[encoding|vocabulary] methods on form by encoding|vocabylary(form) methods on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4161
diff changeset
   309
                entity.has_eid() or '%s_encoding' % self.name in entity):
d2663bcf5306 replace form_field_[encoding|vocabulary] methods on form by encoding|vocabylary(form) methods on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4161
diff changeset
   310
                return form.edited_entity.attr_metadata(self.name, 'encoding')
d2663bcf5306 replace form_field_[encoding|vocabulary] methods on form by encoding|vocabylary(form) methods on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4161
diff changeset
   311
        return form._cw.encoding
d2663bcf5306 replace form_field_[encoding|vocabulary] methods on form by encoding|vocabylary(form) methods on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4161
diff changeset
   312
1307
8c3336c5ddba new form_init callback
sylvain.thenault@logilab.fr
parents: 1306
diff changeset
   313
    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
   314
        """method called before by build_context to trigger potential field
1307
8c3336c5ddba new form_init callback
sylvain.thenault@logilab.fr
parents: 1306
diff changeset
   315
        initialization requiring the form instance
8c3336c5ddba new form_init callback
sylvain.thenault@logilab.fr
parents: 1306
diff changeset
   316
        """
8c3336c5ddba new form_init callback
sylvain.thenault@logilab.fr
parents: 1306
diff changeset
   317
        pass
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
   318
4162
d2663bcf5306 replace form_field_[encoding|vocabulary] methods on form by encoding|vocabylary(form) methods on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4161
diff changeset
   319
    def has_been_modified(self, form):
4495
99c18d3f9542 unvisible field may have been modified, for instance relation added by an hidden input
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4481
diff changeset
   320
        # fields not corresponding to an entity attribute / relations
99c18d3f9542 unvisible field may have been modified, for instance relation added by an hidden input
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4481
diff changeset
   321
        # are considered modified
99c18d3f9542 unvisible field may have been modified, for instance relation added by an hidden input
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4481
diff changeset
   322
        if not self.eidparam or not self.role or not form.edited_entity.has_eid():
99c18d3f9542 unvisible field may have been modified, for instance relation added by an hidden input
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4481
diff changeset
   323
            return True # XXX
99c18d3f9542 unvisible field may have been modified, for instance relation added by an hidden input
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4481
diff changeset
   324
        try:
99c18d3f9542 unvisible field may have been modified, for instance relation added by an hidden input
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4481
diff changeset
   325
            if self.role == 'subject':
99c18d3f9542 unvisible field may have been modified, for instance relation added by an hidden input
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4481
diff changeset
   326
                previous_value = getattr(form.edited_entity, self.name)
99c18d3f9542 unvisible field may have been modified, for instance relation added by an hidden input
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4481
diff changeset
   327
            else:
99c18d3f9542 unvisible field may have been modified, for instance relation added by an hidden input
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4481
diff changeset
   328
                previous_value = getattr(form.edited_entity,
99c18d3f9542 unvisible field may have been modified, for instance relation added by an hidden input
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4481
diff changeset
   329
                                         'reverse_%s' % self.name)
99c18d3f9542 unvisible field may have been modified, for instance relation added by an hidden input
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4481
diff changeset
   330
        except AttributeError:
99c18d3f9542 unvisible field may have been modified, for instance relation added by an hidden input
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4481
diff changeset
   331
            # fields with eidparam=True but not corresponding to an actual
99c18d3f9542 unvisible field may have been modified, for instance relation added by an hidden input
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4481
diff changeset
   332
            # attribute or relation
4162
d2663bcf5306 replace form_field_[encoding|vocabulary] methods on form by encoding|vocabylary(form) methods on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4161
diff changeset
   333
            return True
4495
99c18d3f9542 unvisible field may have been modified, for instance relation added by an hidden input
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4481
diff changeset
   334
        # if it's a non final relation, we need the eids
99c18d3f9542 unvisible field may have been modified, for instance relation added by an hidden input
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4481
diff changeset
   335
        if isinstance(previous_value, tuple):
99c18d3f9542 unvisible field may have been modified, for instance relation added by an hidden input
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4481
diff changeset
   336
            # widget should return a set of untyped eids
99c18d3f9542 unvisible field may have been modified, for instance relation added by an hidden input
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4481
diff changeset
   337
            previous_value = set(unicode(e.eid) for e in previous_value)
99c18d3f9542 unvisible field may have been modified, for instance relation added by an hidden input
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4481
diff changeset
   338
        try:
99c18d3f9542 unvisible field may have been modified, for instance relation added by an hidden input
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4481
diff changeset
   339
            new_value = self.process_form_value(form)
99c18d3f9542 unvisible field may have been modified, for instance relation added by an hidden input
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4481
diff changeset
   340
        except ProcessFormError:
99c18d3f9542 unvisible field may have been modified, for instance relation added by an hidden input
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4481
diff changeset
   341
            return True
99c18d3f9542 unvisible field may have been modified, for instance relation added by an hidden input
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4481
diff changeset
   342
        except UnmodifiedField:
99c18d3f9542 unvisible field may have been modified, for instance relation added by an hidden input
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4481
diff changeset
   343
            return False
99c18d3f9542 unvisible field may have been modified, for instance relation added by an hidden input
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4481
diff changeset
   344
        if previous_value == new_value:
99c18d3f9542 unvisible field may have been modified, for instance relation added by an hidden input
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4481
diff changeset
   345
            return False # not modified
99c18d3f9542 unvisible field may have been modified, for instance relation added by an hidden input
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4481
diff changeset
   346
        return True
4162
d2663bcf5306 replace form_field_[encoding|vocabulary] methods on form by encoding|vocabylary(form) methods on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4161
diff changeset
   347
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
   348
    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
   349
        """process posted form and return correctly typed value"""
4359
fabc680bb0bf fix Bytes submission pb on POST, due to multiple call to field.process_form_value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4354
diff changeset
   350
        try:
fabc680bb0bf fix Bytes submission pb on POST, due to multiple call to field.process_form_value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4354
diff changeset
   351
            return form.formvalues[self]
fabc680bb0bf fix Bytes submission pb on POST, due to multiple call to field.process_form_value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4354
diff changeset
   352
        except KeyError:
fabc680bb0bf fix Bytes submission pb on POST, due to multiple call to field.process_form_value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4354
diff changeset
   353
            value = form.formvalues[self] = self._process_form_value(form)
fabc680bb0bf fix Bytes submission pb on POST, due to multiple call to field.process_form_value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4354
diff changeset
   354
            return value
fabc680bb0bf fix Bytes submission pb on POST, due to multiple call to field.process_form_value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4354
diff changeset
   355
fabc680bb0bf fix Bytes submission pb on POST, due to multiple call to field.process_form_value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4354
diff changeset
   356
    def _process_form_value(self, 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
   357
        widget = self.get_widget(form)
4370
75c610a85949 introduce new _ensure_correctly_typed method on fields, responsible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4369
diff changeset
   358
        value = widget.process_field_data(form, self)
75c610a85949 introduce new _ensure_correctly_typed method on fields, responsible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4369
diff changeset
   359
        return self._ensure_correctly_typed(form, value)
75c610a85949 introduce new _ensure_correctly_typed method on fields, responsible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4369
diff changeset
   360
75c610a85949 introduce new _ensure_correctly_typed method on fields, responsible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4369
diff changeset
   361
    def _ensure_correctly_typed(self, form, value):
75c610a85949 introduce new _ensure_correctly_typed method on fields, responsible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4369
diff changeset
   362
        """widget might to return date as a correctly formatted string or as
75c610a85949 introduce new _ensure_correctly_typed method on fields, responsible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4369
diff changeset
   363
        correctly typed objects, but process_for_value must return a typed value.
75c610a85949 introduce new _ensure_correctly_typed method on fields, responsible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4369
diff changeset
   364
        Override this method to type the value if necessary
75c610a85949 introduce new _ensure_correctly_typed method on fields, responsible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4369
diff changeset
   365
        """
4392
91a56a30141e by default this is not the widget responsability to turn empty string into None,
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4388
diff changeset
   366
        return value or None
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
   367
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
   368
    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
   369
        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
   370
            if field is self:
4251
3c6569be1f86 fix pb with bytes field processing: currently when an existing file is edited
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4241
diff changeset
   371
                try:
3c6569be1f86 fix pb with bytes field processing: currently when an existing file is edited
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4241
diff changeset
   372
                    yield field, field.process_form_value(form)
3c6569be1f86 fix pb with bytes field processing: currently when an existing file is edited
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4241
diff changeset
   373
                except UnmodifiedField:
3c6569be1f86 fix pb with bytes field processing: currently when an existing file is edited
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4241
diff changeset
   374
                    continue
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
   375
            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
   376
                # 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
   377
                # of compound fields (of compound fields of ...)
4166
677e487e691a process_posted yield field instead of field's name
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4165
diff changeset
   378
                for field, value in field.process_posted(form):
677e487e691a process_posted yield field instead of field's name
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4165
diff changeset
   379
                    yield field, value
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
   380
1986
96c0e56cb0cf move widget selection's logic on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   381
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   382
class StringField(Field):
4368
d752ad901f14 cleanup module namespace but only importing the formwidgets module
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4359
diff changeset
   383
    widget = fw.TextArea
4215
9fbc39453012 [forms] make it easier to override StringField's mininum size
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 4212
diff changeset
   384
    size = 45
1986
96c0e56cb0cf move widget selection's logic on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   385
4168
9d83f9c80c1c nicer StringField __init__
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4166
diff changeset
   386
    def __init__(self, name=None, max_length=None, **kwargs):
1986
96c0e56cb0cf move widget selection's logic on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   387
        self.max_length = max_length # must be set before super call
4168
9d83f9c80c1c nicer StringField __init__
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4166
diff changeset
   388
        super(StringField, self).__init__(name=name, **kwargs)
1986
96c0e56cb0cf move widget selection's logic on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   389
96c0e56cb0cf move widget selection's logic on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   390
    def init_widget(self, widget):
96c0e56cb0cf move widget selection's logic on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   391
        if widget is None:
96c0e56cb0cf move widget selection's logic on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   392
            if self.choices:
4368
d752ad901f14 cleanup module namespace but only importing the formwidgets module
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4359
diff changeset
   393
                widget = fw.Select()
1986
96c0e56cb0cf move widget selection's logic on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   394
            elif self.max_length and self.max_length < 257:
4368
d752ad901f14 cleanup module namespace but only importing the formwidgets module
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4359
diff changeset
   395
                widget = fw.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
   396
1986
96c0e56cb0cf move widget selection's logic on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   397
        super(StringField, self).init_widget(widget)
4368
d752ad901f14 cleanup module namespace but only importing the formwidgets module
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4359
diff changeset
   398
        if isinstance(self.widget, fw.TextArea):
1573
d34589d35daa drop TextField, this is simply a StringField with a text area widget
sylvain.thenault@logilab.fr
parents: 1564
diff changeset
   399
            self.init_text_area(self.widget)
4368
d752ad901f14 cleanup module namespace but only importing the formwidgets module
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4359
diff changeset
   400
        elif isinstance(self.widget, fw.TextInput):
2360
1d43aa551ba9 [formwidgets,formfields] hum, this way
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 2356
diff changeset
   401
            self.init_text_input(self.widget)
1d43aa551ba9 [formwidgets,formfields] hum, this way
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 2356
diff changeset
   402
1d43aa551ba9 [formwidgets,formfields] hum, this way
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 2356
diff changeset
   403
    def init_text_input(self, widget):
1d43aa551ba9 [formwidgets,formfields] hum, this way
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 2356
diff changeset
   404
        if self.max_length:
4215
9fbc39453012 [forms] make it easier to override StringField's mininum size
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 4212
diff changeset
   405
            widget.attrs.setdefault('size', min(self.size, self.max_length))
2360
1d43aa551ba9 [formwidgets,formfields] hum, this way
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 2356
diff changeset
   406
            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
   407
d34589d35daa drop TextField, this is simply a StringField with a text area widget
sylvain.thenault@logilab.fr
parents: 1564
diff changeset
   408
    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
   409
        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
   410
            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
   411
            widget.attrs.setdefault('rows', 5)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   412
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   413
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
   414
class PasswordField(StringField):
4368
d752ad901f14 cleanup module namespace but only importing the formwidgets module
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4359
diff changeset
   415
    widget = fw.PasswordInput
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
   416
4369
6d3dae46ee95 fix typed_value implementation w/ eidparam field which are actual entity's relation and have .value set for their initial value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4368
diff changeset
   417
    def typed_value(self, form, load_bytes=False):
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
   418
        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
   419
            # 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
   420
            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
   421
                return INTERNAL_FIELD_VALUE
4369
6d3dae46ee95 fix typed_value implementation w/ eidparam field which are actual entity's relation and have .value set for their initial value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4368
diff changeset
   422
            return self.initial_typed_value(form, load_bytes)
6d3dae46ee95 fix typed_value implementation w/ eidparam field which are actual entity's relation and have .value set for their initial value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4368
diff changeset
   423
        return super(PasswordField, self).typed_value(form, load_bytes)
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
   424
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
   425
1573
d34589d35daa drop TextField, this is simply a StringField with a text area widget
sylvain.thenault@logilab.fr
parents: 1564
diff changeset
   426
class RichTextField(StringField):
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   427
    widget = None
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   428
    def __init__(self, format_field=None, **kwargs):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   429
        super(RichTextField, self).__init__(**kwargs)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   430
        self.format_field = format_field
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   431
2348
acf4b6a59558 [formwidgets] ensure textarea for richstring has not ridicuously small size (close #344547)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 2347
diff changeset
   432
    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
   433
        pass
acf4b6a59558 [formwidgets] ensure textarea for richstring has not ridicuously small size (close #344547)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 2347
diff changeset
   434
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   435
    def get_widget(self, form):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   436
        if self.widget is None:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   437
            if self.use_fckeditor(form):
4368
d752ad901f14 cleanup module namespace but only importing the formwidgets module
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4359
diff changeset
   438
                return fw.FCKEditor()
d752ad901f14 cleanup module namespace but only importing the formwidgets module
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4359
diff changeset
   439
            widget = fw.TextArea()
1573
d34589d35daa drop TextField, this is simply a StringField with a text area widget
sylvain.thenault@logilab.fr
parents: 1564
diff changeset
   440
            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
   441
            return widget
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   442
        return self.widget
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   443
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   444
    def get_format_field(self, form):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   445
        if self.format_field:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   446
            return self.format_field
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   447
        # 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
   448
        # context dictionnary
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3388
diff changeset
   449
        req = form._cw
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   450
        try:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   451
            return req.data[self]
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   452
        except KeyError:
4165
eb9acad29407 proper field's role handling: may be 'subject' / 'object' *in case
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4162
diff changeset
   453
            fkwargs = {'eidparam': self.eidparam, 'role': self.role}
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   454
            if self.use_fckeditor(form):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   455
                # 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
   456
                # deactivated, we want an hidden field for the format
4368
d752ad901f14 cleanup module namespace but only importing the formwidgets module
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4359
diff changeset
   457
                fkwargs['widget'] = fw.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
   458
                fkwargs['value'] = 'text/html'
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   459
            else:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   460
                # else we want a format selector
4368
d752ad901f14 cleanup module namespace but only importing the formwidgets module
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4359
diff changeset
   461
                fkwargs['widget'] = fw.Select()
1095
6917ebe281e9 test and fix guess_field, some pylint fixes
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
   462
                fcstr = FormatConstraint()
3347
428f95118556 fix vocab param to avoid deprecation warning
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3337
diff changeset
   463
                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
   464
                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
   465
                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
   466
            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
   467
            field = StringField(name=self.name + '_format', **fkwargs)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   468
            req.data[self] = field
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   469
            return field
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
   470
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   471
    def actual_fields(self, form):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   472
        yield self
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   473
        format_field = self.get_format_field(form)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   474
        if format_field:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   475
            yield format_field
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
   476
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   477
    def use_fckeditor(self, form):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   478
        """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
   479
        `attr`, according to user preferences
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   480
        """
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3388
diff changeset
   481
        if form._cw.use_fckeditor():
4162
d2663bcf5306 replace form_field_[encoding|vocabulary] methods on form by encoding|vocabylary(form) methods on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4161
diff changeset
   482
            return self.format(form) == 'text/html'
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   483
        return False
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   484
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   485
    def render(self, form, renderer):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   486
        format_field = self.get_format_field(form)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   487
        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
   488
            # 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
   489
            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
   490
                format_field.widget.attrs['style'] = 'display: block'
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   491
            result = format_field.render(form, renderer)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   492
        else:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   493
            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
   494
        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
   495
1417
06af20e663f2 remove spaces
sylvain.thenault@logilab.fr
parents: 1393
diff changeset
   496
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   497
class FileField(StringField):
4368
d752ad901f14 cleanup module namespace but only importing the formwidgets module
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4359
diff changeset
   498
    widget = fw.FileInput
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   499
    needs_multipart = True
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
   500
3496
35a67ac6efe8 support name metadata on guess_field; add name_field to FileField
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3347
diff changeset
   501
    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
   502
                 **kwargs):
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   503
        super(FileField, self).__init__(**kwargs)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   504
        self.format_field = format_field
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   505
        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
   506
        self.name_field = name_field
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
   507
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   508
    def actual_fields(self, form):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   509
        yield self
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   510
        if self.format_field:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   511
            yield self.format_field
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   512
        if self.encoding_field:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   513
            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
   514
        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
   515
            yield self.name_field
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   516
4369
6d3dae46ee95 fix typed_value implementation w/ eidparam field which are actual entity's relation and have .value set for their initial value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4368
diff changeset
   517
    def typed_value(self, form, load_bytes=False):
6d3dae46ee95 fix typed_value implementation w/ eidparam field which are actual entity's relation and have .value set for their initial value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4368
diff changeset
   518
        if self.eidparam and self.role is not None:
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
   519
            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
   520
                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
   521
                    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
   522
                # 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
   523
                # 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
   524
                # * 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
   525
                # * 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
   526
                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
   527
            return False
4369
6d3dae46ee95 fix typed_value implementation w/ eidparam field which are actual entity's relation and have .value set for their initial value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4368
diff changeset
   528
        return super(FileField, self).typed_value(form, load_bytes)
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
   529
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   530
    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
   531
        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
   532
        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
   533
            divid = '%s-advanced' % self.input_name(form)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   534
            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
   535
                        (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
   536
                         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
   537
                         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
   538
                         form._cw._('show advanced fields')))
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   539
            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
   540
            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
   541
                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
   542
            if self.format_field:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   543
                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
   544
            if self.encoding_field:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   545
                wdgs.append(self.render_subfield(form, self.encoding_field, renderer))
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
   546
            wdgs.append(u'</div>')
4369
6d3dae46ee95 fix typed_value implementation w/ eidparam field which are actual entity's relation and have .value set for their initial value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4368
diff changeset
   547
        if not self.required and self.typed_value(form):
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   548
            # 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
   549
            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
   550
            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
   551
                                   type=u'checkbox'))
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3388
diff changeset
   552
            wdgs.append(form._cw._('detach attached file'))
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   553
        return u'\n'.join(wdgs)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   554
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   555
    def render_subfield(self, form, field, renderer):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   556
        return (renderer.render_label(form, field)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   557
                + field.render(form, renderer)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   558
                + renderer.render_help(form, field)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   559
                + u'<br/>')
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   560
4359
fabc680bb0bf fix Bytes submission pb on POST, due to multiple call to field.process_form_value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4354
diff changeset
   561
    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
   562
        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
   563
        if self.input_name(form, u'__detach') in posted:
4251
3c6569be1f86 fix pb with bytes field processing: currently when an existing file is edited
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4241
diff changeset
   564
            # drop current file value on explictily asked to detach
3c6569be1f86 fix pb with bytes field processing: currently when an existing file is edited
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4241
diff changeset
   565
            return None
3c6569be1f86 fix pb with bytes field processing: currently when an existing file is edited
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4241
diff changeset
   566
        try:
3c6569be1f86 fix pb with bytes field processing: currently when an existing file is edited
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4241
diff changeset
   567
            value = posted[self.input_name(form)]
3c6569be1f86 fix pb with bytes field processing: currently when an existing file is edited
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4241
diff changeset
   568
        except KeyError:
3c6569be1f86 fix pb with bytes field processing: currently when an existing file is edited
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4241
diff changeset
   569
            # raise UnmodifiedField instead of returning None, since the later
3c6569be1f86 fix pb with bytes field processing: currently when an existing file is edited
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4241
diff changeset
   570
            # will try to remove already attached file if any
3c6569be1f86 fix pb with bytes field processing: currently when an existing file is edited
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4241
diff changeset
   571
            raise UnmodifiedField()
3c6569be1f86 fix pb with bytes field processing: currently when an existing file is edited
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4241
diff changeset
   572
        # skip browser submitted mime type
3c6569be1f86 fix pb with bytes field processing: currently when an existing file is edited
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4241
diff changeset
   573
        filename, _, stream = value
3c6569be1f86 fix pb with bytes field processing: currently when an existing file is edited
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4241
diff changeset
   574
        # value is a  3-uple (filename, mimetype, stream)
3c6569be1f86 fix pb with bytes field processing: currently when an existing file is edited
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4241
diff changeset
   575
        value = Binary(stream.read())
4273
183cd0df6f1a fix dumb name error
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4272
diff changeset
   576
        if not value.getvalue(): # usually an unexistant file
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
   577
            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
   578
        else:
4251
3c6569be1f86 fix pb with bytes field processing: currently when an existing file is edited
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4241
diff changeset
   579
            # set filename on the Binary instance, may be used later in hooks
3c6569be1f86 fix pb with bytes field processing: currently when an existing file is edited
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4241
diff changeset
   580
            value.filename = filename
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
   581
        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
   582
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
   583
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   584
class EditableFileField(FileField):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   585
    editable_formats = ('text/plain', 'text/html', 'text/rest')
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
   586
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   587
    def render(self, form, renderer):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   588
        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
   589
        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
   590
            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
   591
            if data:
4162
d2663bcf5306 replace form_field_[encoding|vocabulary] methods on form by encoding|vocabylary(form) methods on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4161
diff changeset
   592
                encoding = self.encoding(form)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   593
                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
   594
                    form.formvalues[self] = unicode(data.getvalue(), encoding)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   595
                except UnicodeError:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   596
                    pass
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   597
                else:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   598
                    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
   599
                        msg = form._cw._(
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   600
                            '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
   601
                            ', 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
   602
                            '"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
   603
                            'with the widget below.')
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   604
                    else:
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3388
diff changeset
   605
                        msg = form._cw._(
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   606
                            '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
   607
                            ', 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
   608
                    wdgs.append(u'<p><b>%s</b></p>' % msg)
4368
d752ad901f14 cleanup module namespace but only importing the formwidgets module
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4359
diff changeset
   609
                    wdgs.append(fw.TextArea(setdomid=False).render(form, self, renderer))
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   610
                    # XXX restore form context?
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   611
        return '\n'.join(wdgs)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   612
4359
fabc680bb0bf fix Bytes submission pb on POST, due to multiple call to field.process_form_value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4354
diff changeset
   613
    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
   614
        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
   615
        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
   616
            # file modified using a text widget
4162
d2663bcf5306 replace form_field_[encoding|vocabulary] methods on form by encoding|vocabylary(form) methods on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4161
diff changeset
   617
            return Binary(value.encode(self.encoding(form)))
4359
fabc680bb0bf fix Bytes submission pb on POST, due to multiple call to field.process_form_value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4354
diff changeset
   618
        return super(EditableFileField, self)._process_form_value(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
   619
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
   620
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   621
class IntField(Field):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   622
    def __init__(self, min=None, max=None, **kwargs):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   623
        super(IntField, self).__init__(**kwargs)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   624
        self.min = min
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   625
        self.max = max
4368
d752ad901f14 cleanup module namespace but only importing the formwidgets module
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4359
diff changeset
   626
        if isinstance(self.widget, fw.TextInput):
1758
d46f59e5efd3 some widget adjustments
sylvain.thenault@logilab.fr
parents: 1738
diff changeset
   627
            self.widget.attrs.setdefault('size', 5)
d46f59e5efd3 some widget adjustments
sylvain.thenault@logilab.fr
parents: 1738
diff changeset
   628
            self.widget.attrs.setdefault('maxlength', 15)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   629
4370
75c610a85949 introduce new _ensure_correctly_typed method on fields, responsible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4369
diff changeset
   630
    def _ensure_correctly_typed(self, form, value):
75c610a85949 introduce new _ensure_correctly_typed method on fields, responsible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4369
diff changeset
   631
        if isinstance(value, basestring):
4528
a51f37efc882 quick fix for typed formfield validation: accept empty string, split
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4499
diff changeset
   632
            value = value.strip()
a51f37efc882 quick fix for typed formfield validation: accept empty string, split
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4499
diff changeset
   633
            if not value:
a51f37efc882 quick fix for typed formfield validation: accept empty string, split
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4499
diff changeset
   634
                return None
4225
c49bb6e3d343 fix process_form_values: we should handle value errors and properly raise ProcessFormError
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4181
diff changeset
   635
            try:
c49bb6e3d343 fix process_form_values: we should handle value errors and properly raise ProcessFormError
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4181
diff changeset
   636
                return int(value)
c49bb6e3d343 fix process_form_values: we should handle value errors and properly raise ProcessFormError
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4181
diff changeset
   637
            except ValueError:
c49bb6e3d343 fix process_form_values: we should handle value errors and properly raise ProcessFormError
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4181
diff changeset
   638
                raise ProcessFormError(form._cw._('an integer is expected'))
4370
75c610a85949 introduce new _ensure_correctly_typed method on fields, responsible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4369
diff changeset
   639
        return value
1986
96c0e56cb0cf move widget selection's logic on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   640
96c0e56cb0cf move widget selection's logic on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   641
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   642
class BooleanField(Field):
4368
d752ad901f14 cleanup module namespace but only importing the formwidgets module
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4359
diff changeset
   643
    widget = fw.Radio
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
   644
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   645
    def vocabulary(self, form):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   646
        if self.choices:
4131
d8ca873142f4 call super class if choices specified to get std behaviour
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3874
diff changeset
   647
            return super(BooleanField, self).vocabulary(form)
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3388
diff changeset
   648
        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
   649
4370
75c610a85949 introduce new _ensure_correctly_typed method on fields, responsible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4369
diff changeset
   650
    def _ensure_correctly_typed(self, form, value):
4393
87e48fe398f1 systematically call bool on BooleanField values
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4392
diff changeset
   651
        return bool(value)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   652
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   653
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
   654
class FloatField(IntField):
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   655
    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
   656
        formatstr = req.property_value('ui.float-format')
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   657
        if value is None:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   658
            return u''
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   659
        return formatstr % float(value)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   660
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   661
    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
   662
        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
   663
4370
75c610a85949 introduce new _ensure_correctly_typed method on fields, responsible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4369
diff changeset
   664
    def _ensure_correctly_typed(self, form, value):
75c610a85949 introduce new _ensure_correctly_typed method on fields, responsible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4369
diff changeset
   665
        if isinstance(value, basestring):
4528
a51f37efc882 quick fix for typed formfield validation: accept empty string, split
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4499
diff changeset
   666
            value = value.strip()
a51f37efc882 quick fix for typed formfield validation: accept empty string, split
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4499
diff changeset
   667
            if not value:
a51f37efc882 quick fix for typed formfield validation: accept empty string, split
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4499
diff changeset
   668
                return None
4225
c49bb6e3d343 fix process_form_values: we should handle value errors and properly raise ProcessFormError
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4181
diff changeset
   669
            try:
c49bb6e3d343 fix process_form_values: we should handle value errors and properly raise ProcessFormError
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4181
diff changeset
   670
                return float(value)
c49bb6e3d343 fix process_form_values: we should handle value errors and properly raise ProcessFormError
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4181
diff changeset
   671
            except ValueError:
c49bb6e3d343 fix process_form_values: we should handle value errors and properly raise ProcessFormError
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4181
diff changeset
   672
                raise ProcessFormError(form._cw._('a float is expected'))
c49bb6e3d343 fix process_form_values: we should handle value errors and properly raise ProcessFormError
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4181
diff changeset
   673
        return None
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   674
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   675
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   676
class DateField(StringField):
4374
ff3efacfea42 by default use new jquery widgets for Time/Date/DateTime fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4370
diff changeset
   677
    widget = fw.JQueryDatePicker
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   678
    format_prop = 'ui.date-format'
4374
ff3efacfea42 by default use new jquery widgets for Time/Date/DateTime fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4370
diff changeset
   679
    etype = 'Date'
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
   680
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   681
    def format_single_value(self, req, value):
4382
6fb02edd05da 3.6 api update, cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4377
diff changeset
   682
        if value:
4544
d92aa3221c30 split introduced in the wrong place
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4528
diff changeset
   683
            return ustrftime(value, req.property_value(self.format_prop))
4382
6fb02edd05da 3.6 api update, cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4377
diff changeset
   684
        return u''
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   685
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   686
    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
   687
        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
   688
4370
75c610a85949 introduce new _ensure_correctly_typed method on fields, responsible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4369
diff changeset
   689
    def _ensure_correctly_typed(self, form, value):
75c610a85949 introduce new _ensure_correctly_typed method on fields, responsible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4369
diff changeset
   690
        if isinstance(value, basestring):
4528
a51f37efc882 quick fix for typed formfield validation: accept empty string, split
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4499
diff changeset
   691
            value = value.strip()
a51f37efc882 quick fix for typed formfield validation: accept empty string, split
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4499
diff changeset
   692
            if not value:
a51f37efc882 quick fix for typed formfield validation: accept empty string, split
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4499
diff changeset
   693
                return None
4225
c49bb6e3d343 fix process_form_values: we should handle value errors and properly raise ProcessFormError
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4181
diff changeset
   694
            try:
4370
75c610a85949 introduce new _ensure_correctly_typed method on fields, responsible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4369
diff changeset
   695
                value = form._cw.parse_datetime(value, self.etype)
4225
c49bb6e3d343 fix process_form_values: we should handle value errors and properly raise ProcessFormError
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4181
diff changeset
   696
            except ValueError, ex:
c49bb6e3d343 fix process_form_values: we should handle value errors and properly raise ProcessFormError
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4181
diff changeset
   697
                raise ProcessFormError(unicode(ex))
4370
75c610a85949 introduce new _ensure_correctly_typed method on fields, responsible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4369
diff changeset
   698
        return value
1081
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
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   701
class DateTimeField(DateField):
4374
ff3efacfea42 by default use new jquery widgets for Time/Date/DateTime fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4370
diff changeset
   702
    widget = fw.JQueryDateTimePicker
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   703
    format_prop = 'ui.datetime-format'
4370
75c610a85949 introduce new _ensure_correctly_typed method on fields, responsible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4369
diff changeset
   704
    etype = 'Datetime'
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   705
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   706
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   707
class TimeField(DateField):
4374
ff3efacfea42 by default use new jquery widgets for Time/Date/DateTime fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4370
diff changeset
   708
    widget = fw.JQueryTimePicker
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
   709
    format_prop = 'ui.time-format'
4370
75c610a85949 introduce new _ensure_correctly_typed method on fields, responsible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4369
diff changeset
   710
    etype = 'Time'
1986
96c0e56cb0cf move widget selection's logic on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   711
4161
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   712
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   713
# 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
   714
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   715
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
   716
    # 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
   717
    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
   718
    if linkedto:
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   719
        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
   720
        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
   721
    return []
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   722
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   723
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
   724
    # 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
   725
    vocab = []
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   726
    if not required:
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   727
        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
   728
    # 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
   729
    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
   730
        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
   731
        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
   732
    return vocab
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
   733
4161
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   734
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
   735
    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
   736
        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
   737
    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
   738
        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
   739
    else:
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   740
        done = None
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   741
    result = []
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   742
    rsetsize = None
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   743
    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
   744
        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
   745
            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
   746
        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
   747
        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
   748
            break
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   749
    return result
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   750
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   751
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
   752
    """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
   753
    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
   754
    """
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   755
    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
   756
        done = set()
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   757
    res = []
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   758
    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
   759
        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
   760
            continue
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   761
        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
   762
        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
   763
    return res
2146
6645e18e8c93 edit[s|o] field's value should be formatted as the associated field
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2095
diff changeset
   764
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
   765
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   766
class RelationField(Field):
4395
e50b71c0dd87 cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4393
diff changeset
   767
    """the relation field to edit non final relations of an entity"""
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   768
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   769
    @staticmethod
1095
6917ebe281e9 test and fix guess_field, some pylint fixes
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
   770
    def fromcardinality(card, **kwargs):
4368
d752ad901f14 cleanup module namespace but only importing the formwidgets module
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4359
diff changeset
   771
        kwargs.setdefault('widget', fw.Select(multiple=card in '*+'))
1738
2cfd50c8a415 should not override potential explicit widget
sylvain.thenault@logilab.fr
parents: 1709
diff changeset
   772
        return RelationField(**kwargs)
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
   773
4161
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   774
    def choices(self, form, limit=None):
4388
15c6607c4bda [forms] propagate aguments given to .vocabulary to .choices if it's a callable.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4386
diff changeset
   775
        """Take care, choices function for relation field instance should take
15c6607c4bda [forms] propagate aguments given to .vocabulary to .choices if it's a callable.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4386
diff changeset
   776
        an extra 'limit' argument, with default to None.
15c6607c4bda [forms] propagate aguments given to .vocabulary to .choices if it's a callable.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4386
diff changeset
   777
15c6607c4bda [forms] propagate aguments given to .vocabulary to .choices if it's a callable.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4386
diff changeset
   778
        This argument is used by the 'unrelateddivs' view (see in autoform) and
15c6607c4bda [forms] propagate aguments given to .vocabulary to .choices if it's a callable.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4386
diff changeset
   779
        when it's specified (eg not None), vocabulary returned should:
15c6607c4bda [forms] propagate aguments given to .vocabulary to .choices if it's a callable.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4386
diff changeset
   780
        * not include already related entities
15c6607c4bda [forms] propagate aguments given to .vocabulary to .choices if it's a callable.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4386
diff changeset
   781
        * have a max size of `limit` entities
15c6607c4bda [forms] propagate aguments given to .vocabulary to .choices if it's a callable.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4386
diff changeset
   782
        """
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1108
diff changeset
   783
        entity = form.edited_entity
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   784
        # first see if its specified by __linkto form parameters
4388
15c6607c4bda [forms] propagate aguments given to .vocabulary to .choices if it's a callable.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4386
diff changeset
   785
        if limit is None:
15c6607c4bda [forms] propagate aguments given to .vocabulary to .choices if it's a callable.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4386
diff changeset
   786
            linkedto = relvoc_linkedto(entity, self.name, self.role)
15c6607c4bda [forms] propagate aguments given to .vocabulary to .choices if it's a callable.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4386
diff changeset
   787
            if linkedto:
15c6607c4bda [forms] propagate aguments given to .vocabulary to .choices if it's a callable.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4386
diff changeset
   788
                return linkedto
15c6607c4bda [forms] propagate aguments given to .vocabulary to .choices if it's a callable.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4386
diff changeset
   789
            vocab = relvoc_init(entity, self.name, self.role, self.required)
15c6607c4bda [forms] propagate aguments given to .vocabulary to .choices if it's a callable.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4386
diff changeset
   790
        else:
15c6607c4bda [forms] propagate aguments given to .vocabulary to .choices if it's a callable.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4386
diff changeset
   791
            vocab = []
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   792
        # 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
   793
        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
   794
        try:
4269
da0d254f2eb0 remove deprecation warnings + name error
alex & cheb
parents: 4252
diff changeset
   795
            vocab += getattr(form, method)(self.name, limit)
4161
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   796
            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
   797
                 % (method, form), DeprecationWarning)
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   798
        except AttributeError:
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   799
            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
   800
        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
   801
            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
   802
        return vocab
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
   803
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
   804
    def form_init(self, form):
4304
0b53e850cdb5 refactor field's value retreiving from the widget (eg 'display value' concept):
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4303
diff changeset
   805
        #if not self.display_value(form):
0b53e850cdb5 refactor field's value retreiving from the widget (eg 'display value' concept):
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4303
diff changeset
   806
        value = form.edited_entity.linked_to(self.name, self.role)
0b53e850cdb5 refactor field's value retreiving from the widget (eg 'display value' concept):
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4303
diff changeset
   807
        if value:
0b53e850cdb5 refactor field's value retreiving from the widget (eg 'display value' concept):
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4303
diff changeset
   808
            searchedvalues = ['%s:%s:%s' % (self.name, eid, self.role)
0b53e850cdb5 refactor field's value retreiving from the widget (eg 'display value' concept):
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4303
diff changeset
   809
                              for eid in value]
0b53e850cdb5 refactor field's value retreiving from the widget (eg 'display value' concept):
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4303
diff changeset
   810
            # remove associated __linkto hidden fields
0b53e850cdb5 refactor field's value retreiving from the widget (eg 'display value' concept):
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4303
diff changeset
   811
            for field in form.root_form.fields_by_name('__linkto'):
0b53e850cdb5 refactor field's value retreiving from the widget (eg 'display value' concept):
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4303
diff changeset
   812
                if field.value in searchedvalues:
0b53e850cdb5 refactor field's value retreiving from the widget (eg 'display value' concept):
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4303
diff changeset
   813
                    form.root_form.remove_field(field)
0b53e850cdb5 refactor field's value retreiving from the widget (eg 'display value' concept):
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4303
diff changeset
   814
            form.formvalues[self] = value
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
   815
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   816
    def format_single_value(self, req, value):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   817
        return value
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   818
4581
c92ded4dee20 [forms] fix RelationField bug with pending eids (eg inlined forms): we have to override process_form_value to avoid caching when recomputing is needed
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4546
diff changeset
   819
    def process_form_value(self, form):
c92ded4dee20 [forms] fix RelationField bug with pending eids (eg inlined forms): we have to override process_form_value to avoid caching when recomputing is needed
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4546
diff changeset
   820
        """process posted form and return correctly typed value"""
c92ded4dee20 [forms] fix RelationField bug with pending eids (eg inlined forms): we have to override process_form_value to avoid caching when recomputing is needed
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4546
diff changeset
   821
        try:
c92ded4dee20 [forms] fix RelationField bug with pending eids (eg inlined forms): we have to override process_form_value to avoid caching when recomputing is needed
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4546
diff changeset
   822
            return form.formvalues[self]
c92ded4dee20 [forms] fix RelationField bug with pending eids (eg inlined forms): we have to override process_form_value to avoid caching when recomputing is needed
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4546
diff changeset
   823
        except KeyError:
c92ded4dee20 [forms] fix RelationField bug with pending eids (eg inlined forms): we have to override process_form_value to avoid caching when recomputing is needed
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4546
diff changeset
   824
            value = self._process_form_value(form)
c92ded4dee20 [forms] fix RelationField bug with pending eids (eg inlined forms): we have to override process_form_value to avoid caching when recomputing is needed
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4546
diff changeset
   825
            # if value is None, there are some remaining pending fields, we'll
c92ded4dee20 [forms] fix RelationField bug with pending eids (eg inlined forms): we have to override process_form_value to avoid caching when recomputing is needed
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4546
diff changeset
   826
            # have to recompute this later -> don't cache in formvalues
c92ded4dee20 [forms] fix RelationField bug with pending eids (eg inlined forms): we have to override process_form_value to avoid caching when recomputing is needed
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4546
diff changeset
   827
            if value is not None:
c92ded4dee20 [forms] fix RelationField bug with pending eids (eg inlined forms): we have to override process_form_value to avoid caching when recomputing is needed
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4546
diff changeset
   828
                form.formvalues[self] = value
c92ded4dee20 [forms] fix RelationField bug with pending eids (eg inlined forms): we have to override process_form_value to avoid caching when recomputing is needed
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4546
diff changeset
   829
            return value
c92ded4dee20 [forms] fix RelationField bug with pending eids (eg inlined forms): we have to override process_form_value to avoid caching when recomputing is needed
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4546
diff changeset
   830
4359
fabc680bb0bf fix Bytes submission pb on POST, due to multiple call to field.process_form_value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4354
diff changeset
   831
    def _process_form_value(self, form):
4110
8728d8c95985 [mq]: fix_for_forms
Arthur Lutz <arthur.lutz@logilab.fr>
parents: 4101
diff changeset
   832
        """process posted form and return correctly typed value"""
8728d8c95985 [mq]: fix_for_forms
Arthur Lutz <arthur.lutz@logilab.fr>
parents: 4101
diff changeset
   833
        widget = self.get_widget(form)
4171
f1b9f0ed1253 make new editcontroller works, based on a _cw_edited_fields hidden input
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4170
diff changeset
   834
        values = widget.process_field_data(form, self)
f1b9f0ed1253 make new editcontroller works, based on a _cw_edited_fields hidden input
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4170
diff changeset
   835
        if values is None:
f1b9f0ed1253 make new editcontroller works, based on a _cw_edited_fields hidden input
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4170
diff changeset
   836
            values = ()
f1b9f0ed1253 make new editcontroller works, based on a _cw_edited_fields hidden input
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4170
diff changeset
   837
        elif not isinstance(values, list):
f1b9f0ed1253 make new editcontroller works, based on a _cw_edited_fields hidden input
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4170
diff changeset
   838
            values = (values,)
f1b9f0ed1253 make new editcontroller works, based on a _cw_edited_fields hidden input
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4170
diff changeset
   839
        eids = set()
f1b9f0ed1253 make new editcontroller works, based on a _cw_edited_fields hidden input
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4170
diff changeset
   840
        for eid in values:
4227
39f01be4a6c5 should skip INTERNAL_FIELD_VALUE
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4226
diff changeset
   841
            if not eid or eid == INTERNAL_FIELD_VALUE:
4171
f1b9f0ed1253 make new editcontroller works, based on a _cw_edited_fields hidden input
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4170
diff changeset
   842
                continue
f1b9f0ed1253 make new editcontroller works, based on a _cw_edited_fields hidden input
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4170
diff changeset
   843
            typed_eid = form.actual_eid(eid)
f1b9f0ed1253 make new editcontroller works, based on a _cw_edited_fields hidden input
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4170
diff changeset
   844
            if typed_eid is None:
4226
67dd296f864d should use a set for pending fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4225
diff changeset
   845
                form._cw.data['pendingfields'].add( (form, self) )
4171
f1b9f0ed1253 make new editcontroller works, based on a _cw_edited_fields hidden input
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4170
diff changeset
   846
                return None
f1b9f0ed1253 make new editcontroller works, based on a _cw_edited_fields hidden input
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4170
diff changeset
   847
            eids.add(typed_eid)
f1b9f0ed1253 make new editcontroller works, based on a _cw_edited_fields hidden input
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4170
diff changeset
   848
        return eids
f1b9f0ed1253 make new editcontroller works, based on a _cw_edited_fields hidden input
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4170
diff changeset
   849
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   850
2523
1d245fbbeb90 some new field/widgets classes: CompoundField, IntervalWidget, HorizontalLayoutWidget
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2522
diff changeset
   851
class CompoundField(Field):
1d245fbbeb90 some new field/widgets classes: CompoundField, IntervalWidget, HorizontalLayoutWidget
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2522
diff changeset
   852
    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
   853
        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
   854
        self.fields = fields
1d245fbbeb90 some new field/widgets classes: CompoundField, IntervalWidget, HorizontalLayoutWidget
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2522
diff changeset
   855
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
   856
    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
   857
        return self.fields
2568
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2549
diff changeset
   858
2523
1d245fbbeb90 some new field/widgets classes: CompoundField, IntervalWidget, HorizontalLayoutWidget
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2522
diff changeset
   859
    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
   860
        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
   861
1d245fbbeb90 some new field/widgets classes: CompoundField, IntervalWidget, HorizontalLayoutWidget
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2522
diff changeset
   862
1453
a9841184be7c guess_field now takes an entity schema as first argument, not an entity class
sylvain.thenault@logilab.fr
parents: 1437
diff changeset
   863
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
   864
    """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
   865
    '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
   866
    """
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   867
    fieldclass = None
4014
24f7d7eb4c23 yams api update
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3890
diff changeset
   868
    rdef = eschema.rdef(rschema, role)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   869
    if role == 'subject':
4014
24f7d7eb4c23 yams api update
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3890
diff changeset
   870
        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
   871
        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
   872
            if rdef.get('internationalizable'):
2095
897732d3ee5a avoid overriding specified values when guessing field
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2091
diff changeset
   873
                kwargs.setdefault('internationalizable', True)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   874
    else:
4014
24f7d7eb4c23 yams api update
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3890
diff changeset
   875
        targetschema = rdef.subject
4044
3876c894e018 card referenced later
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4023
diff changeset
   876
    card = rdef.role_cardinality(role)
1095
6917ebe281e9 test and fix guess_field, some pylint fixes
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
   877
    kwargs['required'] = card in '1+'
6917ebe281e9 test and fix guess_field, some pylint fixes
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
   878
    kwargs['name'] = rschema.type
4165
eb9acad29407 proper field's role handling: may be 'subject' / 'object' *in case
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4162
diff changeset
   879
    kwargs['role'] = role
3308
88f5f89d8d1b fix generated label for object relation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3299
diff changeset
   880
    if role == 'object':
3574
f179ccbd13e6 [forms] fix generated label for fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3563
diff changeset
   881
        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
   882
    else:
3574
f179ccbd13e6 [forms] fix generated label for fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3563
diff changeset
   883
        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
   884
    kwargs['eidparam'] = True
4014
24f7d7eb4c23 yams api update
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3890
diff changeset
   885
    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
   886
    if rschema.final:
1104
58f27c3c0167 more guess_field tests and fixes
sylvain.thenault@logilab.fr
parents: 1101
diff changeset
   887
        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
   888
            return None
6917ebe281e9 test and fix guess_field, some pylint fixes
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
   889
        fieldclass = FIELDS[targetschema]
6917ebe281e9 test and fix guess_field, some pylint fixes
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
   890
        if fieldclass is StringField:
1104
58f27c3c0167 more guess_field tests and fixes
sylvain.thenault@logilab.fr
parents: 1101
diff changeset
   891
            if eschema.has_metadata(rschema, 'format'):
58f27c3c0167 more guess_field tests and fixes
sylvain.thenault@logilab.fr
parents: 1101
diff changeset
   892
                # use RichTextField instead of StringField if the attribute has
58f27c3c0167 more guess_field tests and fixes
sylvain.thenault@logilab.fr
parents: 1101
diff changeset
   893
                # a "format" metadata. But getting information from constraints
58f27c3c0167 more guess_field tests and fixes
sylvain.thenault@logilab.fr
parents: 1101
diff changeset
   894
                # may be useful anyway...
4014
24f7d7eb4c23 yams api update
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3890
diff changeset
   895
                for cstr in rdef.constraints:
1104
58f27c3c0167 more guess_field tests and fixes
sylvain.thenault@logilab.fr
parents: 1101
diff changeset
   896
                    if isinstance(cstr, StaticVocabularyConstraint):
58f27c3c0167 more guess_field tests and fixes
sylvain.thenault@logilab.fr
parents: 1101
diff changeset
   897
                        raise Exception('rich text field with static vocabulary')
58f27c3c0167 more guess_field tests and fixes
sylvain.thenault@logilab.fr
parents: 1101
diff changeset
   898
                return RichTextField(**kwargs)
1574
0c6dbb774f54 drop text field usage
sylvain.thenault@logilab.fr
parents: 1573
diff changeset
   899
            # init StringField parameters according to constraints
4014
24f7d7eb4c23 yams api update
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3890
diff changeset
   900
            for cstr in rdef.constraints:
1574
0c6dbb774f54 drop text field usage
sylvain.thenault@logilab.fr
parents: 1573
diff changeset
   901
                if isinstance(cstr, StaticVocabularyConstraint):
1577
25b46db3cb81 should set field's choices
sylvain.thenault@logilab.fr
parents: 1574
diff changeset
   902
                    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
   903
                    break
4014
24f7d7eb4c23 yams api update
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3890
diff changeset
   904
            for cstr in rdef.constraints:
1574
0c6dbb774f54 drop text field usage
sylvain.thenault@logilab.fr
parents: 1573
diff changeset
   905
                if isinstance(cstr, SizeConstraint) and cstr.max is not None:
0c6dbb774f54 drop text field usage
sylvain.thenault@logilab.fr
parents: 1573
diff changeset
   906
                    kwargs['max_length'] = cstr.max
0c6dbb774f54 drop text field usage
sylvain.thenault@logilab.fr
parents: 1573
diff changeset
   907
            return StringField(**kwargs)
1104
58f27c3c0167 more guess_field tests and fixes
sylvain.thenault@logilab.fr
parents: 1101
diff changeset
   908
        if fieldclass is FileField:
4160
3fbdeef9a610 cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4159
diff changeset
   909
            for metadata in KNOWN_METAATTRIBUTES:
1104
58f27c3c0167 more guess_field tests and fixes
sylvain.thenault@logilab.fr
parents: 1101
diff changeset
   910
                metaschema = eschema.has_metadata(rschema, metadata)
58f27c3c0167 more guess_field tests and fixes
sylvain.thenault@logilab.fr
parents: 1101
diff changeset
   911
                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
   912
                    kwargs['%s_field' % metadata] = guess_field(eschema, metaschema,
1104
58f27c3c0167 more guess_field tests and fixes
sylvain.thenault@logilab.fr
parents: 1101
diff changeset
   913
                                                                skip_meta_attr=False)
1095
6917ebe281e9 test and fix guess_field, some pylint fixes
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
   914
        return fieldclass(**kwargs)
6917ebe281e9 test and fix guess_field, some pylint fixes
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
   915
    return RelationField.fromcardinality(card, **kwargs)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   916
1986
96c0e56cb0cf move widget selection's logic on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   917
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   918
FIELDS = {
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   919
    'Boolean':  BooleanField,
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   920
    'Bytes':    FileField,
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   921
    'Date':     DateField,
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   922
    'Datetime': DateTimeField,
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   923
    'Int':      IntField,
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   924
    'Float':    FloatField,
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   925
    '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
   926
    'Password': PasswordField,
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   927
    'String' :  StringField,
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   928
    'Time':     TimeField,
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   929
    }