web/form.py
author Sylvain Thénault <sylvain.thenault@logilab.fr>
Thu, 18 Feb 2010 10:54:50 +0100
branchstable
changeset 4624 1b46d5ece0d5
parent 4252 6c4f109c2b03
child 4668 9f82f81bf13d
permissions -rw-r--r--
turn default logging threshold to warning (we usually want them), and log 'no schema for eid' pb using warning instead of error, so we see them in logs but not during migration
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
     1
"""abstract form classes for CubicWeb web client
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
     2
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
     3
:organization: Logilab
4212
ab6573088b4a update copyright: welcome 2010
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3925
diff changeset
     4
:copyright: 2001-2010 LOGILAB S.A. (Paris, FRANCE), license is LGPL v2.
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
     5
:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
1977
606923dff11b big bunch of copyright / docstring update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1962
diff changeset
     6
:license: GNU Lesser General Public License, v2.1 - http://www.gnu.org/licenses
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
     7
"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
     8
__docformat__ = "restructuredtext en"
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
     9
4224
5998df006968 refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4165
diff changeset
    10
from warnings import warn
5998df006968 refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4165
diff changeset
    11
3512
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
    12
from logilab.common.decorators import iclassmethod
4224
5998df006968 refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4165
diff changeset
    13
from logilab.common.deprecation import deprecated
3512
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
    14
2656
a93ae0f6c0ad R [base classes] only AppObject remaning, no more AppRsetObject
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2005
diff changeset
    15
from cubicweb.appobject import AppObject
1133
8a409ea0c9ec more linting
sylvain.thenault@logilab.fr
parents: 1132
diff changeset
    16
from cubicweb.view import NOINDEX, NOFOLLOW
4023
eae23c40627a drop common subpackage
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4003
diff changeset
    17
from cubicweb import tags
2005
e8032965f37a turn every form class into appobject. They should not be instantiated manually anymore.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1995
diff changeset
    18
from cubicweb.web import stdmsgs, httpcache, formfields
1995
ec95eaa2b711 turn renderers into appobjects
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
    19
1097
611bacbbe001 pylint fixes, media definitions on form as well
sylvain.thenault@logilab.fr
parents: 1082
diff changeset
    20
1318
50e1a778c5ee new FormViewMixIn class, cleanup FormMixIn (to remove once cubes doesn't use it anymore)
sylvain.thenault@logilab.fr
parents: 1315
diff changeset
    21
class FormViewMixIn(object):
50e1a778c5ee new FormViewMixIn class, cleanup FormMixIn (to remove once cubes doesn't use it anymore)
sylvain.thenault@logilab.fr
parents: 1315
diff changeset
    22
    """abstract form view mix-in"""
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    23
    category = 'form'
1995
ec95eaa2b711 turn renderers into appobjects
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
    24
    http_cache_manager = httpcache.NoHTTPCacheManager
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    25
    add_to_breadcrumbs = False
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1406
diff changeset
    26
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    27
    def html_headers(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    28
        """return a list of html headers (eg something to be inserted between
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    29
        <head> and </head> of the returned page
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    30
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    31
        by default forms are neither indexed nor followed
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    32
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    33
        return [NOINDEX, NOFOLLOW]
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1406
diff changeset
    34
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    35
    def linkable(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    36
        """override since forms are usually linked by an action,
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    37
        so we don't want them to be listed by appli.possible_views
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    38
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    39
        return False
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    40
1318
50e1a778c5ee new FormViewMixIn class, cleanup FormMixIn (to remove once cubes doesn't use it anymore)
sylvain.thenault@logilab.fr
parents: 1315
diff changeset
    41
844
8ab6f64c3750 start django like forms
sylvain.thenault@logilab.fr
parents: 765
diff changeset
    42
###############################################################################
8ab6f64c3750 start django like forms
sylvain.thenault@logilab.fr
parents: 765
diff changeset
    43
8ab6f64c3750 start django like forms
sylvain.thenault@logilab.fr
parents: 765
diff changeset
    44
class metafieldsform(type):
1406
133476216f4a define self.fields before it is used ...
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 1400
diff changeset
    45
    """metaclass for FieldsForm to retrieve fields defined as class attributes
133476216f4a define self.fields before it is used ...
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 1400
diff changeset
    46
    and put them into a single ordered list: '_fields_'.
1393
ff6758d7b96f cleanup, more docstring
sylvain.thenault@logilab.fr
parents: 1392
diff changeset
    47
    """
844
8ab6f64c3750 start django like forms
sylvain.thenault@logilab.fr
parents: 765
diff changeset
    48
    def __new__(mcs, name, bases, classdict):
8ab6f64c3750 start django like forms
sylvain.thenault@logilab.fr
parents: 765
diff changeset
    49
        allfields = []
8ab6f64c3750 start django like forms
sylvain.thenault@logilab.fr
parents: 765
diff changeset
    50
        for base in bases:
8ab6f64c3750 start django like forms
sylvain.thenault@logilab.fr
parents: 765
diff changeset
    51
            if hasattr(base, '_fields_'):
8ab6f64c3750 start django like forms
sylvain.thenault@logilab.fr
parents: 765
diff changeset
    52
                allfields += base._fields_
8ab6f64c3750 start django like forms
sylvain.thenault@logilab.fr
parents: 765
diff changeset
    53
        clsfields = (item for item in classdict.items()
2005
e8032965f37a turn every form class into appobject. They should not be instantiated manually anymore.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1995
diff changeset
    54
                     if isinstance(item[1], formfields.Field))
869
168ad6d424d1 form to edit multiple entities, use it in DeleteConfForm
sylvain.thenault@logilab.fr
parents: 867
diff changeset
    55
        for fieldname, field in sorted(clsfields, key=lambda x: x[1].creation_rank):
844
8ab6f64c3750 start django like forms
sylvain.thenault@logilab.fr
parents: 765
diff changeset
    56
            if not field.name:
869
168ad6d424d1 form to edit multiple entities, use it in DeleteConfForm
sylvain.thenault@logilab.fr
parents: 867
diff changeset
    57
                field.set_name(fieldname)
844
8ab6f64c3750 start django like forms
sylvain.thenault@logilab.fr
parents: 765
diff changeset
    58
            allfields.append(field)
8ab6f64c3750 start django like forms
sylvain.thenault@logilab.fr
parents: 765
diff changeset
    59
        classdict['_fields_'] = allfields
8ab6f64c3750 start django like forms
sylvain.thenault@logilab.fr
parents: 765
diff changeset
    60
        return super(metafieldsform, mcs).__new__(mcs, name, bases, classdict)
1270
53f35db66f88 raise specific exception
sylvain.thenault@logilab.fr
parents: 1265
diff changeset
    61
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1406
diff changeset
    62
1270
53f35db66f88 raise specific exception
sylvain.thenault@logilab.fr
parents: 1265
diff changeset
    63
class FieldNotFound(Exception):
53f35db66f88 raise specific exception
sylvain.thenault@logilab.fr
parents: 1265
diff changeset
    64
    """raised by field_by_name when a field with the given name has not been
53f35db66f88 raise specific exception
sylvain.thenault@logilab.fr
parents: 1265
diff changeset
    65
    found
53f35db66f88 raise specific exception
sylvain.thenault@logilab.fr
parents: 1265
diff changeset
    66
    """
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1406
diff changeset
    67
3475
9c07e6c48e35 [forms] drop FormMixIn deprecated in 3.2
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3451
diff changeset
    68
class Form(AppObject):
844
8ab6f64c3750 start django like forms
sylvain.thenault@logilab.fr
parents: 765
diff changeset
    69
    __metaclass__ = metafieldsform
1047
21d4d5e6aa45 make forms selectable (appobject)
sylvain.thenault@logilab.fr
parents: 1032
diff changeset
    70
    __registry__ = 'forms'
3512
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
    71
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
    72
    parent_form = None
3998
94cc7cad3d2d backport stable into default
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3524 3925
diff changeset
    73
    force_session_key = None
3512
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
    74
3475
9c07e6c48e35 [forms] drop FormMixIn deprecated in 3.2
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3451
diff changeset
    75
    def __init__(self, req, rset, **kwargs):
9c07e6c48e35 [forms] drop FormMixIn deprecated in 3.2
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3451
diff changeset
    76
        super(Form, self).__init__(req, rset=rset, **kwargs)
9c07e6c48e35 [forms] drop FormMixIn deprecated in 3.2
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3451
diff changeset
    77
        self.restore_previous_post(self.session_key())
3512
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
    78
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
    79
    @property
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
    80
    def root_form(self):
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
    81
        """return the root form"""
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
    82
        if self.parent_form is None:
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
    83
            return self
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
    84
        return self.parent_form.root_form
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
    85
3998
94cc7cad3d2d backport stable into default
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3524 3925
diff changeset
    86
    @property
4224
5998df006968 refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4165
diff changeset
    87
    def form_valerror(self):
5998df006968 refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4165
diff changeset
    88
        """the validation error exception if any"""
5998df006968 refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4165
diff changeset
    89
        if self.parent_form is None:
5998df006968 refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4165
diff changeset
    90
            return self._form_valerror
5998df006968 refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4165
diff changeset
    91
        return self.parent_form.form_valerror
5998df006968 refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4165
diff changeset
    92
5998df006968 refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4165
diff changeset
    93
    @property
3998
94cc7cad3d2d backport stable into default
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3524 3925
diff changeset
    94
    def form_previous_values(self):
4224
5998df006968 refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4165
diff changeset
    95
        """previously posted values (on validation error)"""
3998
94cc7cad3d2d backport stable into default
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3524 3925
diff changeset
    96
        if self.parent_form is None:
94cc7cad3d2d backport stable into default
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3524 3925
diff changeset
    97
            return self._form_previous_values
94cc7cad3d2d backport stable into default
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3524 3925
diff changeset
    98
        return self.parent_form.form_previous_values
94cc7cad3d2d backport stable into default
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3524 3925
diff changeset
    99
3512
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   100
    @iclassmethod
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   101
    def _fieldsattr(cls_or_self):
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   102
        if isinstance(cls_or_self, type):
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   103
            fields = cls_or_self._fields_
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   104
        else:
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   105
            fields = cls_or_self.fields
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   106
        return fields
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   107
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   108
    @iclassmethod
4165
eb9acad29407 proper field's role handling: may be 'subject' / 'object' *in case
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4082
diff changeset
   109
    def field_by_name(cls_or_self, name, role=None):
3512
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   110
        """return field with the given name and role.
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   111
        Raise FieldNotFound if the field can't be found.
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   112
        """
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   113
        for field in cls_or_self._fieldsattr():
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   114
            if field.name == name and field.role == role:
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   115
                return field
4235
49eb7e87d36d specify name *and* role when raising FieldNotFound helps debugging
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4224
diff changeset
   116
        raise FieldNotFound(name, role)
3512
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   117
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   118
    @iclassmethod
4165
eb9acad29407 proper field's role handling: may be 'subject' / 'object' *in case
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4082
diff changeset
   119
    def fields_by_name(cls_or_self, name, role=None):
3512
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   120
        """return a list of fields with the given name and role"""
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   121
        return [field for field in cls_or_self._fieldsattr()
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   122
                if field.name == name and field.role == role]
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   123
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   124
    @iclassmethod
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   125
    def remove_field(cls_or_self, field):
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   126
        """remove a field from form class or instance"""
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   127
        cls_or_self._fieldsattr().remove(field)
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   128
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   129
    @iclassmethod
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   130
    def append_field(cls_or_self, field):
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   131
        """append a field to form class or instance"""
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   132
        cls_or_self._fieldsattr().append(field)
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   133
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   134
    @iclassmethod
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   135
    def insert_field_before(cls_or_self, new_field, name, role='subject'):
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   136
        field = cls_or_self.field_by_name(name, role)
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   137
        fields = cls_or_self._fieldsattr()
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   138
        fields.insert(fields.index(field), new_field)
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   139
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   140
    @iclassmethod
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   141
    def insert_field_after(cls_or_self, new_field, name, role='subject'):
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   142
        field = cls_or_self.field_by_name(name, role)
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   143
        fields = cls_or_self._fieldsattr()
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   144
        fields.insert(fields.index(field)+1, new_field)
3524
a3431f4e2f40 backport stable branch
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3475 3512
diff changeset
   145
1525
cc2e2cbd7019 include dom id of the form in __errorurl in case there are multiple forms in a page
sylvain.thenault@logilab.fr
parents: 1519
diff changeset
   146
    def session_key(self):
cc2e2cbd7019 include dom id of the form in __errorurl in case there are multiple forms in a page
sylvain.thenault@logilab.fr
parents: 1519
diff changeset
   147
        """return the key that may be used to store / retreive data about a
cc2e2cbd7019 include dom id of the form in __errorurl in case there are multiple forms in a page
sylvain.thenault@logilab.fr
parents: 1519
diff changeset
   148
        previous post which failed because of a validation error
cc2e2cbd7019 include dom id of the form in __errorurl in case there are multiple forms in a page
sylvain.thenault@logilab.fr
parents: 1519
diff changeset
   149
        """
3998
94cc7cad3d2d backport stable into default
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3524 3925
diff changeset
   150
        if self.force_session_key is None:
4082
c7117119e215 3.6 api update
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4023
diff changeset
   151
            return '%s#%s' % (self._cw.url(), self.domid)
3998
94cc7cad3d2d backport stable into default
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3524 3925
diff changeset
   152
        return self.force_session_key
1525
cc2e2cbd7019 include dom id of the form in __errorurl in case there are multiple forms in a page
sylvain.thenault@logilab.fr
parents: 1519
diff changeset
   153
cc2e2cbd7019 include dom id of the form in __errorurl in case there are multiple forms in a page
sylvain.thenault@logilab.fr
parents: 1519
diff changeset
   154
    def restore_previous_post(self, sessionkey):
1318
50e1a778c5ee new FormViewMixIn class, cleanup FormMixIn (to remove once cubes doesn't use it anymore)
sylvain.thenault@logilab.fr
parents: 1315
diff changeset
   155
        # get validation session data which may have been previously set.
50e1a778c5ee new FormViewMixIn class, cleanup FormMixIn (to remove once cubes doesn't use it anymore)
sylvain.thenault@logilab.fr
parents: 1315
diff changeset
   156
        # deleting validation errors here breaks form reloading (errors are
50e1a778c5ee new FormViewMixIn class, cleanup FormMixIn (to remove once cubes doesn't use it anymore)
sylvain.thenault@logilab.fr
parents: 1315
diff changeset
   157
        # no more available), they have to be deleted by application's publish
50e1a778c5ee new FormViewMixIn class, cleanup FormMixIn (to remove once cubes doesn't use it anymore)
sylvain.thenault@logilab.fr
parents: 1315
diff changeset
   158
        # method on successful commit
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3023
diff changeset
   159
        forminfo = self._cw.get_session_data(sessionkey, pop=True)
1318
50e1a778c5ee new FormViewMixIn class, cleanup FormMixIn (to remove once cubes doesn't use it anymore)
sylvain.thenault@logilab.fr
parents: 1315
diff changeset
   160
        if forminfo:
4224
5998df006968 refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4165
diff changeset
   161
            self._form_previous_values = forminfo['values']
5998df006968 refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4165
diff changeset
   162
            self._form_valerror = forminfo['error']
1318
50e1a778c5ee new FormViewMixIn class, cleanup FormMixIn (to remove once cubes doesn't use it anymore)
sylvain.thenault@logilab.fr
parents: 1315
diff changeset
   163
            # if some validation error occured on entity creation, we have to
50e1a778c5ee new FormViewMixIn class, cleanup FormMixIn (to remove once cubes doesn't use it anymore)
sylvain.thenault@logilab.fr
parents: 1315
diff changeset
   164
            # get the original variable name from its attributed eid
1710
8c717cc0b353 refactor error handling: get validation error information from a form attribute instead of req.data to avoid pb when multiple forms are displayed
sylvain.thenault@logilab.fr
parents: 1701
diff changeset
   165
            foreid = self.form_valerror.entity
1318
50e1a778c5ee new FormViewMixIn class, cleanup FormMixIn (to remove once cubes doesn't use it anymore)
sylvain.thenault@logilab.fr
parents: 1315
diff changeset
   166
            for var, eid in forminfo['eidmap'].items():
50e1a778c5ee new FormViewMixIn class, cleanup FormMixIn (to remove once cubes doesn't use it anymore)
sylvain.thenault@logilab.fr
parents: 1315
diff changeset
   167
                if foreid == eid:
1710
8c717cc0b353 refactor error handling: get validation error information from a form attribute instead of req.data to avoid pb when multiple forms are displayed
sylvain.thenault@logilab.fr
parents: 1701
diff changeset
   168
                    self.form_valerror.eid = var
1318
50e1a778c5ee new FormViewMixIn class, cleanup FormMixIn (to remove once cubes doesn't use it anymore)
sylvain.thenault@logilab.fr
parents: 1315
diff changeset
   169
                    break
50e1a778c5ee new FormViewMixIn class, cleanup FormMixIn (to remove once cubes doesn't use it anymore)
sylvain.thenault@logilab.fr
parents: 1315
diff changeset
   170
            else:
1710
8c717cc0b353 refactor error handling: get validation error information from a form attribute instead of req.data to avoid pb when multiple forms are displayed
sylvain.thenault@logilab.fr
parents: 1701
diff changeset
   171
                self.form_valerror.eid = foreid
8c717cc0b353 refactor error handling: get validation error information from a form attribute instead of req.data to avoid pb when multiple forms are displayed
sylvain.thenault@logilab.fr
parents: 1701
diff changeset
   172
        else:
3998
94cc7cad3d2d backport stable into default
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3524 3925
diff changeset
   173
            self._form_previous_values = {}
94cc7cad3d2d backport stable into default
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3524 3925
diff changeset
   174
            self._form_valerror = None
4224
5998df006968 refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4165
diff changeset
   175
5998df006968 refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4165
diff changeset
   176
    def field_error(self, field):
5998df006968 refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4165
diff changeset
   177
        """return field's error if specified in current validation exception"""
5998df006968 refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4165
diff changeset
   178
        if self.form_valerror:
5998df006968 refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4165
diff changeset
   179
            if field.eidparam and self.edited_entity.eid != self.form_valerror.eid:
5998df006968 refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4165
diff changeset
   180
                return None
5998df006968 refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4165
diff changeset
   181
            try:
5998df006968 refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4165
diff changeset
   182
                return self.form_valerror.errors.pop(field.role_name())
5998df006968 refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4165
diff changeset
   183
            except KeyError:
5998df006968 refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4165
diff changeset
   184
                if field.role and field.name in self.form_valerror:
5998df006968 refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4165
diff changeset
   185
                    warn('%s: errors key of attribute/relation should be suffixed by "-<role>"'
5998df006968 refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4165
diff changeset
   186
                         % self.form_valerror.__class__, DeprecationWarning)
5998df006968 refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4165
diff changeset
   187
                    return self.form_valerror.errors.pop(field.name)
5998df006968 refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4165
diff changeset
   188
        return None
5998df006968 refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4165
diff changeset
   189
5998df006968 refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4165
diff changeset
   190
    def remaining_errors(self):
5998df006968 refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4165
diff changeset
   191
        return sorted(self.form_valerror.errors.items())
5998df006968 refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4165
diff changeset
   192
5998df006968 refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4165
diff changeset
   193
    @deprecated('[3.6] use form.field_error and/or new renderer.render_error method')
5998df006968 refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4165
diff changeset
   194
    def form_field_error(self, field):
5998df006968 refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4165
diff changeset
   195
        """return validation error for widget's field, if any"""
5998df006968 refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4165
diff changeset
   196
        err = self.field_error(field)
5998df006968 refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4165
diff changeset
   197
        if err:
5998df006968 refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4165
diff changeset
   198
            return u'<span class="error">%s</span>' % err
5998df006968 refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4165
diff changeset
   199
        return u''
5998df006968 refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4165
diff changeset
   200