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