cubicweb/web/formfields.py
author Denis Laxalde <denis.laxalde@logilab.fr>
Sat, 16 Jan 2016 13:48:51 +0100
changeset 11057 0b59724cb3f2
parent 10903 web/formfields.py@da30851f9706
child 11129 97095348b3ee
permissions -rw-r--r--
Reorganize source tree to have a "cubicweb" top-level package Basically: mkdir cubicweb hg mv *.py -X setup.py cubicweb hg mv dataimport devtools entities etwist ext hooks i18n misc schemas server skeleton sobjects test web wsgi cubicweb Other changes: * adjust path to cubicweb-ctl in devtools tests * update setup.py to avoid importing __pkginfo__ (exec it instead), replace os.path.walk by os.walk and prepend `modname` here and there * update tox.ini to account for new test locations * update doc/conf.py so that it still finds __pkginfo__.py and CWDIR in doc/Makefile
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
9179
570208f74a84 [editcontrollers] Ensure entities are created in an order satisfying schema constraints. Closes #3031719
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8695
diff changeset
     1
# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
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
     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
7879
9aae456abab5 [pylint] fix pylint detected errors and tweak it so that pylint -E will be much less verbose next time (+ update some copyrights on the way)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7756
diff changeset
    31
Now, you usually don't use that class but one of the concrete field classes
5368
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()
7460
2455cdbeadca [schema] support for BigInt type. Closes #1720995
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7231
diff changeset
    40
.. autoclass:: cubicweb.web.formfields.BigIntField()
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    41
.. autoclass:: cubicweb.web.formfields.FloatField()
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    42
.. autoclass:: cubicweb.web.formfields.BooleanField()
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    43
.. autoclass:: cubicweb.web.formfields.DateField()
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    44
.. autoclass:: cubicweb.web.formfields.DateTimeField()
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    45
.. autoclass:: cubicweb.web.formfields.TimeField()
8248
9550555e4c26 Fix bug about missing Interval field (closes #1463996).
Damien Garaud <damien.garaud@logilab.fr>
parents: 8238
diff changeset
    46
.. autoclass:: cubicweb.web.formfields.TimeIntervalField()
5368
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
Compound fields
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    49
''''''''''''''''
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    50
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    51
.. autoclass:: cubicweb.web.formfields.RichTextField()
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    52
.. autoclass:: cubicweb.web.formfields.FileField()
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    53
.. autoclass:: cubicweb.web.formfields.CompoundField()
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
.. 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
    56
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    57
Entity specific fields and function
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    58
'''''''''''''''''''''''''''''''''''
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    59
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    60
.. autoclass:: cubicweb.web.formfields.RelationField()
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
    61
.. 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
    62
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
    63
"""
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
    64
__docformat__ = "restructuredtext en"
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
    65
2244
52e2431e7cce missing import
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2196
diff changeset
    66
from warnings import warn
8248
9550555e4c26 Fix bug about missing Interval field (closes #1463996).
Damien Garaud <damien.garaud@logilab.fr>
parents: 8238
diff changeset
    67
from datetime import datetime, timedelta
1095
6917ebe281e9 test and fix guess_field, some pylint fixes
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
    68
10787
34ada3b21eef [web] fix Field.__str__ on py3k
Julien Cristau <julien.cristau@logilab.fr>
parents: 10716
diff changeset
    69
from six import PY2, text_type, string_types
10612
84468b90e9c1 [py3k] basestring → six.string_types
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10012
diff changeset
    70
2312
af4d8f75c5db use xml_escape
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2244
diff changeset
    71
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
    72
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
    73
from logilab.common.date import ustrftime
8248
9550555e4c26 Fix bug about missing Interval field (closes #1463996).
Damien Garaud <damien.garaud@logilab.fr>
parents: 8238
diff changeset
    74
from logilab.common.configuration import format_time
9550555e4c26 Fix bug about missing Interval field (closes #1463996).
Damien Garaud <damien.garaud@logilab.fr>
parents: 8238
diff changeset
    75
from logilab.common.textutils import apply_units, TIME_UNITS
4158
0e97cf2cf55b missing imports
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4156
diff changeset
    76
5030
5238d9a8dfee [form] put qualified name on validation error, should fix #784299
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4874
diff changeset
    77
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
    78
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
    79
                              FormatConstraint)
1095
6917ebe281e9 test and fix guess_field, some pylint fixes
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
    80
4481
56440a1f816a hidden usage of datetime function which has been moved to lgc
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4443
diff changeset
    81
from cubicweb import Binary, tags, uilib
6082
57933567146f [forms] callable field kwargs now always take form _and_ field parameters
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 5955
diff changeset
    82
from cubicweb.utils import support_args
4368
d752ad901f14 cleanup module namespace but only importing the formwidgets module
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4359
diff changeset
    83
from cubicweb.web import INTERNAL_FIELD_VALUE, ProcessFormError, eid_param, \
8665
e65af61bde7d [uicfg] uicfg.py moves from web/ to web/views/ (prepares #2406609)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8517
diff changeset
    84
     formwidgets as fw
e65af61bde7d [uicfg] uicfg.py moves from web/ to web/views/ (prepares #2406609)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8517
diff changeset
    85
from cubicweb.web.views import uicfg
1095
6917ebe281e9 test and fix guess_field, some pylint fixes
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
    86
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
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
    88
    """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
    89
    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
    90
    """
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
    91
5756
ab03e4adb4f1 [filefield] normalized file names to deal with windows files
Stephanie Marcu <stephanie.marcu@logilab.fr>
parents: 5661
diff changeset
    92
def normalize_filename(filename):
ab03e4adb4f1 [filefield] normalized file names to deal with windows files
Stephanie Marcu <stephanie.marcu@logilab.fr>
parents: 5661
diff changeset
    93
    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
    94
3334
8d831c02da9a fix sort of fields vocabulary: should consider option groups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3308
diff changeset
    95
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
    96
    """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
    97
    result = []
8d831c02da9a fix sort of fields vocabulary: should consider option groups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3308
diff changeset
    98
    partresult = []
8d831c02da9a fix sort of fields vocabulary: should consider option groups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3308
diff changeset
    99
    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
   100
        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
   101
            if partresult:
8d831c02da9a fix sort of fields vocabulary: should consider option groups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3308
diff changeset
   102
                result += sorted(partresult)
8d831c02da9a fix sort of fields vocabulary: should consider option groups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3308
diff changeset
   103
                partresult = []
8d831c02da9a fix sort of fields vocabulary: should consider option groups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3308
diff changeset
   104
            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
   105
        else:
8d831c02da9a fix sort of fields vocabulary: should consider option groups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3308
diff changeset
   106
            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
   107
    result += sorted(partresult)
8d831c02da9a fix sort of fields vocabulary: should consider option groups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3308
diff changeset
   108
    return result
8d831c02da9a fix sort of fields vocabulary: should consider option groups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3308
diff changeset
   109
5367
4176a50c81c9 [form] small api cleanup and refactoring before documenting the form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5220
diff changeset
   110
_MARKER = nullobject()
3334
8d831c02da9a fix sort of fields vocabulary: should consider option groups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3308
diff changeset
   111
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   112
class Field(object):
4443
83ff2bb898a5 start documenting forms
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4395
diff changeset
   113
    """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
   114
    of attributes which may be used for fine control of the behaviour of a
7879
9aae456abab5 [pylint] fix pylint detected errors and tweak it so that pylint -E will be much less verbose next time (+ update some copyrights on the way)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7756
diff changeset
   115
    concrete 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
   116
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   117
    **Attributes**
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   118
4443
83ff2bb898a5 start documenting forms
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4395
diff changeset
   119
    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
   120
    overriden by named arguments given to field's constructor.
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
   121
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   122
    :attr:`name`
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   123
       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
   124
       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
   125
       if `eidparam` is true).
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   126
    :attr:`id`
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   127
       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
   128
       a form.
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   129
    :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
   130
       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
   131
    :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
   132
       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
   133
    :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
   134
       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
   135
       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
   136
    :attr:`value`
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   137
       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
   138
       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
   139
    :attr:`choices`
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   140
       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
   141
       (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
   142
       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
   143
    :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
   144
       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
   145
    :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
   146
       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
   147
       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
   148
       sorted on label.
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   149
    :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
   150
       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
   151
       current request language.
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   152
    :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
   153
       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
   154
    :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
   155
       when the field is linked to an entity attribute or relation, tells the
7756
98e34ae4cf89 [form fields doc] explain when field.role should be None
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7574
diff changeset
   156
       role of the entity in the relation (eg 'subject' or 'object'). If this is
98e34ae4cf89 [form fields doc] explain when field.role should be None
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7574
diff changeset
   157
       not an attribute or relation of the edited entity, `role` should be
98e34ae4cf89 [form fields doc] explain when field.role should be None
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7574
diff changeset
   158
       `None`.
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   159
    :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
   160
       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
   161
    :attr:`order`
3874
7d0d4a6be046 [formfields] allow fields ordering with autoform_field_kwargs
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3873
diff changeset
   162
       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
   163
    :attr:`ignore_req_params`
10903
da30851f9706 spelling: *aly → *ally
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10787
diff changeset
   164
       when true, this field won't consider value potentially specified using
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
   165
       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
   166
       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
   167
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   168
    .. currentmodule:: cubicweb.web.formfields
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   169
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   170
    **Generic methods**
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
    .. automethod:: Field.input_name
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   173
    .. automethod:: Field.dom_id
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   174
    .. automethod:: Field.actual_fields
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   175
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   176
    **Form generation methods**
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   177
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   178
    .. automethod:: form_init
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   179
    .. automethod:: typed_value
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   180
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   181
    **Post handling methods**
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   182
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   183
    .. automethod:: process_posted
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   184
    .. automethod:: process_form_value
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   185
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   186
    """
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
   187
    # 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
   188
    # instance
4368
d752ad901f14 cleanup module namespace but only importing the formwidgets module
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4359
diff changeset
   189
    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
   190
    # does this field requires a multipart form
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   191
    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
   192
    # 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
   193
    __creation_rank = 0
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   194
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
   195
    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
   196
    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
   197
    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
   198
    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
   199
    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
   200
    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
   201
    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
   202
    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
   203
    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
   204
    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
   205
    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
   206
    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
   207
    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
   208
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
    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
   210
        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
   211
            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
   212
            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
   213
        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
   214
        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
   215
            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
   216
        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
   217
        # 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
   218
        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
   219
        # 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
   220
        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
   221
        Field.__creation_rank += 1
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
   222
5916
36206e846a27 [form fields] smarter __str__ / __repr__
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5911
diff changeset
   223
    def as_string(self, repr=True):
36206e846a27 [form fields] smarter __str__ / __repr__
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5911
diff changeset
   224
        l = [u'<%s' % self.__class__.__name__]
36206e846a27 [form fields] smarter __str__ / __repr__
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5911
diff changeset
   225
        for attr in ('name', 'eidparam', 'role', 'id', 'value'):
36206e846a27 [form fields] smarter __str__ / __repr__
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5911
diff changeset
   226
            value = getattr(self, attr)
36206e846a27 [form fields] smarter __str__ / __repr__
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5911
diff changeset
   227
            if value is not None and value is not _MARKER:
36206e846a27 [form fields] smarter __str__ / __repr__
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5911
diff changeset
   228
                l.append('%s=%r' % (attr, value))
36206e846a27 [form fields] smarter __str__ / __repr__
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5911
diff changeset
   229
        if repr:
36206e846a27 [form fields] smarter __str__ / __repr__
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5911
diff changeset
   230
            l.append('@%#x' % id(self))
36206e846a27 [form fields] smarter __str__ / __repr__
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5911
diff changeset
   231
        return u'%s>' % ' '.join(l)
36206e846a27 [form fields] smarter __str__ / __repr__
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5911
diff changeset
   232
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   233
    def __unicode__(self):
5916
36206e846a27 [form fields] smarter __str__ / __repr__
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5911
diff changeset
   234
        return self.as_string(False)
36206e846a27 [form fields] smarter __str__ / __repr__
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5911
diff changeset
   235
10787
34ada3b21eef [web] fix Field.__str__ on py3k
Julien Cristau <julien.cristau@logilab.fr>
parents: 10716
diff changeset
   236
    if PY2:
34ada3b21eef [web] fix Field.__str__ on py3k
Julien Cristau <julien.cristau@logilab.fr>
parents: 10716
diff changeset
   237
        def __str__(self):
34ada3b21eef [web] fix Field.__str__ on py3k
Julien Cristau <julien.cristau@logilab.fr>
parents: 10716
diff changeset
   238
            return self.as_string(False).encode('UTF8')
34ada3b21eef [web] fix Field.__str__ on py3k
Julien Cristau <julien.cristau@logilab.fr>
parents: 10716
diff changeset
   239
    else:
34ada3b21eef [web] fix Field.__str__ on py3k
Julien Cristau <julien.cristau@logilab.fr>
parents: 10716
diff changeset
   240
        __str__ = __unicode__
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   241
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   242
    def __repr__(self):
10787
34ada3b21eef [web] fix Field.__str__ on py3k
Julien Cristau <julien.cristau@logilab.fr>
parents: 10716
diff changeset
   243
        return self.as_string(True)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   244
1986
96c0e56cb0cf move widget selection's logic on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   245
    def init_widget(self, widget):
96c0e56cb0cf move widget selection's logic on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   246
        if widget is not None:
96c0e56cb0cf move widget selection's logic on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   247
            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
   248
        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
   249
            self.widget = fw.Select()
1986
96c0e56cb0cf move widget selection's logic on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   250
        if isinstance(self.widget, type):
96c0e56cb0cf move widget selection's logic on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   251
            self.widget = self.widget()
96c0e56cb0cf move widget selection's logic on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   252
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   253
    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
   254
        """automatically set .label when name is set"""
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   255
        assert name
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   256
        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
   257
        if self.label is _MARKER:
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   258
            self.label = name
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
   259
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   260
    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
   261
        """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
   262
        return not isinstance(self.widget, fw.HiddenInput)
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
   263
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   264
    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
   265
        """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
   266
        :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
   267
        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
   268
        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
   269
        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
   270
        """
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   271
        yield self
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
   272
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   273
    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
   274
        """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
   275
        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
   276
        """
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   277
        if isinstance(value, (list, tuple)):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   278
            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
   279
        return self.format_single_value(req, value)
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
   280
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   281
    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
   282
        """return value suitable for display"""
1306
e70ad982374a bool handling
sylvain.thenault@logilab.fr
parents: 1305
diff changeset
   283
        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
   284
            return u''
1306
e70ad982374a bool handling
sylvain.thenault@logilab.fr
parents: 1305
diff changeset
   285
        if value is True:
e70ad982374a bool handling
sylvain.thenault@logilab.fr
parents: 1305
diff changeset
   286
            return u'1'
10696
4ba4be5553cf [py3k] unicode vs str vs bytes vs the world
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10612
diff changeset
   287
        return text_type(value)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   288
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   289
    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
   290
        """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
   291
        return self.widget
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
   292
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
   293
    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
   294
        """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
   295
        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
   296
        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
   297
        """
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
        # 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
   299
        # 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
   300
        # (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
   301
        # 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
   302
        # 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
   303
        #
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
   304
        # 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
   305
        # 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
   306
        # 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
   307
        # 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
   308
        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
   309
            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
   310
        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
   311
            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
   312
            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
   313
                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
   314
            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
   315
                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
   316
            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
   317
            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
   318
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
   319
    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
   320
        """return <field.name>-<field.role> if role is specified, else field.name"""
8517
199fefe396ab [form] add assertion to ensure field has a name when `role_name` is called
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8458
diff changeset
   321
        assert self.name, 'field without a name (give it to constructor for explicitly built fields)'
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
   322
        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
   323
            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
   324
        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
   325
4303
35e814dce815 dom_id now accepts a suffix argument as input_name
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4302
diff changeset
   326
    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
   327
        """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
   328
        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
   329
        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
   330
        """
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
   331
        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
   332
        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
   333
            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
   334
        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
   335
            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
   336
        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
   337
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
   338
    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
   339
        """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
   340
        """
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
   341
        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
   342
            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
   343
            if form._cw.vreg.schema.rschema(self.name).final:
6142
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6139
diff changeset
   344
                if entity.has_eid() or self.name in entity.cw_attr_cache:
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
   345
                    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
   346
                    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
   347
                        return value
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5497
diff changeset
   348
            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
   349
                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
   350
                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
   351
                    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
   352
        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
   353
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
   354
    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
   355
        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
   356
            if callable(self.value):
10006
8391bf718485 remove most 3.10 bw compat
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9821
diff changeset
   357
                return self.value(form, 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
   358
            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
   359
        formattr = '%s_%s_default' % (self.role, self.name)
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
   360
        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
   361
            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
   362
                return form.edited_entity.e_schema.default(self.name)
8458
1c5f3c66ec53 [html form] use __linkto url parameter value as a default value of the corresponding field in a creation form (closes #2407770)
Florent Cayré <florent.cayre@logilab.fr>
parents: 8248
diff changeset
   363
            return form.linked_to.get((self.name, self.role), ())
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
   364
        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
   365
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   366
    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
   367
        """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
   368
        field
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
   369
        """
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   370
        return u''
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   371
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   372
    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
   373
        """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
   374
        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
   375
        """
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
   376
        widget = self.get_widget(form)
3873
4d95109582c7 [web] remove widget.render backward compatibility
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3790
diff changeset
   377
        return widget.render(form, self, renderer)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   378
4388
15c6607c4bda [forms] propagate aguments given to .vocabulary to .choices if it's a callable.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4386
diff changeset
   379
    def vocabulary(self, form, **kwargs):
5908
91c61feb5bc8 [forms] bw compat code for vocabulary function returning typed values
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5816
diff changeset
   380
        """return vocabulary for this field. This method will be
91c61feb5bc8 [forms] bw compat code for vocabulary function returning typed values
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5816
diff changeset
   381
        called by widgets which requires a vocabulary.
91c61feb5bc8 [forms] bw compat code for vocabulary function returning typed values
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5816
diff changeset
   382
91c61feb5bc8 [forms] bw compat code for vocabulary function returning typed values
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5816
diff changeset
   383
        It should return a list of tuple (label, value), where value
9701
46c8d8701240 an unicode string -> a unicode string
Rémi Cardona <remi.cardona@logilab.fr>
parents: 9283
diff changeset
   384
        *must be a unicode string*, not a typed value.
4161
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   385
        """
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
   386
        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
   387
        if callable(self.choices):
7879
9aae456abab5 [pylint] fix pylint detected errors and tweak it so that pylint -E will be much less verbose next time (+ update some copyrights on the way)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7756
diff changeset
   388
            # pylint: disable=E1102
10716
9a9d57edb1c1 [py3k] im_self → __self__
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10696
diff changeset
   389
            if getattr(self.choices, '__self__', None) is self:
7572
a554010417ce [formfields] use support_args instead of catching type error avoid hiding other issues and making debugging difficult
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7231
diff changeset
   390
                vocab = self.choices(form=form, **kwargs)
7990
a673d1d9a738 [diet] drop pre 3.6 API compatibility (but attempt to keep data cmopatibility). Closes #2017916
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7973
diff changeset
   391
            else:
7572
a554010417ce [formfields] use support_args instead of catching type error avoid hiding other issues and making debugging difficult
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7231
diff changeset
   392
                vocab = self.choices(form=form, field=self, **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
   393
        else:
4170
c325c62cec8e crecord introduced junk...
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4168
diff changeset
   394
            vocab = self.choices
c325c62cec8e crecord introduced junk...
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4168
diff changeset
   395
        if vocab and not isinstance(vocab[0], (list, tuple)):
c325c62cec8e crecord introduced junk...
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4168
diff changeset
   396
            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
   397
        if self.internationalizable:
5908
91c61feb5bc8 [forms] bw compat code for vocabulary function returning typed values
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5816
diff changeset
   398
            # the short-cirtcuit 'and' boolean operator is used here
91c61feb5bc8 [forms] bw compat code for vocabulary function returning typed values
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5816
diff changeset
   399
            # to permit a valid empty string in vocabulary without
91c61feb5bc8 [forms] bw compat code for vocabulary function returning typed values
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5816
diff changeset
   400
            # attempting to translate it by gettext (which can lead to
91c61feb5bc8 [forms] bw compat code for vocabulary function returning typed values
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5816
diff changeset
   401
            # weird strings display)
91c61feb5bc8 [forms] bw compat code for vocabulary function returning typed values
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5816
diff changeset
   402
            vocab = [(label and form._cw._(label), value)
91c61feb5bc8 [forms] bw compat code for vocabulary function returning typed values
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5816
diff changeset
   403
                     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
   404
        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
   405
            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
   406
        return vocab
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
   407
6690
7d68948015ba [forms] remove some deprecation warnings
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6582
diff changeset
   408
    # support field as argument to avoid warning when used as format field value
7d68948015ba [forms] remove some deprecation warnings
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6582
diff changeset
   409
    # callback
7d68948015ba [forms] remove some deprecation warnings
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6582
diff changeset
   410
    def format(self, form, field=None):
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
   411
        """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
   412
        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
   413
            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
   414
            if entity.e_schema.has_metadata(self.name, 'format') and (
6142
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6139
diff changeset
   415
                entity.has_eid() or '%s_format' % self.name in entity.cw_attr_cache):
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5497
diff changeset
   416
                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
   417
        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
   418
d2663bcf5306 replace form_field_[encoding|vocabulary] methods on form by encoding|vocabylary(form) methods on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4161
diff changeset
   419
    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
   420
        """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
   421
        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
   422
            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
   423
            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
   424
                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
   425
                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
   426
        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
   427
1307
8c3336c5ddba new form_init callback
sylvain.thenault@logilab.fr
parents: 1306
diff changeset
   428
    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
   429
        """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
   430
        initialization requiring the form instance. Do nothing by default.
1307
8c3336c5ddba new form_init callback
sylvain.thenault@logilab.fr
parents: 1306
diff changeset
   431
        """
8c3336c5ddba new form_init callback
sylvain.thenault@logilab.fr
parents: 1306
diff changeset
   432
        pass
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
   433
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
   434
    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
   435
        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
   436
            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
   437
                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
   438
        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
   439
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
   440
    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
   441
        # 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
   442
        # 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
   443
        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
   444
            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
   445
        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
   446
            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
   447
                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
   448
            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
   449
                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
   450
                                         '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
   451
        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
   452
            # 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
   453
            # 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
   454
            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
   455
        # 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
   456
        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
   457
            # 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
   458
            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
   459
        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
   460
            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
   461
        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
   462
            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
   463
        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
   464
            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
   465
        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
   466
            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
   467
        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
   468
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
   469
    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
   470
        """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
   471
        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
   472
            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
   473
        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
   474
            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
   475
            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
   476
fabc680bb0bf fix Bytes submission pb on POST, due to multiple call to field.process_form_value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4354
diff changeset
   477
    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
   478
        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
   479
        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
   480
        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
   481
75c610a85949 introduce new _ensure_correctly_typed method on fields, responsible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4369
diff changeset
   482
    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
   483
        """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
   484
        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
   485
        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
   486
        """
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
   487
        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
   488
a357d4147eee [forms] work-in-progress, big editcontroller refactoring: let fields/widgets process posted data
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3385
diff changeset
   489
    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
   490
        """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
   491
        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
   492
        """
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
   493
        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
   494
            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
   495
                try:
5038
90493551b1eb [form] fix validation error handling
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5030
diff changeset
   496
                    value = field.process_form_value(form)
9213
312062f53981 [inlined form field] fix regression introduced in 3.16.4/570208f74a84. Closes #3064653
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 9179
diff changeset
   497
                    if field.no_value(value) and field.required:
5038
90493551b1eb [form] fix validation error handling
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5030
diff changeset
   498
                        raise ProcessFormError(form._cw._("required field"))
90493551b1eb [form] fix validation error handling
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5030
diff changeset
   499
                    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
   500
                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
   501
                    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
   502
            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
   503
                # 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
   504
                # 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
   505
                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
   506
                    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
   507
9213
312062f53981 [inlined form field] fix regression introduced in 3.16.4/570208f74a84. Closes #3064653
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 9179
diff changeset
   508
    @staticmethod
312062f53981 [inlined form field] fix regression introduced in 3.16.4/570208f74a84. Closes #3064653
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 9179
diff changeset
   509
    def no_value(value):
312062f53981 [inlined form field] fix regression introduced in 3.16.4/570208f74a84. Closes #3064653
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 9179
diff changeset
   510
        """return True if the value can be considered as no value for the field"""
312062f53981 [inlined form field] fix regression introduced in 3.16.4/570208f74a84. Closes #3064653
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 9179
diff changeset
   511
        return value is None
312062f53981 [inlined form field] fix regression introduced in 3.16.4/570208f74a84. Closes #3064653
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 9179
diff changeset
   512
1986
96c0e56cb0cf move widget selection's logic on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   513
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   514
class StringField(Field):
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   515
    """Use this field to edit unicode string (`String` yams type). This field
10903
da30851f9706 spelling: *aly → *ally
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10787
diff changeset
   516
    additionally support a `max_length` attribute that specify a maximum size for
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   517
    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
   518
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   519
    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
   520
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   521
    * :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
   522
      using `choices` attribute
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   523
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   524
    * :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
   525
      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
   526
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   527
    * :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
   528
    """
4368
d752ad901f14 cleanup module namespace but only importing the formwidgets module
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4359
diff changeset
   529
    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
   530
    size = 45
9718
927d035b6921 [formfields] Handle 'placeholder' attribute for text and textarea
Christophe de Vienne <christophe@unlish.com>
parents: 9444
diff changeset
   531
    placeholder = None
1986
96c0e56cb0cf move widget selection's logic on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   532
4168
9d83f9c80c1c nicer StringField __init__
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4166
diff changeset
   533
    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
   534
        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
   535
        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
   536
96c0e56cb0cf move widget selection's logic on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   537
    def init_widget(self, widget):
96c0e56cb0cf move widget selection's logic on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   538
        if widget is None:
96c0e56cb0cf move widget selection's logic on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   539
            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
   540
                widget = fw.Select()
1986
96c0e56cb0cf move widget selection's logic on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   541
            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
   542
                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
   543
1986
96c0e56cb0cf move widget selection's logic on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   544
        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
   545
        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
   546
            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
   547
        elif isinstance(self.widget, fw.TextInput):
2360
1d43aa551ba9 [formwidgets,formfields] hum, this way
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 2356
diff changeset
   548
            self.init_text_input(self.widget)
1d43aa551ba9 [formwidgets,formfields] hum, this way
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 2356
diff changeset
   549
9718
927d035b6921 [formfields] Handle 'placeholder' attribute for text and textarea
Christophe de Vienne <christophe@unlish.com>
parents: 9444
diff changeset
   550
        if self.placeholder:
927d035b6921 [formfields] Handle 'placeholder' attribute for text and textarea
Christophe de Vienne <christophe@unlish.com>
parents: 9444
diff changeset
   551
            self.widget.attrs.setdefault('placeholder', self.placeholder)
927d035b6921 [formfields] Handle 'placeholder' attribute for text and textarea
Christophe de Vienne <christophe@unlish.com>
parents: 9444
diff changeset
   552
2360
1d43aa551ba9 [formwidgets,formfields] hum, this way
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 2356
diff changeset
   553
    def init_text_input(self, widget):
1d43aa551ba9 [formwidgets,formfields] hum, this way
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 2356
diff changeset
   554
        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
   555
            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
   556
            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
   557
d34589d35daa drop TextField, this is simply a StringField with a text area widget
sylvain.thenault@logilab.fr
parents: 1564
diff changeset
   558
    def init_text_area(self, widget):
9278
a7894d5f00bb [formfields] py3k kill future compat warning
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9213
diff changeset
   559
        if self.max_length and self.max_length < 513:
1573
d34589d35daa drop TextField, this is simply a StringField with a text area widget
sylvain.thenault@logilab.fr
parents: 1564
diff changeset
   560
            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
   561
            widget.attrs.setdefault('rows', 5)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   562
9718
927d035b6921 [formfields] Handle 'placeholder' attribute for text and textarea
Christophe de Vienne <christophe@unlish.com>
parents: 9444
diff changeset
   563
    def set_placeholder(self, placeholder):
927d035b6921 [formfields] Handle 'placeholder' attribute for text and textarea
Christophe de Vienne <christophe@unlish.com>
parents: 9444
diff changeset
   564
        self.placeholder = placeholder
927d035b6921 [formfields] Handle 'placeholder' attribute for text and textarea
Christophe de Vienne <christophe@unlish.com>
parents: 9444
diff changeset
   565
        if self.widget and self.placeholder:
927d035b6921 [formfields] Handle 'placeholder' attribute for text and textarea
Christophe de Vienne <christophe@unlish.com>
parents: 9444
diff changeset
   566
            self.widget.attrs.setdefault('placeholder', self.placeholder)
927d035b6921 [formfields] Handle 'placeholder' attribute for text and textarea
Christophe de Vienne <christophe@unlish.com>
parents: 9444
diff changeset
   567
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   568
4159
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   569
class PasswordField(StringField):
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   570
    """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
   571
    string).
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   572
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   573
    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
   574
    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
   575
    """
4368
d752ad901f14 cleanup module namespace but only importing the formwidgets module
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4359
diff changeset
   576
    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
   577
    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
   578
        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
   579
            # 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
   580
            # 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
   581
            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
   582
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
   583
    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
   584
        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
   585
            # 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
   586
            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
   587
                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
   588
            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
   589
        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
   590
6b2b20c73d59 refactor form field value handling, to get a nicer api and an easier algorithm to get field's value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4158
diff changeset
   591
1573
d34589d35daa drop TextField, this is simply a StringField with a text area widget
sylvain.thenault@logilab.fr
parents: 1564
diff changeset
   592
class RichTextField(StringField):
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   593
    """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
   594
    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
   595
    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
   596
    one will be automaticall generated.
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   597
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   598
    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
   599
    :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
   600
    :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
   601
    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
   602
    """
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   603
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   604
    widget = None
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   605
    def __init__(self, format_field=None, **kwargs):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   606
        super(RichTextField, self).__init__(**kwargs)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   607
        self.format_field = format_field
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   608
2348
acf4b6a59558 [formwidgets] ensure textarea for richstring has not ridicuously small size (close #344547)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 2347
diff changeset
   609
    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
   610
        pass
acf4b6a59558 [formwidgets] ensure textarea for richstring has not ridicuously small size (close #344547)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 2347
diff changeset
   611
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   612
    def get_widget(self, form):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   613
        if self.widget is None:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   614
            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
   615
                return fw.FCKEditor()
d752ad901f14 cleanup module namespace but only importing the formwidgets module
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4359
diff changeset
   616
            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
   617
            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
   618
            return widget
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   619
        return self.widget
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   620
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   621
    def get_format_field(self, form):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   622
        if self.format_field:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   623
            return self.format_field
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   624
        # we have to cache generated field since it's use as key in the
8238
087bb529035c [spelling] fix dictionnary -> dictionary typo
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7990
diff changeset
   625
        # context dictionary
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3388
diff changeset
   626
        req = form._cw
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   627
        try:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   628
            return req.data[self]
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   629
        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
   630
            fkwargs = {'eidparam': self.eidparam, 'role': self.role}
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   631
            if self.use_fckeditor(form):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   632
                # 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
   633
                # 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
   634
                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
   635
                fkwargs['value'] = 'text/html'
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   636
            else:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   637
                # 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
   638
                fkwargs['widget'] = fw.Select()
1095
6917ebe281e9 test and fix guess_field, some pylint fixes
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
   639
                fcstr = FormatConstraint()
3347
428f95118556 fix vocab param to avoid deprecation warning
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3337
diff changeset
   640
                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
   641
                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
   642
                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
   643
            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
   644
            field = StringField(name=self.name + '_format', **fkwargs)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   645
            req.data[self] = field
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   646
            return field
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
   647
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   648
    def actual_fields(self, form):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   649
        yield self
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   650
        format_field = self.get_format_field(form)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   651
        if format_field:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   652
            yield format_field
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
   653
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   654
    def use_fckeditor(self, form):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   655
        """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
   656
        `attr`, according to user preferences
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   657
        """
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3388
diff changeset
   658
        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
   659
            return self.format(form) == 'text/html'
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   660
        return False
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   661
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   662
    def render(self, form, renderer):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   663
        format_field = self.get_format_field(form)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   664
        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
   665
            # 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
   666
            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
   667
                format_field.widget.attrs['style'] = 'display: block'
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   668
            result = format_field.render(form, renderer)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   669
        else:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   670
            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
   671
        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
   672
1417
06af20e663f2 remove spaces
sylvain.thenault@logilab.fr
parents: 1393
diff changeset
   673
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   674
class FileField(StringField):
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   675
    """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
   676
    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
   677
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   678
    * `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
   679
    * `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
   680
    * `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
   681
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   682
    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
   683
    :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
   684
    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
   685
    """
4368
d752ad901f14 cleanup module namespace but only importing the formwidgets module
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4359
diff changeset
   686
    widget = fw.FileInput
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   687
    needs_multipart = True
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
   688
3496
35a67ac6efe8 support name metadata on guess_field; add name_field to FileField
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3347
diff changeset
   689
    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
   690
                 **kwargs):
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   691
        super(FileField, self).__init__(**kwargs)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   692
        self.format_field = format_field
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   693
        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
   694
        self.name_field = name_field
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
   695
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   696
    def actual_fields(self, form):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   697
        yield self
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   698
        if self.format_field:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   699
            yield self.format_field
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   700
        if self.encoding_field:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   701
            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
   702
        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
   703
            yield self.name_field
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   704
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
   705
    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
   706
        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
   707
            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
   708
                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
   709
                    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
   710
                # 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
   711
                # 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
   712
                # * 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
   713
                # * 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
   714
                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
   715
            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
   716
        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
   717
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   718
    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
   719
        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
   720
        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
   721
            divid = '%s-advanced' % self.input_name(form)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   722
            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
   723
                        (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
   724
                         form._cw._('show advanced fields'),
7070
5f8e52d722c5 [web] provide a data_url() method on req and get_rid of explicit datadir_url usage (#1438736)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 6690
diff changeset
   725
                         xml_escape(form._cw.data_url('puce_down.png')),
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3388
diff changeset
   726
                         form._cw._('show advanced fields')))
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   727
            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
   728
            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
   729
                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
   730
            if self.format_field:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   731
                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
   732
            if self.encoding_field:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   733
                wdgs.append(self.render_subfield(form, self.encoding_field, renderer))
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
   734
            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
   735
        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
   736
            # 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
   737
            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
   738
            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
   739
                                   type=u'checkbox'))
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3388
diff changeset
   740
            wdgs.append(form._cw._('detach attached file'))
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   741
        return u'\n'.join(wdgs)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   742
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   743
    def render_subfield(self, form, field, renderer):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   744
        return (renderer.render_label(form, field)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   745
                + field.render(form, renderer)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   746
                + renderer.render_help(form, field)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   747
                + u'<br/>')
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   748
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
   749
    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
   750
        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
   751
        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
   752
            # 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
   753
            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
   754
        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
   755
            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
   756
        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
   757
            # 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
   758
            # 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
   759
            raise UnmodifiedField()
9147
01124cfd4b1f [etwist] fix handling of multiple files per field
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8695
diff changeset
   760
        # value is a 2-uple (filename, stream) or a list of such
01124cfd4b1f [etwist] fix handling of multiple files per field
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8695
diff changeset
   761
        # tuples (multiple files)
5497
96fd339f7917 Handle new way of reporting unmodified FileFields
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 5426
diff changeset
   762
        try:
9147
01124cfd4b1f [etwist] fix handling of multiple files per field
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8695
diff changeset
   763
            if isinstance(value, list):
01124cfd4b1f [etwist] fix handling of multiple files per field
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8695
diff changeset
   764
                value = value[0]
01124cfd4b1f [etwist] fix handling of multiple files per field
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8695
diff changeset
   765
                form.warning('mutiple files provided, however '
01124cfd4b1f [etwist] fix handling of multiple files per field
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8695
diff changeset
   766
                             'only the first will be picked')
5497
96fd339f7917 Handle new way of reporting unmodified FileFields
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 5426
diff changeset
   767
            filename, stream = value
96fd339f7917 Handle new way of reporting unmodified FileFields
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 5426
diff changeset
   768
        except ValueError:
96fd339f7917 Handle new way of reporting unmodified FileFields
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 5426
diff changeset
   769
            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
   770
        # 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
   771
        value = Binary(stream.read())
4273
183cd0df6f1a fix dumb name error
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4272
diff changeset
   772
        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
   773
            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
   774
        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
   775
            # 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
   776
            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
   777
        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
   778
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
   779
5367
4176a50c81c9 [form] small api cleanup and refactoring before documenting the form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5220
diff changeset
   780
# XXX turn into a widget
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   781
class EditableFileField(FileField):
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   782
    """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
   783
    :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
   784
    actually contains some text.
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   785
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   786
    If the stream format is one of text/plain, text/html, text/rest,
10012
8c2c6fdd8d56 [RichString] Add markdown support
Christophe de Vienne <christophe@unlish.com>
parents: 10006
diff changeset
   787
    text/markdown
10903
da30851f9706 spelling: *aly → *ally
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10787
diff changeset
   788
    then a :class:`~cubicweb.web.formwidgets.TextArea` will be additionally
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   789
    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
   790
    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
   791
    """
10012
8c2c6fdd8d56 [RichString] Add markdown support
Christophe de Vienne <christophe@unlish.com>
parents: 10006
diff changeset
   792
    editable_formats = (
8c2c6fdd8d56 [RichString] Add markdown support
Christophe de Vienne <christophe@unlish.com>
parents: 10006
diff changeset
   793
        'text/plain', 'text/html', 'text/rest', 'text/markdown')
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
   794
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   795
    def render(self, form, renderer):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   796
        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
   797
        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
   798
            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
   799
            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
   800
                encoding = self.encoding(form)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   801
                try:
10696
4ba4be5553cf [py3k] unicode vs str vs bytes vs the world
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10612
diff changeset
   802
                    form.formvalues[(self, form)] = data.getvalue().decode(encoding)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   803
                except UnicodeError:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   804
                    pass
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   805
                else:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   806
                    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
   807
                        msg = form._cw._(
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   808
                            '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
   809
                            ', 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
   810
                            '"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
   811
                            'with the widget below.')
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   812
                    else:
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3388
diff changeset
   813
                        msg = form._cw._(
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   814
                            '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
   815
                            ', 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
   816
                    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
   817
                    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
   818
                    # XXX restore form context?
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   819
        return '\n'.join(wdgs)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   820
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
   821
    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
   822
        value = form._cw.form.get(self.input_name(form))
10696
4ba4be5553cf [py3k] unicode vs str vs bytes vs the world
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10612
diff changeset
   823
        if isinstance(value, text_type):
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
   824
            # 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
   825
            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
   826
        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
   827
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
   828
7460
2455cdbeadca [schema] support for BigInt type. Closes #1720995
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7231
diff changeset
   829
class BigIntField(Field):
2455cdbeadca [schema] support for BigInt type. Closes #1720995
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7231
diff changeset
   830
    """Use this field to edit big integers (`BigInt` yams type). This field
10903
da30851f9706 spelling: *aly → *ally
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10787
diff changeset
   831
    additionally support `min` and `max` attributes that specify a minimum and/or
7460
2455cdbeadca [schema] support for BigInt type. Closes #1720995
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7231
diff changeset
   832
    maximum value for the integer (`None` meaning no boundary).
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   833
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   834
    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
   835
    :class:`~cubicweb.web.formwidgets.TextInput`.
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   836
    """
7460
2455cdbeadca [schema] support for BigInt type. Closes #1720995
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7231
diff changeset
   837
    default_text_input_size = 10
2455cdbeadca [schema] support for BigInt type. Closes #1720995
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7231
diff changeset
   838
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   839
    def __init__(self, min=None, max=None, **kwargs):
7460
2455cdbeadca [schema] support for BigInt type. Closes #1720995
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7231
diff changeset
   840
        super(BigIntField, self).__init__(**kwargs)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   841
        self.min = min
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   842
        self.max = max
7460
2455cdbeadca [schema] support for BigInt type. Closes #1720995
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7231
diff changeset
   843
2455cdbeadca [schema] support for BigInt type. Closes #1720995
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7231
diff changeset
   844
    def init_widget(self, widget):
7462
fbfde96437ad [web] fix typo
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 7460
diff changeset
   845
        super(BigIntField, 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
   846
        if isinstance(self.widget, fw.TextInput):
7460
2455cdbeadca [schema] support for BigInt type. Closes #1720995
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7231
diff changeset
   847
            self.widget.attrs.setdefault('size', self.default_text_input_size)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   848
4370
75c610a85949 introduce new _ensure_correctly_typed method on fields, responsible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4369
diff changeset
   849
    def _ensure_correctly_typed(self, form, value):
10612
84468b90e9c1 [py3k] basestring → six.string_types
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10012
diff changeset
   850
        if isinstance(value, string_types):
4528
a51f37efc882 quick fix for typed formfield validation: accept empty string, split
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4499
diff changeset
   851
            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
   852
            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
   853
                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
   854
            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
   855
                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
   856
            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
   857
                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
   858
        return value
1986
96c0e56cb0cf move widget selection's logic on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   859
96c0e56cb0cf move widget selection's logic on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
   860
7460
2455cdbeadca [schema] support for BigInt type. Closes #1720995
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7231
diff changeset
   861
class IntField(BigIntField):
2455cdbeadca [schema] support for BigInt type. Closes #1720995
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7231
diff changeset
   862
    """Use this field to edit integers (`Int` yams type). Similar to
2455cdbeadca [schema] support for BigInt type. Closes #1720995
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7231
diff changeset
   863
    :class:`~cubicweb.web.formfields.BigIntField` but set max length when text
2455cdbeadca [schema] support for BigInt type. Closes #1720995
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7231
diff changeset
   864
    input widget is used (the default).
2455cdbeadca [schema] support for BigInt type. Closes #1720995
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7231
diff changeset
   865
    """
2455cdbeadca [schema] support for BigInt type. Closes #1720995
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7231
diff changeset
   866
    default_text_input_size = 5
2455cdbeadca [schema] support for BigInt type. Closes #1720995
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7231
diff changeset
   867
2455cdbeadca [schema] support for BigInt type. Closes #1720995
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7231
diff changeset
   868
    def init_widget(self, widget):
7462
fbfde96437ad [web] fix typo
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 7460
diff changeset
   869
        super(IntField, self).init_widget(widget)
7460
2455cdbeadca [schema] support for BigInt type. Closes #1720995
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7231
diff changeset
   870
        if isinstance(self.widget, fw.TextInput):
2455cdbeadca [schema] support for BigInt type. Closes #1720995
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7231
diff changeset
   871
            self.widget.attrs.setdefault('maxlength', 15)
2455cdbeadca [schema] support for BigInt type. Closes #1720995
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7231
diff changeset
   872
2455cdbeadca [schema] support for BigInt type. Closes #1720995
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7231
diff changeset
   873
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   874
class BooleanField(Field):
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   875
    """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
   876
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   877
    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
   878
    :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
   879
    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
   880
    """
4368
d752ad901f14 cleanup module namespace but only importing the formwidgets module
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4359
diff changeset
   881
    widget = fw.Radio
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
   882
6114
3e1718a2db55 [formwidgets] new allow_none attribute on BooleanField allowing a third None value for booleans
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5955
diff changeset
   883
    def __init__(self, allow_none=False, **kwargs):
3e1718a2db55 [formwidgets] new allow_none attribute on BooleanField allowing a third None value for booleans
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5955
diff changeset
   884
        super(BooleanField, self).__init__(**kwargs)
3e1718a2db55 [formwidgets] new allow_none attribute on BooleanField allowing a third None value for booleans
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5955
diff changeset
   885
        self.allow_none = allow_none
3e1718a2db55 [formwidgets] new allow_none attribute on BooleanField allowing a third None value for booleans
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5955
diff changeset
   886
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   887
    def vocabulary(self, form):
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   888
        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
   889
            return super(BooleanField, self).vocabulary(form)
6114
3e1718a2db55 [formwidgets] new allow_none attribute on BooleanField allowing a third None value for booleans
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5955
diff changeset
   890
        if self.allow_none:
7231
18bcb98d129a [widgets] handle no value label for tristate radios, put default separator on class for easier redefinition - closes #1624839
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7166
diff changeset
   891
            return [(form._cw._('indifferent'), ''),
18bcb98d129a [widgets] handle no value label for tristate radios, put default separator on class for easier redefinition - closes #1624839
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7166
diff changeset
   892
                    (form._cw._('yes'), '1'),
18bcb98d129a [widgets] handle no value label for tristate radios, put default separator on class for easier redefinition - closes #1624839
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7166
diff changeset
   893
                    (form._cw._('no'), '0')]
6114
3e1718a2db55 [formwidgets] new allow_none attribute on BooleanField allowing a third None value for booleans
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5955
diff changeset
   894
        # XXX empty string for 'no' in that case for bw compat
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3388
diff changeset
   895
        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
   896
6285
b8a2c9b9a2cb [boolean field] we've to override format_single_value as well in case where None are allowed
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6218
diff changeset
   897
    def format_single_value(self, req, value):
b8a2c9b9a2cb [boolean field] we've to override format_single_value as well in case where None are allowed
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6218
diff changeset
   898
        """return value suitable for display"""
b8a2c9b9a2cb [boolean field] we've to override format_single_value as well in case where None are allowed
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6218
diff changeset
   899
        if self.allow_none:
b8a2c9b9a2cb [boolean field] we've to override format_single_value as well in case where None are allowed
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6218
diff changeset
   900
            if value is None:
b8a2c9b9a2cb [boolean field] we've to override format_single_value as well in case where None are allowed
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6218
diff changeset
   901
                return u''
b8a2c9b9a2cb [boolean field] we've to override format_single_value as well in case where None are allowed
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6218
diff changeset
   902
            if value is False:
b8a2c9b9a2cb [boolean field] we've to override format_single_value as well in case where None are allowed
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6218
diff changeset
   903
                return '0'
b8a2c9b9a2cb [boolean field] we've to override format_single_value as well in case where None are allowed
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6218
diff changeset
   904
        return super(BooleanField, self).format_single_value(req, value)
b8a2c9b9a2cb [boolean field] we've to override format_single_value as well in case where None are allowed
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6218
diff changeset
   905
4370
75c610a85949 introduce new _ensure_correctly_typed method on fields, responsible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4369
diff changeset
   906
    def _ensure_correctly_typed(self, form, value):
6114
3e1718a2db55 [formwidgets] new allow_none attribute on BooleanField allowing a third None value for booleans
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5955
diff changeset
   907
        if self.allow_none:
3e1718a2db55 [formwidgets] new allow_none attribute on BooleanField allowing a third None value for booleans
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5955
diff changeset
   908
            if value:
3e1718a2db55 [formwidgets] new allow_none attribute on BooleanField allowing a third None value for booleans
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5955
diff changeset
   909
                return bool(int(value))
3e1718a2db55 [formwidgets] new allow_none attribute on BooleanField allowing a third None value for booleans
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5955
diff changeset
   910
            return None
4393
87e48fe398f1 systematically call bool on BooleanField values
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4392
diff changeset
   911
        return bool(value)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   912
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   913
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
   914
class FloatField(IntField):
10903
da30851f9706 spelling: *aly → *ally
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10787
diff changeset
   915
    """Use this field to edit floats (`Float` yams type). This field additionally
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   916
    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
   917
    :class:`~cubicweb.web.formfields.IntField`.
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   918
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   919
    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
   920
    :class:`~cubicweb.web.formwidgets.TextInput`.
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   921
    """
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   922
    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
   923
        formatstr = req.property_value('ui.float-format')
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   924
        if value is None:
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   925
            return u''
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   926
        return formatstr % float(value)
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   927
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   928
    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
   929
        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
   930
4370
75c610a85949 introduce new _ensure_correctly_typed method on fields, responsible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4369
diff changeset
   931
    def _ensure_correctly_typed(self, form, value):
10612
84468b90e9c1 [py3k] basestring → six.string_types
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10012
diff changeset
   932
        if isinstance(value, string_types):
4528
a51f37efc882 quick fix for typed formfield validation: accept empty string, split
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4499
diff changeset
   933
            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
   934
            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
   935
                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
   936
            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
   937
                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
   938
            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
   939
                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
   940
        return None
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   941
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   942
8248
9550555e4c26 Fix bug about missing Interval field (closes #1463996).
Damien Garaud <damien.garaud@logilab.fr>
parents: 8238
diff changeset
   943
class TimeIntervalField(StringField):
9550555e4c26 Fix bug about missing Interval field (closes #1463996).
Damien Garaud <damien.garaud@logilab.fr>
parents: 8238
diff changeset
   944
    """Use this field to edit time interval (`Interval` yams type).
9550555e4c26 Fix bug about missing Interval field (closes #1463996).
Damien Garaud <damien.garaud@logilab.fr>
parents: 8238
diff changeset
   945
9550555e4c26 Fix bug about missing Interval field (closes #1463996).
Damien Garaud <damien.garaud@logilab.fr>
parents: 8238
diff changeset
   946
    Unless explicitly specified, the widget for this field will be a
9550555e4c26 Fix bug about missing Interval field (closes #1463996).
Damien Garaud <damien.garaud@logilab.fr>
parents: 8238
diff changeset
   947
    :class:`~cubicweb.web.formwidgets.TextInput`.
9550555e4c26 Fix bug about missing Interval field (closes #1463996).
Damien Garaud <damien.garaud@logilab.fr>
parents: 8238
diff changeset
   948
    """
9550555e4c26 Fix bug about missing Interval field (closes #1463996).
Damien Garaud <damien.garaud@logilab.fr>
parents: 8238
diff changeset
   949
    widget = fw.TextInput
9550555e4c26 Fix bug about missing Interval field (closes #1463996).
Damien Garaud <damien.garaud@logilab.fr>
parents: 8238
diff changeset
   950
9550555e4c26 Fix bug about missing Interval field (closes #1463996).
Damien Garaud <damien.garaud@logilab.fr>
parents: 8238
diff changeset
   951
    def format_single_value(self, req, value):
9550555e4c26 Fix bug about missing Interval field (closes #1463996).
Damien Garaud <damien.garaud@logilab.fr>
parents: 8238
diff changeset
   952
        if value:
9550555e4c26 Fix bug about missing Interval field (closes #1463996).
Damien Garaud <damien.garaud@logilab.fr>
parents: 8238
diff changeset
   953
            value = format_time(value.days * 24 * 3600 + value.seconds)
10696
4ba4be5553cf [py3k] unicode vs str vs bytes vs the world
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10612
diff changeset
   954
            return text_type(value)
8248
9550555e4c26 Fix bug about missing Interval field (closes #1463996).
Damien Garaud <damien.garaud@logilab.fr>
parents: 8238
diff changeset
   955
        return u''
9550555e4c26 Fix bug about missing Interval field (closes #1463996).
Damien Garaud <damien.garaud@logilab.fr>
parents: 8238
diff changeset
   956
9550555e4c26 Fix bug about missing Interval field (closes #1463996).
Damien Garaud <damien.garaud@logilab.fr>
parents: 8238
diff changeset
   957
    def example_format(self, req):
9550555e4c26 Fix bug about missing Interval field (closes #1463996).
Damien Garaud <damien.garaud@logilab.fr>
parents: 8238
diff changeset
   958
        """return a sample string describing what can be given as input for this
9550555e4c26 Fix bug about missing Interval field (closes #1463996).
Damien Garaud <damien.garaud@logilab.fr>
parents: 8238
diff changeset
   959
        field
9550555e4c26 Fix bug about missing Interval field (closes #1463996).
Damien Garaud <damien.garaud@logilab.fr>
parents: 8238
diff changeset
   960
        """
9550555e4c26 Fix bug about missing Interval field (closes #1463996).
Damien Garaud <damien.garaud@logilab.fr>
parents: 8238
diff changeset
   961
        return u'20s, 10min, 24h, 4d'
9550555e4c26 Fix bug about missing Interval field (closes #1463996).
Damien Garaud <damien.garaud@logilab.fr>
parents: 8238
diff changeset
   962
9550555e4c26 Fix bug about missing Interval field (closes #1463996).
Damien Garaud <damien.garaud@logilab.fr>
parents: 8238
diff changeset
   963
    def _ensure_correctly_typed(self, form, value):
10612
84468b90e9c1 [py3k] basestring → six.string_types
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10012
diff changeset
   964
        if isinstance(value, string_types):
8248
9550555e4c26 Fix bug about missing Interval field (closes #1463996).
Damien Garaud <damien.garaud@logilab.fr>
parents: 8238
diff changeset
   965
            value = value.strip()
9550555e4c26 Fix bug about missing Interval field (closes #1463996).
Damien Garaud <damien.garaud@logilab.fr>
parents: 8238
diff changeset
   966
            if not value:
9550555e4c26 Fix bug about missing Interval field (closes #1463996).
Damien Garaud <damien.garaud@logilab.fr>
parents: 8238
diff changeset
   967
                return None
9550555e4c26 Fix bug about missing Interval field (closes #1463996).
Damien Garaud <damien.garaud@logilab.fr>
parents: 8238
diff changeset
   968
            try:
9550555e4c26 Fix bug about missing Interval field (closes #1463996).
Damien Garaud <damien.garaud@logilab.fr>
parents: 8238
diff changeset
   969
                value = apply_units(value, TIME_UNITS)
9550555e4c26 Fix bug about missing Interval field (closes #1463996).
Damien Garaud <damien.garaud@logilab.fr>
parents: 8238
diff changeset
   970
            except ValueError:
9550555e4c26 Fix bug about missing Interval field (closes #1463996).
Damien Garaud <damien.garaud@logilab.fr>
parents: 8238
diff changeset
   971
                raise ProcessFormError(form._cw._('a number (in seconds) or 20s, 10min, 24h or 4d are expected'))
9550555e4c26 Fix bug about missing Interval field (closes #1463996).
Damien Garaud <damien.garaud@logilab.fr>
parents: 8238
diff changeset
   972
        return timedelta(0, value)
9550555e4c26 Fix bug about missing Interval field (closes #1463996).
Damien Garaud <damien.garaud@logilab.fr>
parents: 8238
diff changeset
   973
9550555e4c26 Fix bug about missing Interval field (closes #1463996).
Damien Garaud <damien.garaud@logilab.fr>
parents: 8238
diff changeset
   974
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   975
class DateField(StringField):
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   976
    """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
   977
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   978
    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
   979
    :class:`~cubicweb.web.formwidgets.JQueryDatePicker`.
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   980
    """
4374
ff3efacfea42 by default use new jquery widgets for Time/Date/DateTime fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4370
diff changeset
   981
    widget = fw.JQueryDatePicker
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   982
    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
   983
    etype = 'Date'
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
   984
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   985
    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
   986
        if value:
4544
d92aa3221c30 split introduced in the wrong place
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4528
diff changeset
   987
            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
   988
        return u''
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   989
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
   990
    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
   991
        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
   992
4370
75c610a85949 introduce new _ensure_correctly_typed method on fields, responsible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4369
diff changeset
   993
    def _ensure_correctly_typed(self, form, value):
10612
84468b90e9c1 [py3k] basestring → six.string_types
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10012
diff changeset
   994
        if isinstance(value, string_types):
4528
a51f37efc882 quick fix for typed formfield validation: accept empty string, split
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4499
diff changeset
   995
            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
   996
            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
   997
                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
   998
            try:
4370
75c610a85949 introduce new _ensure_correctly_typed method on fields, responsible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4369
diff changeset
   999
                value = form._cw.parse_datetime(value, self.etype)
8695
358d8bed9626 [toward-py3k] rewrite to "except AnException as exc:" (part of #2711624)
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 8666
diff changeset
  1000
            except ValueError as ex:
10696
4ba4be5553cf [py3k] unicode vs str vs bytes vs the world
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10612
diff changeset
  1001
                raise ProcessFormError(text_type(ex))
4370
75c610a85949 introduce new _ensure_correctly_typed method on fields, responsible
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4369
diff changeset
  1002
        return value
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
  1003
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
class DateTimeField(DateField):
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
  1006
    """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
  1007
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
  1008
    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
  1009
    :class:`~cubicweb.web.formwidgets.JQueryDateTimePicker`.
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
  1010
    """
4374
ff3efacfea42 by default use new jquery widgets for Time/Date/DateTime fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4370
diff changeset
  1011
    widget = fw.JQueryDateTimePicker
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
  1012
    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
  1013
    etype = 'Datetime'
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
  1014
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
  1015
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
  1016
class TimeField(DateField):
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
  1017
    """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
  1018
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
  1019
    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
  1020
    :class:`~cubicweb.web.formwidgets.JQueryTimePicker`.
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
  1021
    """
4374
ff3efacfea42 by default use new jquery widgets for Time/Date/DateTime fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4370
diff changeset
  1022
    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
  1023
    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
  1024
    etype = 'Time'
1986
96c0e56cb0cf move widget selection's logic on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
  1025
4161
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
  1026
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
  1027
# 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
  1028
class CompoundField(Field):
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
  1029
    """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
  1030
    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
  1031
    """
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
  1032
    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
  1033
        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
  1034
        self.fields = fields
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
  1035
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
  1036
    def subfields(self, form):
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
  1037
        return self.fields
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
  1038
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
  1039
    def actual_fields(self, form):
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
  1040
        # 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
  1041
        # 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
  1042
        # 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
  1043
        # 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
  1044
        return list(self.fields)
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
  1045
9444
6012cf57f48e [web/formfields] Make CompoundField inherit needs_multipart from its subfields
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 9283
diff changeset
  1046
    @property
6012cf57f48e [web/formfields] Make CompoundField inherit needs_multipart from its subfields
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 9283
diff changeset
  1047
    def needs_multipart(self):
6012cf57f48e [web/formfields] Make CompoundField inherit needs_multipart from its subfields
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 9283
diff changeset
  1048
        return any(f.needs_multipart for f in self.fields)
6012cf57f48e [web/formfields] Make CompoundField inherit needs_multipart from its subfields
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 9283
diff changeset
  1049
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
  1050
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
  1051
class RelationField(Field):
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
  1052
    """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
  1053
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
  1054
    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
  1055
    :class:`~cubicweb.web.formwidgets.Select`.
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
  1056
    """
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
  1057
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
  1058
    @staticmethod
1095
6917ebe281e9 test and fix guess_field, some pylint fixes
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
  1059
    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
  1060
        kwargs.setdefault('widget', fw.Select(multiple=card in '*+'))
1738
2cfd50c8a415 should not override potential explicit widget
sylvain.thenault@logilab.fr
parents: 1709
diff changeset
  1061
        return RelationField(**kwargs)
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
  1062
4161
4273f5094651 refactor vocabulary handling to avoid having to define methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4160
diff changeset
  1063
    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
  1064
        """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
  1065
        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
  1066
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
  1067
        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
  1068
        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
  1069
        * 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
  1070
        * 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
  1071
        """
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1108
diff changeset
  1072
        entity = form.edited_entity
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
  1073
        # 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
  1074
        if limit is None:
7875
65e460690139 [form, entity] refactor '__linkto', now handled by the entity form, not the entity itself. Closes #1931543
Florent Cayré <florent.cayre@gmail.com>
parents: 7756
diff changeset
  1075
            linkedto = self.relvoc_linkedto(form)
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
  1076
            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
  1077
                return linkedto
7990
a673d1d9a738 [diet] drop pre 3.6 API compatibility (but attempt to keep data cmopatibility). Closes #2017916
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7973
diff changeset
  1078
            # it isn't, search more vocabulary
7875
65e460690139 [form, entity] refactor '__linkto', now handled by the entity form, not the entity itself. Closes #1931543
Florent Cayré <florent.cayre@gmail.com>
parents: 7756
diff changeset
  1079
            vocab = self.relvoc_init(form)
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
  1080
        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
  1081
            vocab = []
7990
a673d1d9a738 [diet] drop pre 3.6 API compatibility (but attempt to keep data cmopatibility). Closes #2017916
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7973
diff changeset
  1082
        vocab += self.relvoc_unrelated(form, 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
  1083
        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
  1084
            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
  1085
        return vocab
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1417
diff changeset
  1086
7875
65e460690139 [form, entity] refactor '__linkto', now handled by the entity form, not the entity itself. Closes #1931543
Florent Cayré <florent.cayre@gmail.com>
parents: 7756
diff changeset
  1087
    def relvoc_linkedto(self, form):
65e460690139 [form, entity] refactor '__linkto', now handled by the entity form, not the entity itself. Closes #1931543
Florent Cayré <florent.cayre@gmail.com>
parents: 7756
diff changeset
  1088
        linkedto = form.linked_to.get((self.name, self.role))
65e460690139 [form, entity] refactor '__linkto', now handled by the entity form, not the entity itself. Closes #1931543
Florent Cayré <florent.cayre@gmail.com>
parents: 7756
diff changeset
  1089
        if linkedto:
65e460690139 [form, entity] refactor '__linkto', now handled by the entity form, not the entity itself. Closes #1931543
Florent Cayré <florent.cayre@gmail.com>
parents: 7756
diff changeset
  1090
            buildent = form._cw.entity_from_eid
10696
4ba4be5553cf [py3k] unicode vs str vs bytes vs the world
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10612
diff changeset
  1091
            return [(buildent(eid).view('combobox'), text_type(eid))
7875
65e460690139 [form, entity] refactor '__linkto', now handled by the entity form, not the entity itself. Closes #1931543
Florent Cayré <florent.cayre@gmail.com>
parents: 7756
diff changeset
  1092
                    for eid in linkedto]
65e460690139 [form, entity] refactor '__linkto', now handled by the entity form, not the entity itself. Closes #1931543
Florent Cayré <florent.cayre@gmail.com>
parents: 7756
diff changeset
  1093
        return []
65e460690139 [form, entity] refactor '__linkto', now handled by the entity form, not the entity itself. Closes #1931543
Florent Cayré <florent.cayre@gmail.com>
parents: 7756
diff changeset
  1094
65e460690139 [form, entity] refactor '__linkto', now handled by the entity form, not the entity itself. Closes #1931543
Florent Cayré <florent.cayre@gmail.com>
parents: 7756
diff changeset
  1095
    def relvoc_init(self, form):
65e460690139 [form, entity] refactor '__linkto', now handled by the entity form, not the entity itself. Closes #1931543
Florent Cayré <florent.cayre@gmail.com>
parents: 7756
diff changeset
  1096
        entity, rtype, role = form.edited_entity, self.name, self.role
65e460690139 [form, entity] refactor '__linkto', now handled by the entity form, not the entity itself. Closes #1931543
Florent Cayré <florent.cayre@gmail.com>
parents: 7756
diff changeset
  1097
        vocab = []
65e460690139 [form, entity] refactor '__linkto', now handled by the entity form, not the entity itself. Closes #1931543
Florent Cayré <florent.cayre@gmail.com>
parents: 7756
diff changeset
  1098
        if not self.required:
65e460690139 [form, entity] refactor '__linkto', now handled by the entity form, not the entity itself. Closes #1931543
Florent Cayré <florent.cayre@gmail.com>
parents: 7756
diff changeset
  1099
            vocab.append(('', INTERNAL_FIELD_VALUE))
65e460690139 [form, entity] refactor '__linkto', now handled by the entity form, not the entity itself. Closes #1931543
Florent Cayré <florent.cayre@gmail.com>
parents: 7756
diff changeset
  1100
        # vocabulary doesn't include current values, add them
65e460690139 [form, entity] refactor '__linkto', now handled by the entity form, not the entity itself. Closes #1931543
Florent Cayré <florent.cayre@gmail.com>
parents: 7756
diff changeset
  1101
        if form.edited_entity.has_eid():
65e460690139 [form, entity] refactor '__linkto', now handled by the entity form, not the entity itself. Closes #1931543
Florent Cayré <florent.cayre@gmail.com>
parents: 7756
diff changeset
  1102
            rset = form.edited_entity.related(self.name, self.role)
10696
4ba4be5553cf [py3k] unicode vs str vs bytes vs the world
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10612
diff changeset
  1103
            vocab += [(e.view('combobox'), text_type(e.eid))
7875
65e460690139 [form, entity] refactor '__linkto', now handled by the entity form, not the entity itself. Closes #1931543
Florent Cayré <florent.cayre@gmail.com>
parents: 7756
diff changeset
  1104
                      for e in rset.entities()]
65e460690139 [form, entity] refactor '__linkto', now handled by the entity form, not the entity itself. Closes #1931543
Florent Cayré <florent.cayre@gmail.com>
parents: 7756
diff changeset
  1105
        return vocab
65e460690139 [form, entity] refactor '__linkto', now handled by the entity form, not the entity itself. Closes #1931543
Florent Cayré <florent.cayre@gmail.com>
parents: 7756
diff changeset
  1106
65e460690139 [form, entity] refactor '__linkto', now handled by the entity form, not the entity itself. Closes #1931543
Florent Cayré <florent.cayre@gmail.com>
parents: 7756
diff changeset
  1107
    def relvoc_unrelated(self, form, limit=None):
65e460690139 [form, entity] refactor '__linkto', now handled by the entity form, not the entity itself. Closes #1931543
Florent Cayré <florent.cayre@gmail.com>
parents: 7756
diff changeset
  1108
        entity = form.edited_entity
65e460690139 [form, entity] refactor '__linkto', now handled by the entity form, not the entity itself. Closes #1931543
Florent Cayré <florent.cayre@gmail.com>
parents: 7756
diff changeset
  1109
        rtype = entity._cw.vreg.schema.rschema(self.name)
65e460690139 [form, entity] refactor '__linkto', now handled by the entity form, not the entity itself. Closes #1931543
Florent Cayré <florent.cayre@gmail.com>
parents: 7756
diff changeset
  1110
        if entity.has_eid():
65e460690139 [form, entity] refactor '__linkto', now handled by the entity form, not the entity itself. Closes #1931543
Florent Cayré <florent.cayre@gmail.com>
parents: 7756
diff changeset
  1111
            done = set(row[0] for row in entity.related(rtype, self.role))
65e460690139 [form, entity] refactor '__linkto', now handled by the entity form, not the entity itself. Closes #1931543
Florent Cayré <florent.cayre@gmail.com>
parents: 7756
diff changeset
  1112
        else:
65e460690139 [form, entity] refactor '__linkto', now handled by the entity form, not the entity itself. Closes #1931543
Florent Cayré <florent.cayre@gmail.com>
parents: 7756
diff changeset
  1113
            done = None
65e460690139 [form, entity] refactor '__linkto', now handled by the entity form, not the entity itself. Closes #1931543
Florent Cayré <florent.cayre@gmail.com>
parents: 7756
diff changeset
  1114
        result = []
65e460690139 [form, entity] refactor '__linkto', now handled by the entity form, not the entity itself. Closes #1931543
Florent Cayré <florent.cayre@gmail.com>
parents: 7756
diff changeset
  1115
        rsetsize = None
65e460690139 [form, entity] refactor '__linkto', now handled by the entity form, not the entity itself. Closes #1931543
Florent Cayré <florent.cayre@gmail.com>
parents: 7756
diff changeset
  1116
        for objtype in rtype.targets(entity.e_schema, self.role):
65e460690139 [form, entity] refactor '__linkto', now handled by the entity form, not the entity itself. Closes #1931543
Florent Cayré <florent.cayre@gmail.com>
parents: 7756
diff changeset
  1117
            if limit is not None:
65e460690139 [form, entity] refactor '__linkto', now handled by the entity form, not the entity itself. Closes #1931543
Florent Cayré <florent.cayre@gmail.com>
parents: 7756
diff changeset
  1118
                rsetsize = limit - len(result)
65e460690139 [form, entity] refactor '__linkto', now handled by the entity form, not the entity itself. Closes #1931543
Florent Cayré <florent.cayre@gmail.com>
parents: 7756
diff changeset
  1119
            result += self._relvoc_unrelated(form, objtype, rsetsize, done)
65e460690139 [form, entity] refactor '__linkto', now handled by the entity form, not the entity itself. Closes #1931543
Florent Cayré <florent.cayre@gmail.com>
parents: 7756
diff changeset
  1120
            if limit is not None and len(result) >= limit:
65e460690139 [form, entity] refactor '__linkto', now handled by the entity form, not the entity itself. Closes #1931543
Florent Cayré <florent.cayre@gmail.com>
parents: 7756
diff changeset
  1121
                break
65e460690139 [form, entity] refactor '__linkto', now handled by the entity form, not the entity itself. Closes #1931543
Florent Cayré <florent.cayre@gmail.com>
parents: 7756
diff changeset
  1122
        return result
65e460690139 [form, entity] refactor '__linkto', now handled by the entity form, not the entity itself. Closes #1931543
Florent Cayré <florent.cayre@gmail.com>
parents: 7756
diff changeset
  1123
65e460690139 [form, entity] refactor '__linkto', now handled by the entity form, not the entity itself. Closes #1931543
Florent Cayré <florent.cayre@gmail.com>
parents: 7756
diff changeset
  1124
    def _relvoc_unrelated(self, form, targettype, limit, done):
65e460690139 [form, entity] refactor '__linkto', now handled by the entity form, not the entity itself. Closes #1931543
Florent Cayré <florent.cayre@gmail.com>
parents: 7756
diff changeset
  1125
        """return unrelated entities for a given relation and target entity type
65e460690139 [form, entity] refactor '__linkto', now handled by the entity form, not the entity itself. Closes #1931543
Florent Cayré <florent.cayre@gmail.com>
parents: 7756
diff changeset
  1126
        for use in vocabulary
65e460690139 [form, entity] refactor '__linkto', now handled by the entity form, not the entity itself. Closes #1931543
Florent Cayré <florent.cayre@gmail.com>
parents: 7756
diff changeset
  1127
        """
65e460690139 [form, entity] refactor '__linkto', now handled by the entity form, not the entity itself. Closes #1931543
Florent Cayré <florent.cayre@gmail.com>
parents: 7756
diff changeset
  1128
        if done is None:
65e460690139 [form, entity] refactor '__linkto', now handled by the entity form, not the entity itself. Closes #1931543
Florent Cayré <florent.cayre@gmail.com>
parents: 7756
diff changeset
  1129
            done = set()
65e460690139 [form, entity] refactor '__linkto', now handled by the entity form, not the entity itself. Closes #1931543
Florent Cayré <florent.cayre@gmail.com>
parents: 7756
diff changeset
  1130
        res = []
65e460690139 [form, entity] refactor '__linkto', now handled by the entity form, not the entity itself. Closes #1931543
Florent Cayré <florent.cayre@gmail.com>
parents: 7756
diff changeset
  1131
        entity = form.edited_entity
7973
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7894
diff changeset
  1132
        for entity in entity.unrelated(self.name, targettype, self.role, limit,
64639bc94e25 [entity] restrict creation form field vocabulary using __linkto information (closes #1799997)
Florent Cayré <florent.cayre@gmail.com>
parents: 7894
diff changeset
  1133
                                       lt_infos=form.linked_to).entities():
7875
65e460690139 [form, entity] refactor '__linkto', now handled by the entity form, not the entity itself. Closes #1931543
Florent Cayré <florent.cayre@gmail.com>
parents: 7756
diff changeset
  1134
            if entity.eid in done:
65e460690139 [form, entity] refactor '__linkto', now handled by the entity form, not the entity itself. Closes #1931543
Florent Cayré <florent.cayre@gmail.com>
parents: 7756
diff changeset
  1135
                continue
65e460690139 [form, entity] refactor '__linkto', now handled by the entity form, not the entity itself. Closes #1931543
Florent Cayré <florent.cayre@gmail.com>
parents: 7756
diff changeset
  1136
            done.add(entity.eid)
10696
4ba4be5553cf [py3k] unicode vs str vs bytes vs the world
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10612
diff changeset
  1137
            res.append((entity.view('combobox'), text_type(entity.eid)))
7875
65e460690139 [form, entity] refactor '__linkto', now handled by the entity form, not the entity itself. Closes #1931543
Florent Cayré <florent.cayre@gmail.com>
parents: 7756
diff changeset
  1138
        return res
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
  1139
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
  1140
    def format_single_value(self, req, value):
10696
4ba4be5553cf [py3k] unicode vs str vs bytes vs the world
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10612
diff changeset
  1141
        return text_type(value)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
  1142
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
  1143
    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
  1144
        """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
  1145
        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
  1146
            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
  1147
        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
  1148
            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
  1149
            # 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
  1150
            # 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
  1151
            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
  1152
                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
  1153
            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
  1154
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
  1155
    def _process_form_value(self, form):
4110
8728d8c95985 [mq]: fix_for_forms
Arthur Lutz <arthur.lutz@logilab.fr>
parents: 4101
diff changeset
  1156
        """process posted form and return correctly typed value"""
8728d8c95985 [mq]: fix_for_forms
Arthur Lutz <arthur.lutz@logilab.fr>
parents: 4101
diff changeset
  1157
        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
  1158
        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
  1159
        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
  1160
            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
  1161
        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
  1162
            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
  1163
        eids = set()
9179
570208f74a84 [editcontrollers] Ensure entities are created in an order satisfying schema constraints. Closes #3031719
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8695
diff changeset
  1164
        rschema = form._cw.vreg.schema.rschema(self.name)
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
  1165
        for eid in values:
4227
39f01be4a6c5 should skip INTERNAL_FIELD_VALUE
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4226
diff changeset
  1166
            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
  1167
                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
  1168
            typed_eid = form.actual_eid(eid)
9179
570208f74a84 [editcontrollers] Ensure entities are created in an order satisfying schema constraints. Closes #3031719
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8695
diff changeset
  1169
            # if entity doesn't exist yet
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
  1170
            if typed_eid is None:
9179
570208f74a84 [editcontrollers] Ensure entities are created in an order satisfying schema constraints. Closes #3031719
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8695
diff changeset
  1171
                # inlined relations of to-be-created **subject entities** have
570208f74a84 [editcontrollers] Ensure entities are created in an order satisfying schema constraints. Closes #3031719
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8695
diff changeset
  1172
                # to be handled separatly
570208f74a84 [editcontrollers] Ensure entities are created in an order satisfying schema constraints. Closes #3031719
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8695
diff changeset
  1173
                if self.role == 'object' and rschema.inlined:
570208f74a84 [editcontrollers] Ensure entities are created in an order satisfying schema constraints. Closes #3031719
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8695
diff changeset
  1174
                    form._cw.data['pending_inlined'][eid].add( (form, self) )
570208f74a84 [editcontrollers] Ensure entities are created in an order satisfying schema constraints. Closes #3031719
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8695
diff changeset
  1175
                else:
570208f74a84 [editcontrollers] Ensure entities are created in an order satisfying schema constraints. Closes #3031719
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8695
diff changeset
  1176
                    form._cw.data['pending_others'].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
  1177
                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
  1178
            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
  1179
        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
  1180
9213
312062f53981 [inlined form field] fix regression introduced in 3.16.4/570208f74a84. Closes #3064653
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 9179
diff changeset
  1181
    @staticmethod
312062f53981 [inlined form field] fix regression introduced in 3.16.4/570208f74a84. Closes #3064653
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 9179
diff changeset
  1182
    def no_value(value):
312062f53981 [inlined form field] fix regression introduced in 3.16.4/570208f74a84. Closes #3064653
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 9179
diff changeset
  1183
        """return True if the value can be considered as no value for the field"""
312062f53981 [inlined form field] fix regression introduced in 3.16.4/570208f74a84. Closes #3064653
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 9179
diff changeset
  1184
        # value is None is the 'not yet ready value, consider the empty set
312062f53981 [inlined form field] fix regression introduced in 3.16.4/570208f74a84. Closes #3064653
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 9179
diff changeset
  1185
        return value is not None and not value
312062f53981 [inlined form field] fix regression introduced in 3.16.4/570208f74a84. Closes #3064653
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 9179
diff changeset
  1186
2523
1d245fbbeb90 some new field/widgets classes: CompoundField, IntervalWidget, HorizontalLayoutWidget
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2522
diff changeset
  1187
5057
d1bd50ae0edd [form] consider autoform_field_kwargs for meta fields; allow required customization
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5038
diff changeset
  1188
_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
  1189
8666
1dd655788ece make ui configurations selectable (closes #2406609)
Florent Cayré <florent.cayre@logilab.fr>
parents: 8665
diff changeset
  1190
def guess_field(eschema, rschema, role='subject', req=None, **kwargs):
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
  1191
    """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
  1192
    (`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
  1193
    (`role`).
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
  1194
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
  1195
    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
  1196
    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
  1197
    """
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
  1198
    fieldclass = None
4014
24f7d7eb4c23 yams api update
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3890
diff changeset
  1199
    rdef = eschema.rdef(rschema, role)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
  1200
    if role == 'subject':
4014
24f7d7eb4c23 yams api update
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3890
diff changeset
  1201
        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
  1202
        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
  1203
            if rdef.get('internationalizable'):
2095
897732d3ee5a avoid overriding specified values when guessing field
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2091
diff changeset
  1204
                kwargs.setdefault('internationalizable', True)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
  1205
    else:
4014
24f7d7eb4c23 yams api update
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3890
diff changeset
  1206
        targetschema = rdef.subject
4044
3876c894e018 card referenced later
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4023
diff changeset
  1207
    card = rdef.role_cardinality(role)
1095
6917ebe281e9 test and fix guess_field, some pylint fixes
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
  1208
    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
  1209
    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
  1210
    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
  1211
    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
  1212
    if role == 'object':
3574
f179ccbd13e6 [forms] fix generated label for fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3563
diff changeset
  1213
        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
  1214
    else:
3574
f179ccbd13e6 [forms] fix generated label for fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3563
diff changeset
  1215
        kwargs.setdefault('label', (eschema.type, rschema.type))
4014
24f7d7eb4c23 yams api update
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3890
diff changeset
  1216
    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
  1217
    if rschema.final:
1095
6917ebe281e9 test and fix guess_field, some pylint fixes
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
  1218
        fieldclass = FIELDS[targetschema]
6917ebe281e9 test and fix guess_field, some pylint fixes
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
  1219
        if fieldclass is StringField:
1104
58f27c3c0167 more guess_field tests and fixes
sylvain.thenault@logilab.fr
parents: 1101
diff changeset
  1220
            if eschema.has_metadata(rschema, 'format'):
58f27c3c0167 more guess_field tests and fixes
sylvain.thenault@logilab.fr
parents: 1101
diff changeset
  1221
                # use RichTextField instead of StringField if the attribute has
58f27c3c0167 more guess_field tests and fixes
sylvain.thenault@logilab.fr
parents: 1101
diff changeset
  1222
                # a "format" metadata. But getting information from constraints
58f27c3c0167 more guess_field tests and fixes
sylvain.thenault@logilab.fr
parents: 1101
diff changeset
  1223
                # may be useful anyway...
4014
24f7d7eb4c23 yams api update
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3890
diff changeset
  1224
                for cstr in rdef.constraints:
1104
58f27c3c0167 more guess_field tests and fixes
sylvain.thenault@logilab.fr
parents: 1101
diff changeset
  1225
                    if isinstance(cstr, StaticVocabularyConstraint):
58f27c3c0167 more guess_field tests and fixes
sylvain.thenault@logilab.fr
parents: 1101
diff changeset
  1226
                        raise Exception('rich text field with static vocabulary')
58f27c3c0167 more guess_field tests and fixes
sylvain.thenault@logilab.fr
parents: 1101
diff changeset
  1227
                return RichTextField(**kwargs)
1574
0c6dbb774f54 drop text field usage
sylvain.thenault@logilab.fr
parents: 1573
diff changeset
  1228
            # init StringField parameters according to constraints
4014
24f7d7eb4c23 yams api update
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3890
diff changeset
  1229
            for cstr in rdef.constraints:
1574
0c6dbb774f54 drop text field usage
sylvain.thenault@logilab.fr
parents: 1573
diff changeset
  1230
                if isinstance(cstr, StaticVocabularyConstraint):
1577
25b46db3cb81 should set field's choices
sylvain.thenault@logilab.fr
parents: 1574
diff changeset
  1231
                    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
  1232
                    break
4014
24f7d7eb4c23 yams api update
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3890
diff changeset
  1233
            for cstr in rdef.constraints:
1574
0c6dbb774f54 drop text field usage
sylvain.thenault@logilab.fr
parents: 1573
diff changeset
  1234
                if isinstance(cstr, SizeConstraint) and cstr.max is not None:
0c6dbb774f54 drop text field usage
sylvain.thenault@logilab.fr
parents: 1573
diff changeset
  1235
                    kwargs['max_length'] = cstr.max
0c6dbb774f54 drop text field usage
sylvain.thenault@logilab.fr
parents: 1573
diff changeset
  1236
            return StringField(**kwargs)
1104
58f27c3c0167 more guess_field tests and fixes
sylvain.thenault@logilab.fr
parents: 1101
diff changeset
  1237
        if fieldclass is FileField:
8666
1dd655788ece make ui configurations selectable (closes #2406609)
Florent Cayré <florent.cayre@logilab.fr>
parents: 8665
diff changeset
  1238
            if req:
1dd655788ece make ui configurations selectable (closes #2406609)
Florent Cayré <florent.cayre@logilab.fr>
parents: 8665
diff changeset
  1239
                aff_kwargs = req.vreg['uicfg'].select('autoform_field_kwargs', req)
1dd655788ece make ui configurations selectable (closes #2406609)
Florent Cayré <florent.cayre@logilab.fr>
parents: 8665
diff changeset
  1240
            else:
1dd655788ece make ui configurations selectable (closes #2406609)
Florent Cayré <florent.cayre@logilab.fr>
parents: 8665
diff changeset
  1241
                aff_kwargs = _AFF_KWARGS
4160
3fbdeef9a610 cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4159
diff changeset
  1242
            for metadata in KNOWN_METAATTRIBUTES:
1104
58f27c3c0167 more guess_field tests and fixes
sylvain.thenault@logilab.fr
parents: 1101
diff changeset
  1243
                metaschema = eschema.has_metadata(rschema, metadata)
58f27c3c0167 more guess_field tests and fixes
sylvain.thenault@logilab.fr
parents: 1101
diff changeset
  1244
                if metaschema is not None:
8666
1dd655788ece make ui configurations selectable (closes #2406609)
Florent Cayré <florent.cayre@logilab.fr>
parents: 8665
diff changeset
  1245
                    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
  1246
                    kwargs['%s_field' % metadata] = guess_field(eschema, metaschema,
8666
1dd655788ece make ui configurations selectable (closes #2406609)
Florent Cayré <florent.cayre@logilab.fr>
parents: 8665
diff changeset
  1247
                                                                req=req, **metakwargs)
1095
6917ebe281e9 test and fix guess_field, some pylint fixes
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
  1248
        return fieldclass(**kwargs)
6917ebe281e9 test and fix guess_field, some pylint fixes
sylvain.thenault@logilab.fr
parents: 1081
diff changeset
  1249
    return RelationField.fromcardinality(card, **kwargs)
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
  1250
1986
96c0e56cb0cf move widget selection's logic on fields
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
  1251
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
  1252
FIELDS = {
7166
dde161937d3e [time zone] support for TZDatetime and TZTime data type
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7070
diff changeset
  1253
    'String' :  StringField,
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
  1254
    'Bytes':    FileField,
7166
dde161937d3e [time zone] support for TZDatetime and TZTime data type
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7070
diff changeset
  1255
    'Password': PasswordField,
dde161937d3e [time zone] support for TZDatetime and TZTime data type
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7070
diff changeset
  1256
dde161937d3e [time zone] support for TZDatetime and TZTime data type
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7070
diff changeset
  1257
    'Boolean':  BooleanField,
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
  1258
    'Int':      IntField,
7460
2455cdbeadca [schema] support for BigInt type. Closes #1720995
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7231
diff changeset
  1259
    'BigInt':   BigIntField,
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
  1260
    'Float':    FloatField,
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
  1261
    'Decimal':  StringField,
7166
dde161937d3e [time zone] support for TZDatetime and TZTime data type
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7070
diff changeset
  1262
dde161937d3e [time zone] support for TZDatetime and TZTime data type
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7070
diff changeset
  1263
    'Date':       DateField,
dde161937d3e [time zone] support for TZDatetime and TZTime data type
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7070
diff changeset
  1264
    'Datetime':   DateTimeField,
dde161937d3e [time zone] support for TZDatetime and TZTime data type
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7070
diff changeset
  1265
    'TZDatetime': DateTimeField,
dde161937d3e [time zone] support for TZDatetime and TZTime data type
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7070
diff changeset
  1266
    'Time':       TimeField,
dde161937d3e [time zone] support for TZDatetime and TZTime data type
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7070
diff changeset
  1267
    'TZTime':     TimeField,
8248
9550555e4c26 Fix bug about missing Interval field (closes #1463996).
Damien Garaud <damien.garaud@logilab.fr>
parents: 8238
diff changeset
  1268
    'Interval':   TimeIntervalField,
1081
f2a85f52b9e5 move fields and widgets to their own module
sylvain.thenault@logilab.fr
parents:
diff changeset
  1269
    }