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