web/formfields.py
author Sylvain Thénault <sylvain.thenault@logilab.fr>
Tue, 06 Jul 2010 17:11:44 +0200
changeset 5908 91c61feb5bc8
parent 5816 5d72fbba92e9
child 5911 47216d37bb3d
permissions -rw-r--r--
[forms] bw compat code for vocabulary function returning typed values
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
5421
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5368
diff changeset
     1
# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5368
diff changeset
     2
# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5368
diff changeset
     3
#
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5368
diff changeset
     4
# This file is part of CubicWeb.
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5368
diff changeset
     5
#
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5368
diff changeset
     6
# CubicWeb is free software: you can redistribute it and/or modify it under the
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5368
diff changeset
     7
# terms of the GNU Lesser General Public License as published by the Free
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5368
diff changeset
     8
# Software Foundation, either version 2.1 of the License, or (at your option)
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5368
diff changeset
     9
# any later version.
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5368
diff changeset
    10
#
5424
8ecbcbff9777 replace logilab-common by CubicWeb in disclaimer
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5421
diff changeset
    11
# CubicWeb is distributed in the hope that it will be useful, but WITHOUT
5421
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5368
diff changeset
    12
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5368
diff changeset
    13
# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5368
diff changeset
    14
# details.
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5368
diff changeset
    15
#
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5368
diff changeset
    16
# You should have received a copy of the GNU Lesser General Public License along
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5368
diff changeset
    17
# with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    18
"""
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    19
The Field class and basic fields
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    20
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    21
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    22
.. Note::
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    23
  Fields are used to control what's edited in forms. They makes the link between
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    24
  something to edit and its display in the form. Actual display is handled by a
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    25
  widget associated to the field.
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    26
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    27
Let first see the base class for fields:
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    28
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    29
.. autoclass:: cubicweb.web.formfields.Field
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    30
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    31
Now, you usually don't use that class but one of the concret field classes
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    32
described below, according to what you want to edit.
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    33
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    34
Basic fields
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    35
''''''''''''
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
    36
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    37
.. autoclass:: cubicweb.web.formfields.StringField()
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    38
.. autoclass:: cubicweb.web.formfields.PasswordField()
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    39
.. autoclass:: cubicweb.web.formfields.IntField()
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    40
.. autoclass:: cubicweb.web.formfields.FloatField()
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    41
.. autoclass:: cubicweb.web.formfields.BooleanField()
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    42
.. autoclass:: cubicweb.web.formfields.DateField()
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    43
.. autoclass:: cubicweb.web.formfields.DateTimeField()
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    44
.. autoclass:: cubicweb.web.formfields.TimeField()
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    45
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    46
Compound fields
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    47
''''''''''''''''
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    48
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    49
.. autoclass:: cubicweb.web.formfields.RichTextField()
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    50
.. autoclass:: cubicweb.web.formfields.FileField()
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    51
.. autoclass:: cubicweb.web.formfields.CompoundField()
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    52
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    53
.. autoclass cubicweb.web.formfields.EditableFileField() XXX should be a widget
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    54
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    55
Entity specific fields and function
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    56
'''''''''''''''''''''''''''''''''''
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    57
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    58
.. autoclass:: cubicweb.web.formfields.RelationField()
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    59
.. autofunction:: cubicweb.web.formfields.guess_field
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    60
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
    61
"""
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
    62
__docformat__ = "restructuredtext en"
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
    63
2244
52e2431e7cce missing import
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2196
diff changeset
    64
from warnings import warn
1095
6917ebe281e9 test and fix guess_field, some pylint fixes
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
    65
from datetime import datetime
6917ebe281e9 test and fix guess_field, some pylint fixes
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
    66
2312
af4d8f75c5db use xml_escape
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2244
diff changeset
    67
from logilab.mtconverter import xml_escape
5367
4176a50c81c9 [form] small api cleanup and refactoring before documenting the form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5220
diff changeset
    68
from logilab.common import nullobject
4481
56440a1f816a hidden usage of datetime function which has been moved to lgc
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4443
diff changeset
    69
from logilab.common.date import ustrftime
4158
0e97cf2cf55b missing imports
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4156
diff changeset
    70
5030
5238d9a8dfee [form] put qualified name on validation error, should fix #784299
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4874
diff changeset
    71
from yams.schema import KNOWN_METAATTRIBUTES, role_name
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
    72
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
    73
                              FormatConstraint)
1095
6917ebe281e9 test and fix guess_field, some pylint fixes
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
    74
4481
56440a1f816a hidden usage of datetime function which has been moved to lgc
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4443
diff changeset
    75
from cubicweb import Binary, tags, uilib
4368
d752ad901f14 cleanup module namespace but only importing the formwidgets module
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4359
diff changeset
    76
from cubicweb.web import INTERNAL_FIELD_VALUE, ProcessFormError, eid_param, \
5057
d1bd50ae0edd [form] consider autoform_field_kwargs for meta fields; allow required customization
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5038
diff changeset
    77
     formwidgets as fw, uicfg
1095
6917ebe281e9 test and fix guess_field, some pylint fixes
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
    78
1986
96c0e56cb0cf move widget selection's logic on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
    79
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
    80
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
    81
    """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
    82
    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
    83
    """
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
    84
5756
ab03e4adb4f1 [filefield] normalized file names to deal with windows files
Stephanie Marcu <stephanie.marcu@logilab.fr>
parents: 5661
diff changeset
    85
def normalize_filename(filename):
ab03e4adb4f1 [filefield] normalized file names to deal with windows files
Stephanie Marcu <stephanie.marcu@logilab.fr>
parents: 5661
diff changeset
    86
    return filename.split('\\')[-1]
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
    87
3334
8d831c02da9a fix sort of fields vocabulary: should consider option groups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3308
diff changeset
    88
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
    89
    """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
    90
    result = []
8d831c02da9a fix sort of fields vocabulary: should consider option groups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3308
diff changeset
    91
    partresult = []
8d831c02da9a fix sort of fields vocabulary: should consider option groups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3308
diff changeset
    92
    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
    93
        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
    94
            if partresult:
8d831c02da9a fix sort of fields vocabulary: should consider option groups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3308
diff changeset
    95
                result += sorted(partresult)
8d831c02da9a fix sort of fields vocabulary: should consider option groups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3308
diff changeset
    96
                partresult = []
8d831c02da9a fix sort of fields vocabulary: should consider option groups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3308
diff changeset
    97
            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
    98
        else:
8d831c02da9a fix sort of fields vocabulary: should consider option groups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3308
diff changeset
    99
            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
   100
    result += sorted(partresult)
8d831c02da9a fix sort of fields vocabulary: should consider option groups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3308
diff changeset
   101
    return result
8d831c02da9a fix sort of fields vocabulary: should consider option groups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3308
diff changeset
   102
5367
4176a50c81c9 [form] small api cleanup and refactoring before documenting the form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5220
diff changeset
   103
_MARKER = nullobject()
3334
8d831c02da9a fix sort of fields vocabulary: should consider option groups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3308
diff changeset
   104
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   105
class Field(object):
4443
83ff2bb898a5 start documenting forms
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4395
diff changeset
   106
    """This class is the abstract base class for all fields. It hold a bunch
83ff2bb898a5 start documenting forms
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4395
diff changeset
   107
    of attributes which may be used for fine control of the behaviour of a
83ff2bb898a5 start documenting forms
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4395
diff changeset
   108
    concret field.
1265
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
   109
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   110
    **Attributes**
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   111
4443
83ff2bb898a5 start documenting forms
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4395
diff changeset
   112
    All the attributes described below have sensible default value which may be
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   113
    overriden by named arguments given to field's constructor.
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
   114
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   115
    :attr:`name`
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   116
       base name of the field (basestring). The actual input name is returned by
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   117
       the :meth:`input_name` method and may differ from that name (for instance
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   118
       if `eidparam` is true).
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   119
    :attr:`id`
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   120
       DOM identifier (default to the same value as `name`), should be unique in
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
   121
       a form.
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   122
    :attr:`label`
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
       label of the field (default to the same value as `name`).
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   124
    :attr:`help`
1265
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
   125
       help message about this field.
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   126
    :attr:`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
   127
       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
   128
       class which may be overriden per instance.
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   129
    :attr:`value`
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   130
       field value. May be an actual value or a callable which should take the
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   131
       form as argument and return a value.
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   132
    :attr:`choices`
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   133
       static vocabulary for this field. May be a list of values, a list of
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   134
       (label, value) tuples or a callable which should take the form and field
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   135
       as arguments and return a list of values or a list of (label, value).
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   136
    :attr:`required`
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
   137
       bool flag telling if the field is required or not.
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   138
    :attr:`sort`
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
   139
       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
   140
       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
   141
       sorted on label.
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   142
    :attr:`internationalizable`
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
   143
       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
   144
       current request language.
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   145
    :attr:`eidparam`
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
   146
       bool flag telling if this field is linked to a specific entity
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   147
    :attr:`role`
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
   148
       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
   149
       role of the entity in the relation (eg 'subject' or 'object')
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   150
    :attr:`fieldset`
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
   151
       optional fieldset to which this field belongs to
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   152
    :attr:`order`
3874
7d0d4a6be046 [formfields] allow fields ordering with autoform_field_kwargs
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3873
diff changeset
   153
       key used by automatic forms to sort fields
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   154
    :attr:`ignore_req_params`
4658
25de2eb0432b [form] add a new ignore_req_params attribute on field controlling value's retreival
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4628
diff changeset
   155
       when true, this field won't consider value potentialy specified using
25de2eb0432b [form] add a new ignore_req_params attribute on field controlling value's retreival
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4628
diff changeset
   156
       request's form parameters (eg you won't be able to specify a value using for
25de2eb0432b [form] add a new ignore_req_params attribute on field controlling value's retreival
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4628
diff changeset
   157
       instance url like http://mywebsite.com/form?field=value)
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   158
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   159
    .. currentmodule:: cubicweb.web.formfields
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   160
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   161
    **Generic methods**
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   162
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   163
    .. automethod:: Field.input_name
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   164
    .. automethod:: Field.dom_id
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   165
    .. automethod:: Field.actual_fields
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   166
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   167
    **Form generation methods**
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   168
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   169
    .. automethod:: form_init
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   170
    .. automethod:: typed_value
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   171
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   172
    **Post handling methods**
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   173
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   174
    .. automethod:: process_posted
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   175
    .. automethod:: process_form_value
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   176
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   177
    """
1265
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
   178
    # 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
   179
    # instance
4368
d752ad901f14 cleanup module namespace but only importing the formwidgets module
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4359
diff changeset
   180
    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
   181
    # does this field requires a multipart form
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   182
    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
   183
    # 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
   184
    __creation_rank = 0
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   185
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
   186
    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
   187
    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
   188
    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
   189
    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
   190
    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
   191
    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
   192
    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
   193
    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
   194
    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
   195
    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
   196
    value = _MARKER
4546
f8ac61376b2b provides a fallback_on_none_attribute field attribute, allowing to specify default value for attributes of *existing* entities
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4544
diff changeset
   197
    fallback_on_none_attribute = False
4658
25de2eb0432b [form] add a new ignore_req_params attribute on field controlling value's retreival
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4628
diff changeset
   198
    ignore_req_params = 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
   199
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
   200
    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
   201
        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
   202
            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
   203
                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
   204
                     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
   205
                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
   206
            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
   207
            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
   208
        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
   209
        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
   210
            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
   211
        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
   212
        # 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
   213
        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
   214
        # 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
   215
        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
   216
        Field.__creation_rank += 1
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
   217
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   218
    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
   219
        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
   220
            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
   221
            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
   222
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   223
    def __repr__(self):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   224
        return self.__unicode__().encode('utf-8')
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   225
1986
96c0e56cb0cf move widget selection's logic on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   226
    def init_widget(self, widget):
96c0e56cb0cf move widget selection's logic on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   227
        if widget is not None:
96c0e56cb0cf move widget selection's logic on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   228
            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
   229
        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
   230
            self.widget = fw.Select()
1986
96c0e56cb0cf move widget selection's logic on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   231
        if isinstance(self.widget, type):
96c0e56cb0cf move widget selection's logic on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   232
            self.widget = self.widget()
96c0e56cb0cf move widget selection's logic on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   233
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   234
    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
   235
        """automatically set .label when name is set"""
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   236
        assert name
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   237
        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
   238
        if self.label is _MARKER:
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   239
            self.label = name
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
   240
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   241
    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
   242
        """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
   243
        return not isinstance(self.widget, fw.HiddenInput)
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
    def actual_fields(self, form):
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   246
        """Fields may be composed of other fields. For instance the
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   247
        :class:`~cubicweb.web.formfields.RichTextField` is containing a format
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   248
        field to define the text format. This method returns actual fields that
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   249
        should be considered for display / edition. It usually simply return
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   250
        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
   251
        """
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   252
        yield self
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
   253
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   254
    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
   255
        """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
   256
        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
   257
        """
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   258
        if isinstance(value, (list, tuple)):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   259
            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
   260
        return self.format_single_value(req, value)
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
   261
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   262
    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
   263
        """return value suitable for display"""
1306
e70ad982374a bool handling
sylvain.thenault@logilab.fr
parents: 1305
diff changeset
   264
        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
   265
            return u''
1306
e70ad982374a bool handling
sylvain.thenault@logilab.fr
parents: 1305
diff changeset
   266
        if value is True:
e70ad982374a bool handling
sylvain.thenault@logilab.fr
parents: 1305
diff changeset
   267
            return u'1'
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   268
        return unicode(value)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   269
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   270
    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
   271
        """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
   272
        return self.widget
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
   273
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
   274
    def input_name(self, form, suffix=None):
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   275
        """Return the 'qualified name' for this field, e.g. something suitable
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   276
        to use as HTML input name. You can specify a suffix that will be
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   277
        included in the name when widget needs several inputs.
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   278
        """
4871
a34b76593ab2 [form fields] fix severe memory leak due to @cached on field.input_name
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4661
diff changeset
   279
        # caching is necessary else we get some pb on entity creation :
a34b76593ab2 [form fields] fix severe memory leak due to @cached on field.input_name
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4661
diff changeset
   280
        # entity.eid is modified from creation mark (eg 'X') to its actual eid
a34b76593ab2 [form fields] fix severe memory leak due to @cached on field.input_name
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4661
diff changeset
   281
        # (eg 123), and then `field.input_name()` won't return the right key
a34b76593ab2 [form fields] fix severe memory leak due to @cached on field.input_name
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4661
diff changeset
   282
        # anymore if not cached (first call to input_name done *before* eventual
a34b76593ab2 [form fields] fix severe memory leak due to @cached on field.input_name
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4661
diff changeset
   283
        # eid affectation).
a34b76593ab2 [form fields] fix severe memory leak due to @cached on field.input_name
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4661
diff changeset
   284
        #
a34b76593ab2 [form fields] fix severe memory leak due to @cached on field.input_name
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4661
diff changeset
   285
        # note that you should NOT use @cached else it will create a memory leak
a34b76593ab2 [form fields] fix severe memory leak due to @cached on field.input_name
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4661
diff changeset
   286
        # on persistent fields (eg created once for all on a form class) because
a34b76593ab2 [form fields] fix severe memory leak due to @cached on field.input_name
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4661
diff changeset
   287
        # of the 'form' appobject argument: the cache will keep growing as new
a34b76593ab2 [form fields] fix severe memory leak due to @cached on field.input_name
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4661
diff changeset
   288
        # form are created...
a34b76593ab2 [form fields] fix severe memory leak due to @cached on field.input_name
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4661
diff changeset
   289
        try:
4874
344857257672 [form] fix bug introduced by 4871:a34b76593ab2 with field using multiple input with different suffix: the suffix should be considered in the cache key
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4871
diff changeset
   290
            return form.formvalues[(self, 'input_name', suffix)]
4871
a34b76593ab2 [form fields] fix severe memory leak due to @cached on field.input_name
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4661
diff changeset
   291
        except KeyError:
a34b76593ab2 [form fields] fix severe memory leak due to @cached on field.input_name
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4661
diff changeset
   292
            name = self.role_name()
a34b76593ab2 [form fields] fix severe memory leak due to @cached on field.input_name
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4661
diff changeset
   293
            if suffix is not None:
a34b76593ab2 [form fields] fix severe memory leak due to @cached on field.input_name
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4661
diff changeset
   294
                name += suffix
a34b76593ab2 [form fields] fix severe memory leak due to @cached on field.input_name
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4661
diff changeset
   295
            if self.eidparam:
a34b76593ab2 [form fields] fix severe memory leak due to @cached on field.input_name
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4661
diff changeset
   296
                name = eid_param(name, form.edited_entity.eid)
4874
344857257672 [form] fix bug introduced by 4871:a34b76593ab2 with field using multiple input with different suffix: the suffix should be considered in the cache key
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4871
diff changeset
   297
            form.formvalues[(self, 'input_name', suffix)] = name
4871
a34b76593ab2 [form fields] fix severe memory leak due to @cached on field.input_name
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4661
diff changeset
   298
            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
   299
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
   300
    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
   301
        """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
   302
        if self.role is not None:
5030
5238d9a8dfee [form] put qualified name on validation error, should fix #784299
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4874
diff changeset
   303
            return role_name(self.name, self.role)
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
   304
        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
   305
4303
35e814dce815 dom_id now accepts a suffix argument as input_name
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4302
diff changeset
   306
    def dom_id(self, form, suffix=None):
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   307
        """Return the HTML DOM identifier for this field, e.g. something
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   308
        suitable to use as HTML input id. You can specify a suffix that will be
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   309
        included in the name when widget needs several inputs.
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   310
        """
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
   311
        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
   312
        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
   313
            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
   314
        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
   315
            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
   316
        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
   317
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
   318
    def typed_value(self, form, load_bytes=False):
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   319
        """Return the correctly typed value for this field in the form context.
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   320
        """
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
   321
        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
   322
            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
   323
            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
   324
                if entity.has_eid() or self.name in entity:
4546
f8ac61376b2b provides a fallback_on_none_attribute field attribute, allowing to specify default value for attributes of *existing* entities
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4544
diff changeset
   325
                    value = getattr(entity, self.name)
f8ac61376b2b provides a fallback_on_none_attribute field attribute, allowing to specify default value for attributes of *existing* entities
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4544
diff changeset
   326
                    if value is not None or not self.fallback_on_none_attribute:
f8ac61376b2b provides a fallback_on_none_attribute field attribute, allowing to specify default value for attributes of *existing* entities
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4544
diff changeset
   327
                        return value
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5497
diff changeset
   328
            elif entity.has_eid() or entity.cw_relation_cached(self.name, self.role):
4546
f8ac61376b2b provides a fallback_on_none_attribute field attribute, allowing to specify default value for attributes of *existing* entities
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4544
diff changeset
   329
                value = [r[0] for r in entity.related(self.name, self.role)]
f8ac61376b2b provides a fallback_on_none_attribute field attribute, allowing to specify default value for attributes of *existing* entities
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4544
diff changeset
   330
                if value or not self.fallback_on_none_attribute:
f8ac61376b2b provides a fallback_on_none_attribute field attribute, allowing to specify default value for attributes of *existing* entities
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4544
diff changeset
   331
                    return value
4369
6d3dae46ee95 fix typed_value implementation w/ eidparam field which are actual entity's relation and have .value set for their initial value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4368
diff changeset
   332
        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
   333
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
   334
    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
   335
        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
   336
            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
   337
                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
   338
            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
   339
        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
   340
        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
   341
            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
   342
                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
   343
            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
   344
        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
   345
            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
   346
                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
   347
            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
   348
        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
   349
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   350
    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
   351
        """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
   352
        field
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
   353
        """
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   354
        return u''
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   355
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   356
    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
   357
        """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
   358
        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
   359
        """
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
   360
        widget = self.get_widget(form)
3873
4d95109582c7 [web] remove widget.render backward compatibility
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3790
diff changeset
   361
        return widget.render(form, self, renderer)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   362
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
   363
    def vocabulary(self, form, **kwargs):
5908
91c61feb5bc8 [forms] bw compat code for vocabulary function returning typed values
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5816
diff changeset
   364
        """return vocabulary for this field. This method will be
91c61feb5bc8 [forms] bw compat code for vocabulary function returning typed values
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5816
diff changeset
   365
        called by widgets which requires a vocabulary.
91c61feb5bc8 [forms] bw compat code for vocabulary function returning typed values
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5816
diff changeset
   366
91c61feb5bc8 [forms] bw compat code for vocabulary function returning typed values
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5816
diff changeset
   367
        It should return a list of tuple (label, value), where value
91c61feb5bc8 [forms] bw compat code for vocabulary function returning typed values
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5816
diff changeset
   368
        *must be an unicode string*, not a typed value.
4161
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   369
        """
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   370
        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
   371
        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
   372
            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
   373
                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
   374
                    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
   375
                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
   376
                    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
   377
            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
   378
                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
   379
                    vocab = self.choices(form=form, **kwargs)
4499
4f741341d96f avoid to see the same warning twice, one for 3.6 another for 3.3
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4495
diff changeset
   380
                    warn('[3.6]  %s: choices should now take '
4f741341d96f avoid to see the same warning twice, one for 3.6 another for 3.3
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4495
diff changeset
   381
                         'the form and field as named arguments' % self,
4f741341d96f avoid to see the same warning twice, one for 3.6 another for 3.3
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4495
diff changeset
   382
                         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
   383
                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
   384
                    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
   385
                         '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
   386
                         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
   387
                    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
   388
        else:
4170
c325c62cec8e crecord introduced junk...
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4168
diff changeset
   389
            vocab = self.choices
c325c62cec8e crecord introduced junk...
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4168
diff changeset
   390
        if vocab and not isinstance(vocab[0], (list, tuple)):
c325c62cec8e crecord introduced junk...
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4168
diff changeset
   391
            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
   392
        if self.internationalizable:
5908
91c61feb5bc8 [forms] bw compat code for vocabulary function returning typed values
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5816
diff changeset
   393
            # the short-cirtcuit 'and' boolean operator is used here
91c61feb5bc8 [forms] bw compat code for vocabulary function returning typed values
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5816
diff changeset
   394
            # to permit a valid empty string in vocabulary without
91c61feb5bc8 [forms] bw compat code for vocabulary function returning typed values
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5816
diff changeset
   395
            # attempting to translate it by gettext (which can lead to
91c61feb5bc8 [forms] bw compat code for vocabulary function returning typed values
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5816
diff changeset
   396
            # weird strings display)
91c61feb5bc8 [forms] bw compat code for vocabulary function returning typed values
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5816
diff changeset
   397
            vocab = [(label and form._cw._(label), value)
91c61feb5bc8 [forms] bw compat code for vocabulary function returning typed values
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5816
diff changeset
   398
                     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
   399
        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
   400
            vocab = vocab_sort(vocab)
5908
91c61feb5bc8 [forms] bw compat code for vocabulary function returning typed values
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5816
diff changeset
   401
        # XXX pre 3.9 bw compat
91c61feb5bc8 [forms] bw compat code for vocabulary function returning typed values
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5816
diff changeset
   402
        for i, (label, value) in enumerate(vocab):
91c61feb5bc8 [forms] bw compat code for vocabulary function returning typed values
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5816
diff changeset
   403
            if not isinstance(value, basestring):
91c61feb5bc8 [forms] bw compat code for vocabulary function returning typed values
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5816
diff changeset
   404
                warn('[3.9] %s: vocabulary value should be an unicode string'
91c61feb5bc8 [forms] bw compat code for vocabulary function returning typed values
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5816
diff changeset
   405
                     % self, DeprecationWarning)
91c61feb5bc8 [forms] bw compat code for vocabulary function returning typed values
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5816
diff changeset
   406
                vocab[i] = (label, unicode(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
   407
        return vocab
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
   408
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
   409
    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
   410
        """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
   411
        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
   412
            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
   413
            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
   414
                entity.has_eid() or '%s_format' % self.name in entity):
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5497
diff changeset
   415
                return form.edited_entity.cw_attr_metadata(self.name, 'format')
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
   416
        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
   417
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
   418
    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
   419
        """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
   420
        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
   421
            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
   422
            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
   423
                entity.has_eid() or '%s_encoding' % self.name in entity):
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5497
diff changeset
   424
                return form.edited_entity.cw_attr_metadata(self.name, 'encoding')
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
   425
        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
   426
1307
8c3336c5ddba new form_init callback
sylvain.thenault@logilab.fr
parents: 1306
diff changeset
   427
    def form_init(self, form):
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   428
        """Method called at form initialization to trigger potential field
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   429
        initialization requiring the form instance. Do nothing by default.
1307
8c3336c5ddba new form_init callback
sylvain.thenault@logilab.fr
parents: 1306
diff changeset
   430
        """
8c3336c5ddba new form_init callback
sylvain.thenault@logilab.fr
parents: 1306
diff changeset
   431
        pass
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
   432
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
   433
    def has_been_modified(self, form):
5697
ec1ce7198ef4 [form] fix untested (unread?) has_been_modified implementation...
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5679
diff changeset
   434
        for field in self.actual_fields(form):
ec1ce7198ef4 [form] fix untested (unread?) has_been_modified implementation...
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5679
diff changeset
   435
            if field._has_been_modified(form):
5676
aa04ccb8dd62 [edit ctrl] fix bad interaction with fields: the loop on actual fields should be done in has_been_modified
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5557
diff changeset
   436
                return True # XXX
aa04ccb8dd62 [edit ctrl] fix bad interaction with fields: the loop on actual fields should be done in has_been_modified
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5557
diff changeset
   437
        return False # not modified
aa04ccb8dd62 [edit ctrl] fix bad interaction with fields: the loop on actual fields should be done in has_been_modified
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5557
diff changeset
   438
aa04ccb8dd62 [edit ctrl] fix bad interaction with fields: the loop on actual fields should be done in has_been_modified
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5557
diff changeset
   439
    def _has_been_modified(self, form):
4495
99c18d3f9542 unvisible field may have been modified, for instance relation added by an hidden input
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4481
diff changeset
   440
        # fields not corresponding to an entity attribute / relations
99c18d3f9542 unvisible field may have been modified, for instance relation added by an hidden input
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4481
diff changeset
   441
        # are considered modified
99c18d3f9542 unvisible field may have been modified, for instance relation added by an hidden input
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4481
diff changeset
   442
        if not self.eidparam or not self.role or not form.edited_entity.has_eid():
99c18d3f9542 unvisible field may have been modified, for instance relation added by an hidden input
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4481
diff changeset
   443
            return True # XXX
99c18d3f9542 unvisible field may have been modified, for instance relation added by an hidden input
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4481
diff changeset
   444
        try:
99c18d3f9542 unvisible field may have been modified, for instance relation added by an hidden input
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4481
diff changeset
   445
            if self.role == 'subject':
99c18d3f9542 unvisible field may have been modified, for instance relation added by an hidden input
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4481
diff changeset
   446
                previous_value = getattr(form.edited_entity, self.name)
99c18d3f9542 unvisible field may have been modified, for instance relation added by an hidden input
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4481
diff changeset
   447
            else:
99c18d3f9542 unvisible field may have been modified, for instance relation added by an hidden input
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4481
diff changeset
   448
                previous_value = getattr(form.edited_entity,
99c18d3f9542 unvisible field may have been modified, for instance relation added by an hidden input
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4481
diff changeset
   449
                                         'reverse_%s' % self.name)
99c18d3f9542 unvisible field may have been modified, for instance relation added by an hidden input
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4481
diff changeset
   450
        except AttributeError:
99c18d3f9542 unvisible field may have been modified, for instance relation added by an hidden input
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4481
diff changeset
   451
            # fields with eidparam=True but not corresponding to an actual
99c18d3f9542 unvisible field may have been modified, for instance relation added by an hidden input
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4481
diff changeset
   452
            # attribute or relation
4162
d2663bcf5306 replace form_field_[encoding|vocabulary] methods on form by encoding|vocabylary(form) methods on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4161
diff changeset
   453
            return True
4495
99c18d3f9542 unvisible field may have been modified, for instance relation added by an hidden input
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4481
diff changeset
   454
        # if it's a non final relation, we need the eids
5661
84ef08bbda3c [web/formwidgets] check on list (entity.related_cache swapped from tuple to list a while ago without known reasons), do not unicode wrap the eids
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 5497
diff changeset
   455
        # XXX underlying regression: getattr(ent, 'foo') used to return
84ef08bbda3c [web/formwidgets] check on list (entity.related_cache swapped from tuple to list a while ago without known reasons), do not unicode wrap the eids
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 5497
diff changeset
   456
        #     a tuple, now we get a list
84ef08bbda3c [web/formwidgets] check on list (entity.related_cache swapped from tuple to list a while ago without known reasons), do not unicode wrap the eids
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 5497
diff changeset
   457
        if isinstance(previous_value, (list, tuple)):
4495
99c18d3f9542 unvisible field may have been modified, for instance relation added by an hidden input
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4481
diff changeset
   458
            # widget should return a set of untyped eids
5661
84ef08bbda3c [web/formwidgets] check on list (entity.related_cache swapped from tuple to list a while ago without known reasons), do not unicode wrap the eids
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 5497
diff changeset
   459
            previous_value = set(e.eid for e in previous_value)
4495
99c18d3f9542 unvisible field may have been modified, for instance relation added by an hidden input
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4481
diff changeset
   460
        try:
99c18d3f9542 unvisible field may have been modified, for instance relation added by an hidden input
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4481
diff changeset
   461
            new_value = self.process_form_value(form)
99c18d3f9542 unvisible field may have been modified, for instance relation added by an hidden input
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4481
diff changeset
   462
        except ProcessFormError:
99c18d3f9542 unvisible field may have been modified, for instance relation added by an hidden input
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4481
diff changeset
   463
            return True
99c18d3f9542 unvisible field may have been modified, for instance relation added by an hidden input
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4481
diff changeset
   464
        except UnmodifiedField:
5676
aa04ccb8dd62 [edit ctrl] fix bad interaction with fields: the loop on actual fields should be done in has_been_modified
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5557
diff changeset
   465
            return False # not modified
4495
99c18d3f9542 unvisible field may have been modified, for instance relation added by an hidden input
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4481
diff changeset
   466
        if previous_value == new_value:
99c18d3f9542 unvisible field may have been modified, for instance relation added by an hidden input
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4481
diff changeset
   467
            return False # not modified
99c18d3f9542 unvisible field may have been modified, for instance relation added by an hidden input
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4481
diff changeset
   468
        return True
4162
d2663bcf5306 replace form_field_[encoding|vocabulary] methods on form by encoding|vocabylary(form) methods on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4161
diff changeset
   469
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
   470
    def process_form_value(self, form):
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   471
        """Return the correctly typed value posted for this field."""
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
   472
        try:
4661
87672c718c3c [form] cache field value in form.formvalues using (field, form) key since in some case the same field instance may be shared accross multiple forms, which may share the formvalues dict in case of sub-forms
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4658
diff changeset
   473
            return form.formvalues[(self, 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
   474
        except KeyError:
4661
87672c718c3c [form] cache field value in form.formvalues using (field, form) key since in some case the same field instance may be shared accross multiple forms, which may share the formvalues dict in case of sub-forms
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4658
diff changeset
   475
            value = form.formvalues[(self, form)] = self._process_form_value(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
   476
            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
   477
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
   478
    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
   479
        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
   480
        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
   481
        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
   482
75c610a85949 introduce new _ensure_correctly_typed method on fields, responsible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4369
diff changeset
   483
    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
   484
        """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
   485
        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
   486
        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
   487
        """
4392
91a56a30141e by default this is not the widget responsability to turn empty string into None,
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4388
diff changeset
   488
        return value or None
3387
a357d4147eee [forms] work-in-progress, big editcontroller refactoring: let fields/widgets process posted data
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3385
diff changeset
   489
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
   490
    def process_posted(self, form):
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   491
        """Return an iterator on (field, value) that has been posted for
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   492
        field returned by :meth:`~cubicweb.web.formfields.Field.actual_fields`.
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   493
        """
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
   494
        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
   495
            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
   496
                try:
5038
90493551b1eb [form] fix validation error handling
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5030
diff changeset
   497
                    value = field.process_form_value(form)
90493551b1eb [form] fix validation error handling
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5030
diff changeset
   498
                    if value is None and field.required:
90493551b1eb [form] fix validation error handling
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5030
diff changeset
   499
                        raise ProcessFormError(form._cw._("required field"))
90493551b1eb [form] fix validation error handling
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5030
diff changeset
   500
                    yield field, value
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
   501
                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
   502
                    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
   503
            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
   504
                # 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
   505
                # 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
   506
                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
   507
                    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
   508
1986
96c0e56cb0cf move widget selection's logic on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   509
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   510
class StringField(Field):
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   511
    """Use this field to edit unicode string (`String` yams type). This field
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   512
    additionaly support a `max_length` attribute that specify a maximum size for
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   513
    the string (`None` meaning no limit).
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   514
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   515
    Unless explicitly specified, the widget for this field will be:
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   516
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   517
    * :class:`~cubicweb.web.formwidgets.Select` if some vocabulary is specified
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   518
      using `choices` attribute
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   519
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   520
    * :class:`~cubicweb.web.formwidgets.TextInput` if maximum size is specified
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   521
      using `max_length` attribute and this length is inferior to 257.
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   522
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   523
    * :class:`~cubicweb.web.formwidgets.TextArea` in all other cases
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   524
    """
4368
d752ad901f14 cleanup module namespace but only importing the formwidgets module
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4359
diff changeset
   525
    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
   526
    size = 45
1986
96c0e56cb0cf move widget selection's logic on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   527
4168
9d83f9c80c1c nicer StringField __init__
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4166
diff changeset
   528
    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
   529
        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
   530
        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
   531
96c0e56cb0cf move widget selection's logic on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   532
    def init_widget(self, widget):
96c0e56cb0cf move widget selection's logic on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   533
        if widget is None:
96c0e56cb0cf move widget selection's logic on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   534
            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
   535
                widget = fw.Select()
1986
96c0e56cb0cf move widget selection's logic on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   536
            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
   537
                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
   538
1986
96c0e56cb0cf move widget selection's logic on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   539
        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
   540
        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
   541
            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
   542
        elif isinstance(self.widget, fw.TextInput):
2360
1d43aa551ba9 [formwidgets,formfields] hum, this way
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 2356
diff changeset
   543
            self.init_text_input(self.widget)
1d43aa551ba9 [formwidgets,formfields] hum, this way
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 2356
diff changeset
   544
1d43aa551ba9 [formwidgets,formfields] hum, this way
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 2356
diff changeset
   545
    def init_text_input(self, widget):
1d43aa551ba9 [formwidgets,formfields] hum, this way
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 2356
diff changeset
   546
        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
   547
            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
   548
            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
   549
d34589d35daa drop TextField, this is simply a StringField with a text area widget
sylvain.thenault@logilab.fr
parents: 1564
diff changeset
   550
    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
   551
        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
   552
            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
   553
            widget.attrs.setdefault('rows', 5)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   554
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   555
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
   556
class PasswordField(StringField):
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   557
    """Use this field to edit password (`Password` yams type, encoded python
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   558
    string).
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   559
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   560
    Unless explicitly specified, the widget for this field will be
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   561
    a :class:`~cubicweb.web.formwidgets.PasswordInput`.
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   562
    """
4368
d752ad901f14 cleanup module namespace but only importing the formwidgets module
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4359
diff changeset
   563
    widget = fw.PasswordInput
4628
2f23148d0870 [form fields] nicer behaviour of the password field: don't put internal field value on edition (triggering validation error if one validation without removing the value, due to confirmation mismatch), and don't show the field as required in such case
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4583
diff changeset
   564
    def form_init(self, form):
2f23148d0870 [form fields] nicer behaviour of the password field: don't put internal field value on edition (triggering validation error if one validation without removing the value, due to confirmation mismatch), and don't show the field as required in such case
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4583
diff changeset
   565
        if self.eidparam and form.edited_entity.has_eid():
2f23148d0870 [form fields] nicer behaviour of the password field: don't put internal field value on edition (triggering validation error if one validation without removing the value, due to confirmation mismatch), and don't show the field as required in such case
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4583
diff changeset
   566
            # see below: value is probably set but we can't retreive it. Ensure
2f23148d0870 [form fields] nicer behaviour of the password field: don't put internal field value on edition (triggering validation error if one validation without removing the value, due to confirmation mismatch), and don't show the field as required in such case
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4583
diff changeset
   567
            # the field isn't show as a required field on modification
2f23148d0870 [form fields] nicer behaviour of the password field: don't put internal field value on edition (triggering validation error if one validation without removing the value, due to confirmation mismatch), and don't show the field as required in such case
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4583
diff changeset
   568
            self.required = 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
   569
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
   570
    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
   571
        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
   572
            # 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
   573
            if form.edited_entity.has_eid():
4628
2f23148d0870 [form fields] nicer behaviour of the password field: don't put internal field value on edition (triggering validation error if one validation without removing the value, due to confirmation mismatch), and don't show the field as required in such case
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4583
diff changeset
   574
                return ''
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
   575
            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
   576
        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
   577
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   578
1573
d34589d35daa drop TextField, this is simply a StringField with a text area widget
sylvain.thenault@logilab.fr
parents: 1564
diff changeset
   579
class RichTextField(StringField):
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   580
    """This compound field allow edition of text (unicode string) in
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   581
    a particular format. It has an inner field holding the text format,
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   582
    that can be specified using `format_field` argument. If not specified
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   583
    one will be automaticall generated.
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   584
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   585
    Unless explicitly specified, the widget for this field will be a
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   586
    :class:`~cubicweb.web.formwidgets.FCKEditor` or a
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   587
    :class:`~cubicweb.web.formwidgets.TextArea`. according to the field's
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   588
    format and to user's preferences.
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   589
    """
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   590
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   591
    widget = None
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   592
    def __init__(self, format_field=None, **kwargs):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   593
        super(RichTextField, self).__init__(**kwargs)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   594
        self.format_field = format_field
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   595
2348
acf4b6a59558 [formwidgets] ensure textarea for richstring has not ridicuously small size (close #344547)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 2347
diff changeset
   596
    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
   597
        pass
acf4b6a59558 [formwidgets] ensure textarea for richstring has not ridicuously small size (close #344547)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 2347
diff changeset
   598
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   599
    def get_widget(self, form):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   600
        if self.widget is None:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   601
            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
   602
                return fw.FCKEditor()
d752ad901f14 cleanup module namespace but only importing the formwidgets module
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4359
diff changeset
   603
            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
   604
            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
   605
            return widget
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   606
        return self.widget
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   607
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   608
    def get_format_field(self, form):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   609
        if self.format_field:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   610
            return self.format_field
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   611
        # 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
   612
        # context dictionnary
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3388
diff changeset
   613
        req = form._cw
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   614
        try:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   615
            return req.data[self]
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   616
        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
   617
            fkwargs = {'eidparam': self.eidparam, 'role': self.role}
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   618
            if self.use_fckeditor(form):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   619
                # 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
   620
                # 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
   621
                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
   622
                fkwargs['value'] = 'text/html'
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   623
            else:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   624
                # 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
   625
                fkwargs['widget'] = fw.Select()
1095
6917ebe281e9 test and fix guess_field, some pylint fixes
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
   626
                fcstr = FormatConstraint()
3347
428f95118556 fix vocab param to avoid deprecation warning
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3337
diff changeset
   627
                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
   628
                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
   629
                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
   630
            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
   631
            field = StringField(name=self.name + '_format', **fkwargs)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   632
            req.data[self] = field
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   633
            return field
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
   634
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   635
    def actual_fields(self, form):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   636
        yield self
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   637
        format_field = self.get_format_field(form)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   638
        if format_field:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   639
            yield format_field
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
   640
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   641
    def use_fckeditor(self, form):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   642
        """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
   643
        `attr`, according to user preferences
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   644
        """
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3388
diff changeset
   645
        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
   646
            return self.format(form) == 'text/html'
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   647
        return False
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   648
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   649
    def render(self, form, renderer):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   650
        format_field = self.get_format_field(form)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   651
        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
   652
            # 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
   653
            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
   654
                format_field.widget.attrs['style'] = 'display: block'
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   655
            result = format_field.render(form, renderer)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   656
        else:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   657
            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
   658
        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
   659
1417
06af20e663f2 remove spaces
sylvain.thenault@logilab.fr
parents: 1393
diff changeset
   660
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   661
class FileField(StringField):
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   662
    """This compound field allow edition of binary stream (`Bytes` yams
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   663
    type). Three inner fields may be specified:
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   664
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   665
    * `format_field`, holding the file's format.
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   666
    * `encoding_field`, holding the file's content encoding.
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   667
    * `name_field`, holding the file's name.
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   668
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   669
    Unless explicitly specified, the widget for this field will be a
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   670
    :class:`~cubicweb.web.formwidgets.FileInput`. Inner fields, if any,
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   671
    will be added to a drop down menu at the right of the file input.
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   672
    """
4368
d752ad901f14 cleanup module namespace but only importing the formwidgets module
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4359
diff changeset
   673
    widget = fw.FileInput
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   674
    needs_multipart = True
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
   675
3496
35a67ac6efe8 support name metadata on guess_field; add name_field to FileField
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3347
diff changeset
   676
    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
   677
                 **kwargs):
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   678
        super(FileField, self).__init__(**kwargs)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   679
        self.format_field = format_field
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   680
        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
   681
        self.name_field = name_field
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
   682
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   683
    def actual_fields(self, form):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   684
        yield self
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   685
        if self.format_field:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   686
            yield self.format_field
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   687
        if self.encoding_field:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   688
            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
   689
        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
   690
            yield self.name_field
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   691
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
   692
    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
   693
        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
   694
            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
   695
                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
   696
                    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
   697
                # 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
   698
                # 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
   699
                # * 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
   700
                # * 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
   701
                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
   702
            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
   703
        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
   704
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   705
    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
   706
        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
   707
        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
   708
            divid = '%s-advanced' % self.input_name(form)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   709
            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
   710
                        (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
   711
                         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
   712
                         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
   713
                         form._cw._('show advanced fields')))
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   714
            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
   715
            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
   716
                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
   717
            if self.format_field:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   718
                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
   719
            if self.encoding_field:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   720
                wdgs.append(self.render_subfield(form, self.encoding_field, renderer))
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
   721
            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
   722
        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
   723
            # 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
   724
            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
   725
            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
   726
                                   type=u'checkbox'))
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3388
diff changeset
   727
            wdgs.append(form._cw._('detach attached file'))
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   728
        return u'\n'.join(wdgs)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   729
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   730
    def render_subfield(self, form, field, renderer):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   731
        return (renderer.render_label(form, field)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   732
                + field.render(form, renderer)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   733
                + renderer.render_help(form, field)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   734
                + u'<br/>')
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   735
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
   736
    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
   737
        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
   738
        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
   739
            # 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
   740
            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
   741
        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
   742
            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
   743
        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
   744
            # 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
   745
            # 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
   746
            raise UnmodifiedField()
5270
6297d5265572 [etwist] allow to specify max size for POST request in the configuration. We should deal with this nicely on the js form validation code.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5238
diff changeset
   747
        # value is a 2-uple (filename, stream)
5497
96fd339f7917 Handle new way of reporting unmodified FileFields
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 5426
diff changeset
   748
        try:
96fd339f7917 Handle new way of reporting unmodified FileFields
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 5426
diff changeset
   749
            filename, stream = value
96fd339f7917 Handle new way of reporting unmodified FileFields
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 5426
diff changeset
   750
        except ValueError:
96fd339f7917 Handle new way of reporting unmodified FileFields
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 5426
diff changeset
   751
            raise UnmodifiedField()
5270
6297d5265572 [etwist] allow to specify max size for POST request in the configuration. We should deal with this nicely on the js form validation code.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5238
diff changeset
   752
        # XXX avoid in memory loading of posted files. Requires Binary handling changes...
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
   753
        value = Binary(stream.read())
4273
183cd0df6f1a fix dumb name error
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4272
diff changeset
   754
        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
   755
            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
   756
        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
   757
            # set filename on the Binary instance, may be used later in hooks
5756
ab03e4adb4f1 [filefield] normalized file names to deal with windows files
Stephanie Marcu <stephanie.marcu@logilab.fr>
parents: 5661
diff changeset
   758
            value.filename = normalize_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
   759
        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
   760
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
   761
5367
4176a50c81c9 [form] small api cleanup and refactoring before documenting the form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5220
diff changeset
   762
# XXX turn into a widget
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   763
class EditableFileField(FileField):
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   764
    """This compound field allow edition of binary stream as
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   765
    :class:`~cubicweb.web.formfields.FileField` but expect that stream to
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   766
    actually contains some text.
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   767
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   768
    If the stream format is one of text/plain, text/html, text/rest,
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   769
    then a :class:`~cubicweb.web.formwidgets.TextArea` will be additionaly
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   770
    displayed, allowing to directly the file's content when desired, instead
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   771
    of choosing a file from user's file system.
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   772
    """
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   773
    editable_formats = ('text/plain', 'text/html', 'text/rest')
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
   774
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   775
    def render(self, form, renderer):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   776
        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
   777
        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
   778
            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
   779
            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
   780
                encoding = self.encoding(form)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   781
                try:
4661
87672c718c3c [form] cache field value in form.formvalues using (field, form) key since in some case the same field instance may be shared accross multiple forms, which may share the formvalues dict in case of sub-forms
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4658
diff changeset
   782
                    form.formvalues[(self, form)] = unicode(data.getvalue(), encoding)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   783
                except UnicodeError:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   784
                    pass
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   785
                else:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   786
                    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
   787
                        msg = form._cw._(
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   788
                            '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
   789
                            ', 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
   790
                            '"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
   791
                            'with the widget below.')
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   792
                    else:
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3388
diff changeset
   793
                        msg = form._cw._(
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   794
                            '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
   795
                            ', 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
   796
                    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
   797
                    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
   798
                    # XXX restore form context?
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   799
        return '\n'.join(wdgs)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   800
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
   801
    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
   802
        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
   803
        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
   804
            # 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
   805
            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
   806
        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
   807
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
   808
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   809
class IntField(Field):
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   810
    """Use this field to edit integers (`Int` yams type). This field additionaly
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   811
    support `min` and `max` attributes that specify a minimum and/or maximum
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   812
    value for the integer (`None` meaning no boundary).
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   813
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   814
    Unless explicitly specified, the widget for this field will be a
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   815
    :class:`~cubicweb.web.formwidgets.TextInput`.
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   816
    """
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   817
    def __init__(self, min=None, max=None, **kwargs):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   818
        super(IntField, self).__init__(**kwargs)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   819
        self.min = min
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   820
        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
   821
        if isinstance(self.widget, fw.TextInput):
1758
d46f59e5efd3 some widget adjustments
sylvain.thenault@logilab.fr
parents: 1738
diff changeset
   822
            self.widget.attrs.setdefault('size', 5)
d46f59e5efd3 some widget adjustments
sylvain.thenault@logilab.fr
parents: 1738
diff changeset
   823
            self.widget.attrs.setdefault('maxlength', 15)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   824
4370
75c610a85949 introduce new _ensure_correctly_typed method on fields, responsible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4369
diff changeset
   825
    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
   826
        if isinstance(value, basestring):
4528
a51f37efc882 quick fix for typed formfield validation: accept empty string, split
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4499
diff changeset
   827
            value = value.strip()
a51f37efc882 quick fix for typed formfield validation: accept empty string, split
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4499
diff changeset
   828
            if not value:
a51f37efc882 quick fix for typed formfield validation: accept empty string, split
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4499
diff changeset
   829
                return None
4225
c49bb6e3d343 fix process_form_values: we should handle value errors and properly raise ProcessFormError
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4181
diff changeset
   830
            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
   831
                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
   832
            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
   833
                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
   834
        return value
1986
96c0e56cb0cf move widget selection's logic on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   835
96c0e56cb0cf move widget selection's logic on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   836
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   837
class BooleanField(Field):
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   838
    """Use this field to edit booleans (`Boolean` yams type).
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   839
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   840
    Unless explicitly specified, the widget for this field will be a
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   841
    :class:`~cubicweb.web.formwidgets.Radio` with yes/no values. You
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   842
    can change that values by specifing `choices`.
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   843
    """
4368
d752ad901f14 cleanup module namespace but only importing the formwidgets module
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4359
diff changeset
   844
    widget = fw.Radio
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
   845
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   846
    def vocabulary(self, form):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   847
        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
   848
            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
   849
        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
   850
4370
75c610a85949 introduce new _ensure_correctly_typed method on fields, responsible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4369
diff changeset
   851
    def _ensure_correctly_typed(self, form, value):
4393
87e48fe398f1 systematically call bool on BooleanField values
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4392
diff changeset
   852
        return bool(value)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   853
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   854
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
   855
class FloatField(IntField):
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   856
    """Use this field to edit floats (`Float` yams type). This field additionaly
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   857
    support `min` and `max` attributes as the
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   858
    :class:`~cubicweb.web.formfields.IntField`.
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   859
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   860
    Unless explicitly specified, the widget for this field will be a
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   861
    :class:`~cubicweb.web.formwidgets.TextInput`.
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   862
    """
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   863
    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
   864
        formatstr = req.property_value('ui.float-format')
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   865
        if value is None:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   866
            return u''
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   867
        return formatstr % float(value)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   868
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   869
    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
   870
        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
   871
4370
75c610a85949 introduce new _ensure_correctly_typed method on fields, responsible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4369
diff changeset
   872
    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
   873
        if isinstance(value, basestring):
4528
a51f37efc882 quick fix for typed formfield validation: accept empty string, split
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4499
diff changeset
   874
            value = value.strip()
a51f37efc882 quick fix for typed formfield validation: accept empty string, split
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4499
diff changeset
   875
            if not value:
a51f37efc882 quick fix for typed formfield validation: accept empty string, split
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4499
diff changeset
   876
                return None
4225
c49bb6e3d343 fix process_form_values: we should handle value errors and properly raise ProcessFormError
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4181
diff changeset
   877
            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
   878
                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
   879
            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
   880
                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
   881
        return None
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   882
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   883
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   884
class DateField(StringField):
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   885
    """Use this field to edit date (`Date` yams type).
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   886
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   887
    Unless explicitly specified, the widget for this field will be a
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   888
    :class:`~cubicweb.web.formwidgets.JQueryDatePicker`.
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   889
    """
4374
ff3efacfea42 by default use new jquery widgets for Time/Date/DateTime fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4370
diff changeset
   890
    widget = fw.JQueryDatePicker
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   891
    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
   892
    etype = 'Date'
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
   893
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   894
    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
   895
        if value:
4544
d92aa3221c30 split introduced in the wrong place
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4528
diff changeset
   896
            return ustrftime(value, req.property_value(self.format_prop))
4382
6fb02edd05da 3.6 api update, cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4377
diff changeset
   897
        return u''
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   898
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   899
    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
   900
        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
   901
4370
75c610a85949 introduce new _ensure_correctly_typed method on fields, responsible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4369
diff changeset
   902
    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
   903
        if isinstance(value, basestring):
4528
a51f37efc882 quick fix for typed formfield validation: accept empty string, split
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4499
diff changeset
   904
            value = value.strip()
a51f37efc882 quick fix for typed formfield validation: accept empty string, split
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4499
diff changeset
   905
            if not value:
a51f37efc882 quick fix for typed formfield validation: accept empty string, split
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4499
diff changeset
   906
                return None
4225
c49bb6e3d343 fix process_form_values: we should handle value errors and properly raise ProcessFormError
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4181
diff changeset
   907
            try:
4370
75c610a85949 introduce new _ensure_correctly_typed method on fields, responsible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4369
diff changeset
   908
                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
   909
            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
   910
                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
   911
        return value
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   912
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   913
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   914
class DateTimeField(DateField):
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   915
    """Use this field to edit datetime (`Datetime` yams type).
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   916
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   917
    Unless explicitly specified, the widget for this field will be a
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   918
    :class:`~cubicweb.web.formwidgets.JQueryDateTimePicker`.
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   919
    """
4374
ff3efacfea42 by default use new jquery widgets for Time/Date/DateTime fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4370
diff changeset
   920
    widget = fw.JQueryDateTimePicker
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   921
    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
   922
    etype = 'Datetime'
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   923
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   924
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   925
class TimeField(DateField):
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   926
    """Use this field to edit time (`Time` yams type).
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   927
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   928
    Unless explicitly specified, the widget for this field will be a
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   929
    :class:`~cubicweb.web.formwidgets.JQueryTimePicker`.
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   930
    """
4374
ff3efacfea42 by default use new jquery widgets for Time/Date/DateTime fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4370
diff changeset
   931
    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
   932
    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
   933
    etype = 'Time'
1986
96c0e56cb0cf move widget selection's logic on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   934
4161
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   935
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   936
# XXX use cases where we don't actually want a better widget?
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   937
class CompoundField(Field):
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   938
    """This field shouldn't be used directly, it's designed to hold inner
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   939
    fields that should be conceptually groupped together.
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   940
    """
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   941
    def __init__(self, fields, *args, **kwargs):
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   942
        super(CompoundField, self).__init__(*args, **kwargs)
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   943
        self.fields = fields
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   944
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   945
    def subfields(self, form):
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   946
        return self.fields
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   947
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   948
    def actual_fields(self, form):
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   949
        # don't add [self] to actual fields, compound field is usually kinda
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   950
        # virtual, all interesting values are in subfield. Skipping it may avoid
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   951
        # error when processed by the editcontroller : it may be marked as required
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   952
        # while it has no value, hence generating a false error.
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   953
        return list(self.fields)
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   954
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   955
4161
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   956
# 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
   957
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   958
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
   959
    # 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
   960
    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
   961
    if linkedto:
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   962
        buildent = entity._cw.entity_from_eid
5816
5d72fbba92e9 [form] apply patch #933771: format_single_value / vocabulary methods should *always* return actual value as an unicode string
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5762
diff changeset
   963
        return [(buildent(eid).view('combobox'), unicode(eid)) for eid in linkedto]
4161
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   964
    return []
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   965
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   966
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
   967
    # 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
   968
    vocab = []
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   969
    if not required:
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   970
        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
   971
    # 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
   972
    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
   973
        rset = entity.related(rtype, role)
5816
5d72fbba92e9 [form] apply patch #933771: format_single_value / vocabulary methods should *always* return actual value as an unicode string
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5762
diff changeset
   974
        vocab += [(e.view('combobox'), unicode(e.eid)) for e in rset.entities()]
4161
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   975
    return vocab
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
   976
4161
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   977
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
   978
    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
   979
        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
   980
    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
   981
        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
   982
    else:
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   983
        done = None
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   984
    result = []
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   985
    rsetsize = None
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   986
    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
   987
        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
   988
            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
   989
        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
   990
        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
   991
            break
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   992
    return result
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   993
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   994
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
   995
    """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
   996
    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
   997
    """
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   998
    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
   999
        done = set()
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
  1000
    res = []
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
  1001
    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
  1002
        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
  1003
            continue
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
  1004
        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
  1005
        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
  1006
    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
  1007
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
  1008
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
  1009
class RelationField(Field):
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
  1010
    """Use this field to edit a relation of an entity.
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
  1011
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
  1012
    Unless explicitly specified, the widget for this field will be a
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
  1013
    :class:`~cubicweb.web.formwidgets.Select`.
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
  1014
    """
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
  1015
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
  1016
    @staticmethod
1095
6917ebe281e9 test and fix guess_field, some pylint fixes
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
  1017
    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
  1018
        kwargs.setdefault('widget', fw.Select(multiple=card in '*+'))
1738
2cfd50c8a415 should not override potential explicit widget
sylvain.thenault@logilab.fr
parents: 1709
diff changeset
  1019
        return RelationField(**kwargs)
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
  1020
4161
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
  1021
    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
  1022
        """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
  1023
        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
  1024
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
  1025
        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
  1026
        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
  1027
        * 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
  1028
        * 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
  1029
        """
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1108
diff changeset
  1030
        entity = form.edited_entity
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
  1031
        # 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
  1032
        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
  1033
            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
  1034
            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
  1035
                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
  1036
            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
  1037
        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
  1038
            vocab = []
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
  1039
        # 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
  1040
        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
  1041
        try:
4269
da0d254f2eb0 remove deprecation warnings + name error
alex & cheb
parents: 4252
diff changeset
  1042
            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
  1043
            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
  1044
                 % (method, form), DeprecationWarning)
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
  1045
        except AttributeError:
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
  1046
            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
  1047
        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
  1048
            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
  1049
        return vocab
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
  1050
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
  1051
    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
  1052
        #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
  1053
        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
  1054
        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
  1055
            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
  1056
                              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
  1057
            # 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
  1058
            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
  1059
                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
  1060
                    form.root_form.remove_field(field)
4661
87672c718c3c [form] cache field value in form.formvalues using (field, form) key since in some case the same field instance may be shared accross multiple forms, which may share the formvalues dict in case of sub-forms
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4658
diff changeset
  1061
            form.formvalues[(self, form)] = 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
  1062
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
  1063
    def format_single_value(self, req, value):
5816
5d72fbba92e9 [form] apply patch #933771: format_single_value / vocabulary methods should *always* return actual value as an unicode string
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5762
diff changeset
  1064
        return unicode(value)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
  1065
4581
c92ded4dee20 [forms] fix RelationField bug with pending eids (eg inlined forms): we have to override process_form_value to avoid caching when recomputing is needed
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4546
diff changeset
  1066
    def process_form_value(self, form):
c92ded4dee20 [forms] fix RelationField bug with pending eids (eg inlined forms): we have to override process_form_value to avoid caching when recomputing is needed
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4546
diff changeset
  1067
        """process posted form and return correctly typed value"""
c92ded4dee20 [forms] fix RelationField bug with pending eids (eg inlined forms): we have to override process_form_value to avoid caching when recomputing is needed
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4546
diff changeset
  1068
        try:
4661
87672c718c3c [form] cache field value in form.formvalues using (field, form) key since in some case the same field instance may be shared accross multiple forms, which may share the formvalues dict in case of sub-forms
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4658
diff changeset
  1069
            return form.formvalues[(self, form)]
4581
c92ded4dee20 [forms] fix RelationField bug with pending eids (eg inlined forms): we have to override process_form_value to avoid caching when recomputing is needed
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4546
diff changeset
  1070
        except KeyError:
c92ded4dee20 [forms] fix RelationField bug with pending eids (eg inlined forms): we have to override process_form_value to avoid caching when recomputing is needed
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4546
diff changeset
  1071
            value = self._process_form_value(form)
c92ded4dee20 [forms] fix RelationField bug with pending eids (eg inlined forms): we have to override process_form_value to avoid caching when recomputing is needed
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4546
diff changeset
  1072
            # if value is None, there are some remaining pending fields, we'll
c92ded4dee20 [forms] fix RelationField bug with pending eids (eg inlined forms): we have to override process_form_value to avoid caching when recomputing is needed
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4546
diff changeset
  1073
            # have to recompute this later -> don't cache in formvalues
c92ded4dee20 [forms] fix RelationField bug with pending eids (eg inlined forms): we have to override process_form_value to avoid caching when recomputing is needed
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4546
diff changeset
  1074
            if value is not None:
4661
87672c718c3c [form] cache field value in form.formvalues using (field, form) key since in some case the same field instance may be shared accross multiple forms, which may share the formvalues dict in case of sub-forms
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4658
diff changeset
  1075
                form.formvalues[(self, form)] = value
4581
c92ded4dee20 [forms] fix RelationField bug with pending eids (eg inlined forms): we have to override process_form_value to avoid caching when recomputing is needed
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4546
diff changeset
  1076
            return value
c92ded4dee20 [forms] fix RelationField bug with pending eids (eg inlined forms): we have to override process_form_value to avoid caching when recomputing is needed
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4546
diff changeset
  1077
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
  1078
    def _process_form_value(self, form):
4110
8728d8c95985 [mq]: fix_for_forms
Arthur Lutz <arthur.lutz@logilab.fr>
parents: 4101
diff changeset
  1079
        """process posted form and return correctly typed value"""
8728d8c95985 [mq]: fix_for_forms
Arthur Lutz <arthur.lutz@logilab.fr>
parents: 4101
diff changeset
  1080
        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
  1081
        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
  1082
        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
  1083
            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
  1084
        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
  1085
            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
  1086
        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
  1087
        for eid in values:
4227
39f01be4a6c5 should skip INTERNAL_FIELD_VALUE
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4226
diff changeset
  1088
            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
  1089
                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
  1090
            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
  1091
            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
  1092
                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
  1093
                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
  1094
            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
  1095
        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
  1096
2523
1d245fbbeb90 some new field/widgets classes: CompoundField, IntervalWidget, HorizontalLayoutWidget
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2522
diff changeset
  1097
5057
d1bd50ae0edd [form] consider autoform_field_kwargs for meta fields; allow required customization
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5038
diff changeset
  1098
_AFF_KWARGS = uicfg.autoform_field_kwargs
d1bd50ae0edd [form] consider autoform_field_kwargs for meta fields; allow required customization
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5038
diff changeset
  1099
5712
e136d392bd71 [form] refactor meta-attributes handling: hide them by default using uicfg.afs instead of returning None (or not, according to skip_meta_attr flag argument) in guess_field
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5697
diff changeset
  1100
def guess_field(eschema, rschema, role='subject', **kwargs):
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
  1101
    """This function return the most adapted field to edit the given relation
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
  1102
    (`rschema`) where the given entity type (`eschema`) is the subject or object
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
  1103
    (`role`).
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
  1104
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
  1105
    The field is initialized according to information found in the schema,
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
  1106
    though any value can be explicitly specified using `kwargs`.
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
  1107
    """
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
  1108
    fieldclass = None
4014
24f7d7eb4c23 yams api update
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3890
diff changeset
  1109
    rdef = eschema.rdef(rschema, role)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
  1110
    if role == 'subject':
4014
24f7d7eb4c23 yams api update
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3890
diff changeset
  1111
        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
  1112
        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
  1113
            if rdef.get('internationalizable'):
2095
897732d3ee5a avoid overriding specified values when guessing field
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2091
diff changeset
  1114
                kwargs.setdefault('internationalizable', True)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
  1115
    else:
4014
24f7d7eb4c23 yams api update
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3890
diff changeset
  1116
        targetschema = rdef.subject
4044
3876c894e018 card referenced later
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4023
diff changeset
  1117
    card = rdef.role_cardinality(role)
1095
6917ebe281e9 test and fix guess_field, some pylint fixes
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
  1118
    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
  1119
    kwargs['role'] = role
5057
d1bd50ae0edd [form] consider autoform_field_kwargs for meta fields; allow required customization
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5038
diff changeset
  1120
    kwargs['eidparam'] = True
d1bd50ae0edd [form] consider autoform_field_kwargs for meta fields; allow required customization
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5038
diff changeset
  1121
    kwargs.setdefault('required', card in '1+')
3308
88f5f89d8d1b fix generated label for object relation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3299
diff changeset
  1122
    if role == 'object':
3574
f179ccbd13e6 [forms] fix generated label for fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3563
diff changeset
  1123
        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
  1124
    else:
3574
f179ccbd13e6 [forms] fix generated label for fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3563
diff changeset
  1125
        kwargs.setdefault('label', (eschema.type, rschema.type))
4014
24f7d7eb4c23 yams api update
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3890
diff changeset
  1126
    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
  1127
    if rschema.final:
1095
6917ebe281e9 test and fix guess_field, some pylint fixes
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
  1128
        fieldclass = FIELDS[targetschema]
6917ebe281e9 test and fix guess_field, some pylint fixes
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
  1129
        if fieldclass is StringField:
1104
58f27c3c0167 more guess_field tests and fixes
sylvain.thenault@logilab.fr
parents: 1101
diff changeset
  1130
            if eschema.has_metadata(rschema, 'format'):
58f27c3c0167 more guess_field tests and fixes
sylvain.thenault@logilab.fr
parents: 1101
diff changeset
  1131
                # use RichTextField instead of StringField if the attribute has
58f27c3c0167 more guess_field tests and fixes
sylvain.thenault@logilab.fr
parents: 1101
diff changeset
  1132
                # a "format" metadata. But getting information from constraints
58f27c3c0167 more guess_field tests and fixes
sylvain.thenault@logilab.fr
parents: 1101
diff changeset
  1133
                # may be useful anyway...
4014
24f7d7eb4c23 yams api update
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3890
diff changeset
  1134
                for cstr in rdef.constraints:
1104
58f27c3c0167 more guess_field tests and fixes
sylvain.thenault@logilab.fr
parents: 1101
diff changeset
  1135
                    if isinstance(cstr, StaticVocabularyConstraint):
58f27c3c0167 more guess_field tests and fixes
sylvain.thenault@logilab.fr
parents: 1101
diff changeset
  1136
                        raise Exception('rich text field with static vocabulary')
58f27c3c0167 more guess_field tests and fixes
sylvain.thenault@logilab.fr
parents: 1101
diff changeset
  1137
                return RichTextField(**kwargs)
1574
0c6dbb774f54 drop text field usage
sylvain.thenault@logilab.fr
parents: 1573
diff changeset
  1138
            # init StringField parameters according to constraints
4014
24f7d7eb4c23 yams api update
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3890
diff changeset
  1139
            for cstr in rdef.constraints:
1574
0c6dbb774f54 drop text field usage
sylvain.thenault@logilab.fr
parents: 1573
diff changeset
  1140
                if isinstance(cstr, StaticVocabularyConstraint):
1577
25b46db3cb81 should set field's choices
sylvain.thenault@logilab.fr
parents: 1574
diff changeset
  1141
                    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
  1142
                    break
4014
24f7d7eb4c23 yams api update
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3890
diff changeset
  1143
            for cstr in rdef.constraints:
1574
0c6dbb774f54 drop text field usage
sylvain.thenault@logilab.fr
parents: 1573
diff changeset
  1144
                if isinstance(cstr, SizeConstraint) and cstr.max is not None:
0c6dbb774f54 drop text field usage
sylvain.thenault@logilab.fr
parents: 1573
diff changeset
  1145
                    kwargs['max_length'] = cstr.max
0c6dbb774f54 drop text field usage
sylvain.thenault@logilab.fr
parents: 1573
diff changeset
  1146
            return StringField(**kwargs)
1104
58f27c3c0167 more guess_field tests and fixes
sylvain.thenault@logilab.fr
parents: 1101
diff changeset
  1147
        if fieldclass is FileField:
4160
3fbdeef9a610 cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4159
diff changeset
  1148
            for metadata in KNOWN_METAATTRIBUTES:
1104
58f27c3c0167 more guess_field tests and fixes
sylvain.thenault@logilab.fr
parents: 1101
diff changeset
  1149
                metaschema = eschema.has_metadata(rschema, metadata)
58f27c3c0167 more guess_field tests and fixes
sylvain.thenault@logilab.fr
parents: 1101
diff changeset
  1150
                if metaschema is not None:
5057
d1bd50ae0edd [form] consider autoform_field_kwargs for meta fields; allow required customization
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5038
diff changeset
  1151
                    metakwargs = _AFF_KWARGS.etype_get(eschema, metaschema, 'subject')
1453
a9841184be7c guess_field now takes an entity schema as first argument, not an entity class
sylvain.thenault@logilab.fr
parents: 1437
diff changeset
  1152
                    kwargs['%s_field' % metadata] = guess_field(eschema, metaschema,
5057
d1bd50ae0edd [form] consider autoform_field_kwargs for meta fields; allow required customization
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5038
diff changeset
  1153
                                                                **metakwargs)
1095
6917ebe281e9 test and fix guess_field, some pylint fixes
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
  1154
        return fieldclass(**kwargs)
6917ebe281e9 test and fix guess_field, some pylint fixes
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
  1155
    return RelationField.fromcardinality(card, **kwargs)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
  1156
1986
96c0e56cb0cf move widget selection's logic on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
  1157
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
  1158
FIELDS = {
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
  1159
    'Boolean':  BooleanField,
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
  1160
    'Bytes':    FileField,
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
  1161
    'Date':     DateField,
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
  1162
    'Datetime': DateTimeField,
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
  1163
    'Int':      IntField,
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
  1164
    'Float':    FloatField,
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
  1165
    '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
  1166
    'Password': PasswordField,
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
  1167
    'String' :  StringField,
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
  1168
    'Time':     TimeField,
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
  1169
    }