web/formfields.py
author Sylvain Thénault <sylvain.thenault@logilab.fr>
Thu, 17 Jun 2010 15:15:52 +0200
changeset 5774 0d792bceb25d
parent 5762 730d458ec1bf
child 5816 5d72fbba92e9
permissions -rw-r--r--
backport stable
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):
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
   364
        """return vocabulary for this field. This method will be called by
4161
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   365
        widgets which requires a vocabulary.
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   366
        """
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   367
        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
   368
        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
   369
            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
   370
                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
   371
                    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
   372
                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
   373
                    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
   374
            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
   375
                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
   376
                    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
   377
                    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
   378
                         '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
   379
                         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
   380
                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
   381
                    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
   382
                         '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
   383
                         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
   384
                    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
   385
        else:
4170
c325c62cec8e crecord introduced junk...
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4168
diff changeset
   386
            vocab = self.choices
c325c62cec8e crecord introduced junk...
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4168
diff changeset
   387
        if vocab and not isinstance(vocab[0], (list, tuple)):
c325c62cec8e crecord introduced junk...
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4168
diff changeset
   388
            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
   389
        if self.internationalizable:
3790
34fdb8fb49d1 [B] web: weird display with internationalizable (Closes: #503071)
Julien Jehannet <julien.jehannet@logilab.fr>
parents: 3689
diff changeset
   390
            # the short-cirtcuit 'and' boolean operator is used here to permit
34fdb8fb49d1 [B] web: weird display with internationalizable (Closes: #503071)
Julien Jehannet <julien.jehannet@logilab.fr>
parents: 3689
diff changeset
   391
            # a valid empty string in vocabulary without attempting to translate
34fdb8fb49d1 [B] web: weird display with internationalizable (Closes: #503071)
Julien Jehannet <julien.jehannet@logilab.fr>
parents: 3689
diff changeset
   392
            # it by gettext (which can lead to weird strings display)
3890
d7a270f50f54 backport stable branch (one more time painfully)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3720 3874
diff changeset
   393
            vocab = [(label and form._cw._(label), value) for label, value in vocab]
1265
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
   394
        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
   395
            vocab = vocab_sort(vocab)
1265
e5cdd5c0dce3 handle sort/internationalizable on Field base class + fix guess_field to deal with internationalizable and default values
sylvain.thenault@logilab.fr
parents: 1181
diff changeset
   396
        return vocab
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
   397
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
   398
    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
   399
        """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
   400
        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
   401
            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
   402
            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
   403
                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
   404
                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
   405
        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
   406
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
   407
    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
   408
        """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
   409
        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
   410
            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
   411
            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
   412
                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
   413
                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
   414
        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
   415
1307
8c3336c5ddba new form_init callback
sylvain.thenault@logilab.fr
parents: 1306
diff changeset
   416
    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
   417
        """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
   418
        initialization requiring the form instance. Do nothing by default.
1307
8c3336c5ddba new form_init callback
sylvain.thenault@logilab.fr
parents: 1306
diff changeset
   419
        """
8c3336c5ddba new form_init callback
sylvain.thenault@logilab.fr
parents: 1306
diff changeset
   420
        pass
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
   421
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
   422
    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
   423
        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
   424
            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
   425
                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
   426
        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
   427
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
   428
    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
   429
        # 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
   430
        # 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
   431
        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
   432
            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
   433
        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
   434
            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
   435
                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
   436
            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
   437
                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
   438
                                         '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
   439
        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
   440
            # 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
   441
            # 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
   442
            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
   443
        # 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
   444
        # 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
   445
        #     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
   446
        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
   447
            # 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
   448
            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
   449
        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
   450
            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
   451
        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
   452
            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
   453
        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
   454
            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
   455
        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
   456
            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
   457
        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
   458
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
   459
    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
   460
        """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
   461
        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
   462
            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
   463
        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
   464
            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
   465
            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
   466
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
   467
    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
   468
        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
   469
        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
   470
        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
   471
75c610a85949 introduce new _ensure_correctly_typed method on fields, responsible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4369
diff changeset
   472
    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
   473
        """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
   474
        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
   475
        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
   476
        """
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
   477
        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
   478
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
    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
   480
        """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
   481
        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
   482
        """
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
   483
        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
   484
            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
   485
                try:
5038
90493551b1eb [form] fix validation error handling
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5030
diff changeset
   486
                    value = field.process_form_value(form)
90493551b1eb [form] fix validation error handling
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5030
diff changeset
   487
                    if value is None and field.required:
90493551b1eb [form] fix validation error handling
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5030
diff changeset
   488
                        raise ProcessFormError(form._cw._("required field"))
90493551b1eb [form] fix validation error handling
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5030
diff changeset
   489
                    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
   490
                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
   491
                    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
   492
            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
   493
                # 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
   494
                # 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
   495
                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
   496
                    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
   497
1986
96c0e56cb0cf move widget selection's logic on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   498
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   499
class StringField(Field):
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   500
    """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
   501
    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
   502
    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
   503
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   504
    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
   505
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   506
    * :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
   507
      using `choices` attribute
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   508
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   509
    * :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
   510
      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
   511
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   512
    * :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
   513
    """
4368
d752ad901f14 cleanup module namespace but only importing the formwidgets module
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4359
diff changeset
   514
    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
   515
    size = 45
1986
96c0e56cb0cf move widget selection's logic on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   516
4168
9d83f9c80c1c nicer StringField __init__
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4166
diff changeset
   517
    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
   518
        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
   519
        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
   520
96c0e56cb0cf move widget selection's logic on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   521
    def init_widget(self, widget):
96c0e56cb0cf move widget selection's logic on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   522
        if widget is None:
96c0e56cb0cf move widget selection's logic on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   523
            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
   524
                widget = fw.Select()
1986
96c0e56cb0cf move widget selection's logic on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   525
            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
   526
                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
   527
1986
96c0e56cb0cf move widget selection's logic on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   528
        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
   529
        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
   530
            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
   531
        elif isinstance(self.widget, fw.TextInput):
2360
1d43aa551ba9 [formwidgets,formfields] hum, this way
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 2356
diff changeset
   532
            self.init_text_input(self.widget)
1d43aa551ba9 [formwidgets,formfields] hum, this way
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 2356
diff changeset
   533
1d43aa551ba9 [formwidgets,formfields] hum, this way
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 2356
diff changeset
   534
    def init_text_input(self, widget):
1d43aa551ba9 [formwidgets,formfields] hum, this way
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 2356
diff changeset
   535
        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
   536
            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
   537
            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
   538
d34589d35daa drop TextField, this is simply a StringField with a text area widget
sylvain.thenault@logilab.fr
parents: 1564
diff changeset
   539
    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
   540
        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
   541
            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
   542
            widget.attrs.setdefault('rows', 5)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   543
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   544
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
   545
class PasswordField(StringField):
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   546
    """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
   547
    string).
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   548
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   549
    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
   550
    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
   551
    """
4368
d752ad901f14 cleanup module namespace but only importing the formwidgets module
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4359
diff changeset
   552
    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
   553
    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
   554
        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
   555
            # 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
   556
            # 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
   557
            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
   558
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
   559
    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
   560
        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
   561
            # 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
   562
            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
   563
                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
   564
            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
   565
        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
   566
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   567
1573
d34589d35daa drop TextField, this is simply a StringField with a text area widget
sylvain.thenault@logilab.fr
parents: 1564
diff changeset
   568
class RichTextField(StringField):
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   569
    """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
   570
    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
   571
    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
   572
    one will be automaticall generated.
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   573
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   574
    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
   575
    :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
   576
    :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
   577
    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
   578
    """
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   579
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   580
    widget = None
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   581
    def __init__(self, format_field=None, **kwargs):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   582
        super(RichTextField, self).__init__(**kwargs)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   583
        self.format_field = format_field
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   584
2348
acf4b6a59558 [formwidgets] ensure textarea for richstring has not ridicuously small size (close #344547)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 2347
diff changeset
   585
    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
   586
        pass
acf4b6a59558 [formwidgets] ensure textarea for richstring has not ridicuously small size (close #344547)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 2347
diff changeset
   587
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   588
    def get_widget(self, form):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   589
        if self.widget is None:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   590
            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
   591
                return fw.FCKEditor()
d752ad901f14 cleanup module namespace but only importing the formwidgets module
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4359
diff changeset
   592
            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
   593
            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
   594
            return widget
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   595
        return self.widget
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   596
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   597
    def get_format_field(self, form):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   598
        if self.format_field:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   599
            return self.format_field
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   600
        # 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
   601
        # context dictionnary
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3388
diff changeset
   602
        req = form._cw
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   603
        try:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   604
            return req.data[self]
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   605
        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
   606
            fkwargs = {'eidparam': self.eidparam, 'role': self.role}
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   607
            if self.use_fckeditor(form):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   608
                # 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
   609
                # 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
   610
                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
   611
                fkwargs['value'] = 'text/html'
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   612
            else:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   613
                # 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
   614
                fkwargs['widget'] = fw.Select()
1095
6917ebe281e9 test and fix guess_field, some pylint fixes
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
   615
                fcstr = FormatConstraint()
3347
428f95118556 fix vocab param to avoid deprecation warning
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3337
diff changeset
   616
                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
   617
                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
   618
                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
   619
            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
   620
            field = StringField(name=self.name + '_format', **fkwargs)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   621
            req.data[self] = field
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   622
            return field
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
   623
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   624
    def actual_fields(self, form):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   625
        yield self
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   626
        format_field = self.get_format_field(form)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   627
        if format_field:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   628
            yield format_field
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
   629
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   630
    def use_fckeditor(self, form):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   631
        """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
   632
        `attr`, according to user preferences
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   633
        """
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3388
diff changeset
   634
        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
   635
            return self.format(form) == 'text/html'
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   636
        return False
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   637
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   638
    def render(self, form, renderer):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   639
        format_field = self.get_format_field(form)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   640
        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
   641
            # 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
   642
            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
   643
                format_field.widget.attrs['style'] = 'display: block'
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   644
            result = format_field.render(form, renderer)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   645
        else:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   646
            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
   647
        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
   648
1417
06af20e663f2 remove spaces
sylvain.thenault@logilab.fr
parents: 1393
diff changeset
   649
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   650
class FileField(StringField):
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   651
    """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
   652
    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
   653
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   654
    * `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
   655
    * `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
   656
    * `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
   657
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   658
    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
   659
    :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
   660
    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
   661
    """
4368
d752ad901f14 cleanup module namespace but only importing the formwidgets module
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4359
diff changeset
   662
    widget = fw.FileInput
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   663
    needs_multipart = True
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
   664
3496
35a67ac6efe8 support name metadata on guess_field; add name_field to FileField
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3347
diff changeset
   665
    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
   666
                 **kwargs):
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   667
        super(FileField, self).__init__(**kwargs)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   668
        self.format_field = format_field
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   669
        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
   670
        self.name_field = name_field
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
   671
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   672
    def actual_fields(self, form):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   673
        yield self
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   674
        if self.format_field:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   675
            yield self.format_field
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   676
        if self.encoding_field:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   677
            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
   678
        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
   679
            yield self.name_field
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   680
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
   681
    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
   682
        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
   683
            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
   684
                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
   685
                    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
   686
                # 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
   687
                # 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
   688
                # * 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
   689
                # * 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
   690
                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
   691
            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
   692
        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
   693
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   694
    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
   695
        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
   696
        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
   697
            divid = '%s-advanced' % self.input_name(form)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   698
            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
   699
                        (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
   700
                         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
   701
                         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
   702
                         form._cw._('show advanced fields')))
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   703
            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
   704
            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
   705
                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
   706
            if self.format_field:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   707
                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
   708
            if self.encoding_field:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   709
                wdgs.append(self.render_subfield(form, self.encoding_field, renderer))
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
   710
            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
   711
        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
   712
            # 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
   713
            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
   714
            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
   715
                                   type=u'checkbox'))
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3388
diff changeset
   716
            wdgs.append(form._cw._('detach attached file'))
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   717
        return u'\n'.join(wdgs)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   718
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   719
    def render_subfield(self, form, field, renderer):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   720
        return (renderer.render_label(form, field)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   721
                + field.render(form, renderer)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   722
                + renderer.render_help(form, field)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   723
                + u'<br/>')
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   724
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
   725
    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
   726
        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
   727
        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
   728
            # 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
   729
            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
   730
        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
   731
            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
   732
        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
   733
            # 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
   734
            # 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
   735
            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
   736
        # 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
   737
        try:
96fd339f7917 Handle new way of reporting unmodified FileFields
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 5426
diff changeset
   738
            filename, stream = value
96fd339f7917 Handle new way of reporting unmodified FileFields
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 5426
diff changeset
   739
        except ValueError:
96fd339f7917 Handle new way of reporting unmodified FileFields
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 5426
diff changeset
   740
            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
   741
        # 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
   742
        value = Binary(stream.read())
4273
183cd0df6f1a fix dumb name error
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4272
diff changeset
   743
        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
   744
            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
   745
        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
   746
            # 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
   747
            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
   748
        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
   749
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
   750
5367
4176a50c81c9 [form] small api cleanup and refactoring before documenting the form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5220
diff changeset
   751
# XXX turn into a widget
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   752
class EditableFileField(FileField):
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   753
    """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
   754
    :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
   755
    actually contains some text.
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   756
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   757
    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
   758
    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
   759
    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
   760
    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
   761
    """
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   762
    editable_formats = ('text/plain', 'text/html', 'text/rest')
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
   763
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   764
    def render(self, form, renderer):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   765
        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
   766
        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
   767
            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
   768
            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
   769
                encoding = self.encoding(form)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   770
                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
   771
                    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
   772
                except UnicodeError:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   773
                    pass
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   774
                else:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   775
                    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
   776
                        msg = form._cw._(
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   777
                            '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
   778
                            ', 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
   779
                            '"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
   780
                            'with the widget below.')
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   781
                    else:
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3388
diff changeset
   782
                        msg = form._cw._(
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   783
                            '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
   784
                            ', 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
   785
                    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
   786
                    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
   787
                    # XXX restore form context?
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   788
        return '\n'.join(wdgs)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   789
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
   790
    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
   791
        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
   792
        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
   793
            # 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
   794
            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
   795
        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
   796
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
   797
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   798
class IntField(Field):
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   799
    """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
   800
    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
   801
    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
   802
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   803
    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
   804
    :class:`~cubicweb.web.formwidgets.TextInput`.
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   805
    """
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   806
    def __init__(self, min=None, max=None, **kwargs):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   807
        super(IntField, self).__init__(**kwargs)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   808
        self.min = min
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   809
        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
   810
        if isinstance(self.widget, fw.TextInput):
1758
d46f59e5efd3 some widget adjustments
sylvain.thenault@logilab.fr
parents: 1738
diff changeset
   811
            self.widget.attrs.setdefault('size', 5)
d46f59e5efd3 some widget adjustments
sylvain.thenault@logilab.fr
parents: 1738
diff changeset
   812
            self.widget.attrs.setdefault('maxlength', 15)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   813
4370
75c610a85949 introduce new _ensure_correctly_typed method on fields, responsible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4369
diff changeset
   814
    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
   815
        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
   816
            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
   817
            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
   818
                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
   819
            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
   820
                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
   821
            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
   822
                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
   823
        return value
1986
96c0e56cb0cf move widget selection's logic on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   824
96c0e56cb0cf move widget selection's logic on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   825
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   826
class BooleanField(Field):
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   827
    """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
   828
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   829
    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
   830
    :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
   831
    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
   832
    """
4368
d752ad901f14 cleanup module namespace but only importing the formwidgets module
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4359
diff changeset
   833
    widget = fw.Radio
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
   834
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   835
    def vocabulary(self, form):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   836
        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
   837
            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
   838
        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
   839
4370
75c610a85949 introduce new _ensure_correctly_typed method on fields, responsible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4369
diff changeset
   840
    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
   841
        return bool(value)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   842
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   843
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
   844
class FloatField(IntField):
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   845
    """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
   846
    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
   847
    :class:`~cubicweb.web.formfields.IntField`.
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   848
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   849
    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
   850
    :class:`~cubicweb.web.formwidgets.TextInput`.
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   851
    """
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   852
    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
   853
        formatstr = req.property_value('ui.float-format')
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   854
        if value is None:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   855
            return u''
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   856
        return formatstr % float(value)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   857
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   858
    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
   859
        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
   860
4370
75c610a85949 introduce new _ensure_correctly_typed method on fields, responsible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4369
diff changeset
   861
    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
   862
        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
   863
            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
   864
            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
   865
                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
   866
            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
   867
                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
   868
            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
   869
                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
   870
        return None
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   871
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   872
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   873
class DateField(StringField):
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   874
    """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
   875
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   876
    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
   877
    :class:`~cubicweb.web.formwidgets.JQueryDatePicker`.
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   878
    """
4374
ff3efacfea42 by default use new jquery widgets for Time/Date/DateTime fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4370
diff changeset
   879
    widget = fw.JQueryDatePicker
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   880
    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
   881
    etype = 'Date'
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
   882
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   883
    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
   884
        if value:
4544
d92aa3221c30 split introduced in the wrong place
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4528
diff changeset
   885
            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
   886
        return u''
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   887
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   888
    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
   889
        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
   890
4370
75c610a85949 introduce new _ensure_correctly_typed method on fields, responsible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4369
diff changeset
   891
    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
   892
        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
   893
            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
   894
            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
   895
                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
   896
            try:
4370
75c610a85949 introduce new _ensure_correctly_typed method on fields, responsible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4369
diff changeset
   897
                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
   898
            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
   899
                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
   900
        return value
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   901
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   902
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   903
class DateTimeField(DateField):
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   904
    """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
   905
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   906
    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
   907
    :class:`~cubicweb.web.formwidgets.JQueryDateTimePicker`.
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   908
    """
4374
ff3efacfea42 by default use new jquery widgets for Time/Date/DateTime fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4370
diff changeset
   909
    widget = fw.JQueryDateTimePicker
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   910
    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
   911
    etype = 'Datetime'
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 TimeField(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 time (`Time` 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.JQueryTimePicker`.
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.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
   921
    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
   922
    etype = 'Time'
1986
96c0e56cb0cf move widget selection's logic on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   923
4161
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   924
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   925
# 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
   926
class CompoundField(Field):
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   927
    """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
   928
    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
   929
    """
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   930
    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
   931
        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
   932
        self.fields = fields
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   933
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   934
    def subfields(self, form):
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   935
        return self.fields
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   936
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   937
    def actual_fields(self, form):
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   938
        # 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
   939
        # 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
   940
        # 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
   941
        # 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
   942
        return list(self.fields)
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   943
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   944
4161
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   945
# 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
   946
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   947
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
   948
    # 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
   949
    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
   950
    if linkedto:
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   951
        buildent = entity._cw.entity_from_eid
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   952
        return [(buildent(eid).view('combobox'), eid) for eid in linkedto]
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   953
    return []
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   954
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   955
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
   956
    # 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
   957
    vocab = []
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   958
    if not required:
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   959
        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
   960
    # 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
   961
    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
   962
        rset = entity.related(rtype, role)
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   963
        vocab += [(e.view('combobox'), e.eid) for e in rset.entities()]
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   964
    return vocab
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
   965
4161
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   966
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
   967
    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
   968
        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
   969
    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
   970
        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
   971
    else:
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   972
        done = None
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   973
    result = []
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   974
    rsetsize = None
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   975
    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
   976
        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
   977
            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
   978
        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
   979
        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
   980
            break
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   981
    return result
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   982
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   983
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
   984
    """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
   985
    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
   986
    """
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   987
    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
   988
        done = set()
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   989
    res = []
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   990
    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
   991
        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
   992
            continue
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   993
        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
   994
        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
   995
    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
   996
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
   997
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   998
class RelationField(Field):
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   999
    """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
  1000
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
  1001
    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
  1002
    :class:`~cubicweb.web.formwidgets.Select`.
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
  1003
    """
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
  1004
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
  1005
    @staticmethod
1095
6917ebe281e9 test and fix guess_field, some pylint fixes
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
  1006
    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
  1007
        kwargs.setdefault('widget', fw.Select(multiple=card in '*+'))
1738
2cfd50c8a415 should not override potential explicit widget
sylvain.thenault@logilab.fr
parents: 1709
diff changeset
  1008
        return RelationField(**kwargs)
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
  1009
4161
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
  1010
    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
  1011
        """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
  1012
        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
  1013
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
  1014
        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
  1015
        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
  1016
        * 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
  1017
        * 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
  1018
        """
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1108
diff changeset
  1019
        entity = form.edited_entity
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
  1020
        # 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
  1021
        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
  1022
            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
  1023
            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
  1024
                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
  1025
            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
  1026
        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
  1027
            vocab = []
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
  1028
        # 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
  1029
        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
  1030
        try:
4269
da0d254f2eb0 remove deprecation warnings + name error
alex & cheb
parents: 4252
diff changeset
  1031
            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
  1032
            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
  1033
                 % (method, form), DeprecationWarning)
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
  1034
        except AttributeError:
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
  1035
            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
  1036
        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
  1037
            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
  1038
        return vocab
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
  1039
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
  1040
    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
  1041
        #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
  1042
        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
  1043
        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
  1044
            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
  1045
                              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
  1046
            # 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
  1047
            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
  1048
                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
  1049
                    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
  1050
            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
  1051
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
  1052
    def format_single_value(self, req, value):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
  1053
        return value
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
  1054
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
  1055
    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
  1056
        """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
  1057
        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
  1058
            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
  1059
        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
  1060
            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
  1061
            # 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
  1062
            # 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
  1063
            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
  1064
                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
  1065
            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
  1066
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
  1067
    def _process_form_value(self, form):
4110
8728d8c95985 [mq]: fix_for_forms
Arthur Lutz <arthur.lutz@logilab.fr>
parents: 4101
diff changeset
  1068
        """process posted form and return correctly typed value"""
8728d8c95985 [mq]: fix_for_forms
Arthur Lutz <arthur.lutz@logilab.fr>
parents: 4101
diff changeset
  1069
        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
  1070
        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
  1071
        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
  1072
            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
  1073
        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
  1074
            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
  1075
        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
  1076
        for eid in values:
4227
39f01be4a6c5 should skip INTERNAL_FIELD_VALUE
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4226
diff changeset
  1077
            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
  1078
                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
  1079
            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
  1080
            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
  1081
                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
  1082
                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
  1083
            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
  1084
        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
  1085
2523
1d245fbbeb90 some new field/widgets classes: CompoundField, IntervalWidget, HorizontalLayoutWidget
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2522
diff changeset
  1086
5057
d1bd50ae0edd [form] consider autoform_field_kwargs for meta fields; allow required customization
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5038
diff changeset
  1087
_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
  1088
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
  1089
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
  1090
    """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
  1091
    (`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
  1092
    (`role`).
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
  1093
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
  1094
    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
  1095
    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
  1096
    """
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
  1097
    fieldclass = None
4014
24f7d7eb4c23 yams api update
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3890
diff changeset
  1098
    rdef = eschema.rdef(rschema, role)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
  1099
    if role == 'subject':
4014
24f7d7eb4c23 yams api update
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3890
diff changeset
  1100
        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
  1101
        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
  1102
            if rdef.get('internationalizable'):
2095
897732d3ee5a avoid overriding specified values when guessing field
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2091
diff changeset
  1103
                kwargs.setdefault('internationalizable', True)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
  1104
    else:
4014
24f7d7eb4c23 yams api update
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3890
diff changeset
  1105
        targetschema = rdef.subject
4044
3876c894e018 card referenced later
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4023
diff changeset
  1106
    card = rdef.role_cardinality(role)
1095
6917ebe281e9 test and fix guess_field, some pylint fixes
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
  1107
    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
  1108
    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
  1109
    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
  1110
    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
  1111
    if role == 'object':
3574
f179ccbd13e6 [forms] fix generated label for fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3563
diff changeset
  1112
        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
  1113
    else:
3574
f179ccbd13e6 [forms] fix generated label for fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3563
diff changeset
  1114
        kwargs.setdefault('label', (eschema.type, rschema.type))
4014
24f7d7eb4c23 yams api update
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3890
diff changeset
  1115
    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
  1116
    if rschema.final:
1095
6917ebe281e9 test and fix guess_field, some pylint fixes
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
  1117
        fieldclass = FIELDS[targetschema]
6917ebe281e9 test and fix guess_field, some pylint fixes
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
  1118
        if fieldclass is StringField:
1104
58f27c3c0167 more guess_field tests and fixes
sylvain.thenault@logilab.fr
parents: 1101
diff changeset
  1119
            if eschema.has_metadata(rschema, 'format'):
58f27c3c0167 more guess_field tests and fixes
sylvain.thenault@logilab.fr
parents: 1101
diff changeset
  1120
                # use RichTextField instead of StringField if the attribute has
58f27c3c0167 more guess_field tests and fixes
sylvain.thenault@logilab.fr
parents: 1101
diff changeset
  1121
                # a "format" metadata. But getting information from constraints
58f27c3c0167 more guess_field tests and fixes
sylvain.thenault@logilab.fr
parents: 1101
diff changeset
  1122
                # may be useful anyway...
4014
24f7d7eb4c23 yams api update
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3890
diff changeset
  1123
                for cstr in rdef.constraints:
1104
58f27c3c0167 more guess_field tests and fixes
sylvain.thenault@logilab.fr
parents: 1101
diff changeset
  1124
                    if isinstance(cstr, StaticVocabularyConstraint):
58f27c3c0167 more guess_field tests and fixes
sylvain.thenault@logilab.fr
parents: 1101
diff changeset
  1125
                        raise Exception('rich text field with static vocabulary')
58f27c3c0167 more guess_field tests and fixes
sylvain.thenault@logilab.fr
parents: 1101
diff changeset
  1126
                return RichTextField(**kwargs)
1574
0c6dbb774f54 drop text field usage
sylvain.thenault@logilab.fr
parents: 1573
diff changeset
  1127
            # init StringField parameters according to constraints
4014
24f7d7eb4c23 yams api update
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3890
diff changeset
  1128
            for cstr in rdef.constraints:
1574
0c6dbb774f54 drop text field usage
sylvain.thenault@logilab.fr
parents: 1573
diff changeset
  1129
                if isinstance(cstr, StaticVocabularyConstraint):
1577
25b46db3cb81 should set field's choices
sylvain.thenault@logilab.fr
parents: 1574
diff changeset
  1130
                    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
  1131
                    break
4014
24f7d7eb4c23 yams api update
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3890
diff changeset
  1132
            for cstr in rdef.constraints:
1574
0c6dbb774f54 drop text field usage
sylvain.thenault@logilab.fr
parents: 1573
diff changeset
  1133
                if isinstance(cstr, SizeConstraint) and cstr.max is not None:
0c6dbb774f54 drop text field usage
sylvain.thenault@logilab.fr
parents: 1573
diff changeset
  1134
                    kwargs['max_length'] = cstr.max
0c6dbb774f54 drop text field usage
sylvain.thenault@logilab.fr
parents: 1573
diff changeset
  1135
            return StringField(**kwargs)
1104
58f27c3c0167 more guess_field tests and fixes
sylvain.thenault@logilab.fr
parents: 1101
diff changeset
  1136
        if fieldclass is FileField:
4160
3fbdeef9a610 cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4159
diff changeset
  1137
            for metadata in KNOWN_METAATTRIBUTES:
1104
58f27c3c0167 more guess_field tests and fixes
sylvain.thenault@logilab.fr
parents: 1101
diff changeset
  1138
                metaschema = eschema.has_metadata(rschema, metadata)
58f27c3c0167 more guess_field tests and fixes
sylvain.thenault@logilab.fr
parents: 1101
diff changeset
  1139
                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
  1140
                    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
  1141
                    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
  1142
                                                                **metakwargs)
1095
6917ebe281e9 test and fix guess_field, some pylint fixes
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
  1143
        return fieldclass(**kwargs)
6917ebe281e9 test and fix guess_field, some pylint fixes
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
  1144
    return RelationField.fromcardinality(card, **kwargs)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
  1145
1986
96c0e56cb0cf move widget selection's logic on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
  1146
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
  1147
FIELDS = {
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
  1148
    'Boolean':  BooleanField,
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
  1149
    'Bytes':    FileField,
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
  1150
    'Date':     DateField,
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
  1151
    'Datetime': DateTimeField,
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
  1152
    'Int':      IntField,
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
  1153
    'Float':    FloatField,
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
  1154
    '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
  1155
    'Password': PasswordField,
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
  1156
    'String' :  StringField,
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
  1157
    'Time':     TimeField,
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
  1158
    }