web/form.py
author Sylvain Thénault <sylvain.thenault@logilab.fr>
Tue, 25 Oct 2011 18:59:15 +0200
changeset 8022 1d9449663140
parent 7990 a673d1d9a738
child 8337 b5275e739a44
permissions -rw-r--r--
[test] specify X type, as this is not infered from NOT identity with rql#default
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
7432
cab99ccdb774 [ui messages, xss] Start migration towards use of _msgid instead of __message (prone to XSS injection) closes #1698245
Arthur Lutz <arthur.lutz@logilab.fr>
parents: 6109
diff changeset
     1
# copyright 2003-2011 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: 5369
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: 5369
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: 5369
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: 5369
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: 5369
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: 5369
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: 5369
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: 5369
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: 5369
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: 5369
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: 5369
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: 5369
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: 5369
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: 5369
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: 5369
diff changeset
    17
# with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
5588
377c9adfe81e [forms] refactor action handling to ease overriding while keeping action overrideable by instance (closes #969167)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5547
diff changeset
    18
"""abstract form classes for CubicWeb web client"""
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    19
__docformat__ = "restructuredtext en"
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    20
4224
5998df006968 refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4165
diff changeset
    21
from warnings import warn
5998df006968 refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4165
diff changeset
    22
3512
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
    23
from logilab.common.decorators import iclassmethod
4224
5998df006968 refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4165
diff changeset
    24
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
    25
2656
a93ae0f6c0ad R [base classes] only AppObject remaning, no more AppRsetObject
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2005
diff changeset
    26
from cubicweb.appobject import AppObject
1133
8a409ea0c9ec more linting
sylvain.thenault@logilab.fr
parents: 1132
diff changeset
    27
from cubicweb.view import NOINDEX, NOFOLLOW
5369
68c33344581c fix NameError
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 5368
diff changeset
    28
from cubicweb.web import httpcache, formfields, controller, formwidgets as fwdgs
1097
611bacbbe001 pylint fixes, media definitions on form as well
sylvain.thenault@logilab.fr
parents: 1082
diff changeset
    29
1318
50e1a778c5ee new FormViewMixIn class, cleanup FormMixIn (to remove once cubes doesn't use it anymore)
sylvain.thenault@logilab.fr
parents: 1315
diff changeset
    30
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
    31
    """abstract form view mix-in"""
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    32
    category = 'form'
1995
ec95eaa2b711 turn renderers into appobjects
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
    33
    http_cache_manager = httpcache.NoHTTPCacheManager
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    34
    add_to_breadcrumbs = False
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1406
diff changeset
    35
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    36
    def html_headers(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    37
        """return a list of html headers (eg something to be inserted between
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    38
        <head> and </head> of the returned page
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    39
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    40
        by default forms are neither indexed nor followed
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    41
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    42
        return [NOINDEX, NOFOLLOW]
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1406
diff changeset
    43
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    44
    def linkable(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    45
        """override since forms are usually linked by an action,
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    46
        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
    47
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    48
        return False
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    49
1318
50e1a778c5ee new FormViewMixIn class, cleanup FormMixIn (to remove once cubes doesn't use it anymore)
sylvain.thenault@logilab.fr
parents: 1315
diff changeset
    50
844
8ab6f64c3750 start django like forms
sylvain.thenault@logilab.fr
parents: 765
diff changeset
    51
###############################################################################
8ab6f64c3750 start django like forms
sylvain.thenault@logilab.fr
parents: 765
diff changeset
    52
8ab6f64c3750 start django like forms
sylvain.thenault@logilab.fr
parents: 765
diff changeset
    53
class metafieldsform(type):
1406
133476216f4a define self.fields before it is used ...
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 1400
diff changeset
    54
    """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
    55
    and put them into a single ordered list: '_fields_'.
1393
ff6758d7b96f cleanup, more docstring
sylvain.thenault@logilab.fr
parents: 1392
diff changeset
    56
    """
844
8ab6f64c3750 start django like forms
sylvain.thenault@logilab.fr
parents: 765
diff changeset
    57
    def __new__(mcs, name, bases, classdict):
8ab6f64c3750 start django like forms
sylvain.thenault@logilab.fr
parents: 765
diff changeset
    58
        allfields = []
8ab6f64c3750 start django like forms
sylvain.thenault@logilab.fr
parents: 765
diff changeset
    59
        for base in bases:
8ab6f64c3750 start django like forms
sylvain.thenault@logilab.fr
parents: 765
diff changeset
    60
            if hasattr(base, '_fields_'):
8ab6f64c3750 start django like forms
sylvain.thenault@logilab.fr
parents: 765
diff changeset
    61
                allfields += base._fields_
8ab6f64c3750 start django like forms
sylvain.thenault@logilab.fr
parents: 765
diff changeset
    62
        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
    63
                     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
    64
        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
    65
            if not field.name:
869
168ad6d424d1 form to edit multiple entities, use it in DeleteConfForm
sylvain.thenault@logilab.fr
parents: 867
diff changeset
    66
                field.set_name(fieldname)
844
8ab6f64c3750 start django like forms
sylvain.thenault@logilab.fr
parents: 765
diff changeset
    67
            allfields.append(field)
8ab6f64c3750 start django like forms
sylvain.thenault@logilab.fr
parents: 765
diff changeset
    68
        classdict['_fields_'] = allfields
8ab6f64c3750 start django like forms
sylvain.thenault@logilab.fr
parents: 765
diff changeset
    69
        return super(metafieldsform, mcs).__new__(mcs, name, bases, classdict)
1270
53f35db66f88 raise specific exception
sylvain.thenault@logilab.fr
parents: 1265
diff changeset
    70
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1406
diff changeset
    71
1270
53f35db66f88 raise specific exception
sylvain.thenault@logilab.fr
parents: 1265
diff changeset
    72
class FieldNotFound(Exception):
53f35db66f88 raise specific exception
sylvain.thenault@logilab.fr
parents: 1265
diff changeset
    73
    """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
    74
    found
53f35db66f88 raise specific exception
sylvain.thenault@logilab.fr
parents: 1265
diff changeset
    75
    """
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1406
diff changeset
    76
3475
9c07e6c48e35 [forms] drop FormMixIn deprecated in 3.2
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3451
diff changeset
    77
class Form(AppObject):
844
8ab6f64c3750 start django like forms
sylvain.thenault@logilab.fr
parents: 765
diff changeset
    78
    __metaclass__ = metafieldsform
1047
21d4d5e6aa45 make forms selectable (appobject)
sylvain.thenault@logilab.fr
parents: 1032
diff changeset
    79
    __registry__ = 'forms'
3512
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
    80
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
    81
    parent_form = None
3998
94cc7cad3d2d backport stable into default
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3524 3925
diff changeset
    82
    force_session_key = None
4668
9f82f81bf13d [form] fix #719285, due to multiple calls to restore_previous_post, by proper refactorings
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
    83
    domid = 'form'
9f82f81bf13d [form] fix #719285, due to multiple calls to restore_previous_post, by proper refactorings
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
    84
    copy_nav_params = False
7584
e1881933f366 [form, controller] closes #1787233: form should provide a method to process posted content
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7432
diff changeset
    85
    control_fields = set( ('__form_id', '__errorurl', '__domid',
e1881933f366 [form, controller] closes #1787233: form should provide a method to process posted content
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7432
diff changeset
    86
                           '__redirectpath', '_cwmsgid', '__message',
e1881933f366 [form, controller] closes #1787233: form should provide a method to process posted content
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7432
diff changeset
    87
                           ) )
3512
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
    88
4668
9f82f81bf13d [form] fix #719285, due to multiple calls to restore_previous_post, by proper refactorings
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
    89
    def __init__(self, req, rset=None, row=None, col=None,
9f82f81bf13d [form] fix #719285, due to multiple calls to restore_previous_post, by proper refactorings
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
    90
                 submitmsg=None, mainform=True, **kwargs):
9f82f81bf13d [form] fix #719285, due to multiple calls to restore_previous_post, by proper refactorings
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
    91
        super(Form, self).__init__(req, rset=rset, row=row, col=col)
9f82f81bf13d [form] fix #719285, due to multiple calls to restore_previous_post, by proper refactorings
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
    92
        self.fields = list(self.__class__._fields_)
4683
c375d50eaad3 [form] only set __form_id for the main form, not for sub-forms. Should fix regression introduced by 4668:9f82f81bf13d
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4668
diff changeset
    93
        if mainform:
c375d50eaad3 [form] only set __form_id for the main form, not for sub-forms. Should fix regression introduced by 4668:9f82f81bf13d
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4668
diff changeset
    94
            self.add_hidden(u'__form_id', kwargs.pop('formvid', self.__regid__))
4668
9f82f81bf13d [form] fix #719285, due to multiple calls to restore_previous_post, by proper refactorings
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
    95
        for key, val in kwargs.iteritems():
9f82f81bf13d [form] fix #719285, due to multiple calls to restore_previous_post, by proper refactorings
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
    96
            if key in controller.NAV_FORM_PARAMETERS:
9f82f81bf13d [form] fix #719285, due to multiple calls to restore_previous_post, by proper refactorings
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
    97
                self.add_hidden(key, val)
9f82f81bf13d [form] fix #719285, due to multiple calls to restore_previous_post, by proper refactorings
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
    98
            elif key == 'redirect_path':
9f82f81bf13d [form] fix #719285, due to multiple calls to restore_previous_post, by proper refactorings
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
    99
                self.add_hidden(u'__redirectpath', val)
9f82f81bf13d [form] fix #719285, due to multiple calls to restore_previous_post, by proper refactorings
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   100
            elif hasattr(self.__class__, key) and not key[0] == '_':
9f82f81bf13d [form] fix #719285, due to multiple calls to restore_previous_post, by proper refactorings
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   101
                setattr(self, key, val)
9f82f81bf13d [form] fix #719285, due to multiple calls to restore_previous_post, by proper refactorings
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   102
            else:
9f82f81bf13d [form] fix #719285, due to multiple calls to restore_previous_post, by proper refactorings
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   103
                self.cw_extra_kwargs[key] = val
9f82f81bf13d [form] fix #719285, due to multiple calls to restore_previous_post, by proper refactorings
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   104
            # skip other parameters, usually given for selection
9f82f81bf13d [form] fix #719285, due to multiple calls to restore_previous_post, by proper refactorings
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   105
            # (else write a custom class to handle them)
9f82f81bf13d [form] fix #719285, due to multiple calls to restore_previous_post, by proper refactorings
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   106
        if mainform:
9f82f81bf13d [form] fix #719285, due to multiple calls to restore_previous_post, by proper refactorings
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   107
            self.add_hidden(u'__errorurl', self.session_key())
9f82f81bf13d [form] fix #719285, due to multiple calls to restore_previous_post, by proper refactorings
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   108
            self.add_hidden(u'__domid', self.domid)
9f82f81bf13d [form] fix #719285, due to multiple calls to restore_previous_post, by proper refactorings
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   109
            self.restore_previous_post(self.session_key())
9f82f81bf13d [form] fix #719285, due to multiple calls to restore_previous_post, by proper refactorings
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   110
        # XXX why do we need two different variables (mainform and copy_nav_params ?)
9f82f81bf13d [form] fix #719285, due to multiple calls to restore_previous_post, by proper refactorings
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   111
        if self.copy_nav_params:
9f82f81bf13d [form] fix #719285, due to multiple calls to restore_previous_post, by proper refactorings
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   112
            for param in controller.NAV_FORM_PARAMETERS:
9f82f81bf13d [form] fix #719285, due to multiple calls to restore_previous_post, by proper refactorings
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   113
                if not param in kwargs:
9f82f81bf13d [form] fix #719285, due to multiple calls to restore_previous_post, by proper refactorings
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   114
                    value = req.form.get(param)
9f82f81bf13d [form] fix #719285, due to multiple calls to restore_previous_post, by proper refactorings
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   115
                    if value:
9f82f81bf13d [form] fix #719285, due to multiple calls to restore_previous_post, by proper refactorings
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   116
                        self.add_hidden(param, value)
9f82f81bf13d [form] fix #719285, due to multiple calls to restore_previous_post, by proper refactorings
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   117
        if submitmsg is not None:
7432
cab99ccdb774 [ui messages, xss] Start migration towards use of _msgid instead of __message (prone to XSS injection) closes #1698245
Arthur Lutz <arthur.lutz@logilab.fr>
parents: 6109
diff changeset
   118
            self.set_message(submitmsg)
cab99ccdb774 [ui messages, xss] Start migration towards use of _msgid instead of __message (prone to XSS injection) closes #1698245
Arthur Lutz <arthur.lutz@logilab.fr>
parents: 6109
diff changeset
   119
cab99ccdb774 [ui messages, xss] Start migration towards use of _msgid instead of __message (prone to XSS injection) closes #1698245
Arthur Lutz <arthur.lutz@logilab.fr>
parents: 6109
diff changeset
   120
    def set_message(self, submitmsg):
cab99ccdb774 [ui messages, xss] Start migration towards use of _msgid instead of __message (prone to XSS injection) closes #1698245
Arthur Lutz <arthur.lutz@logilab.fr>
parents: 6109
diff changeset
   121
        """sets a submitmsg if exists, using _cwmsgid mechanism """
cab99ccdb774 [ui messages, xss] Start migration towards use of _msgid instead of __message (prone to XSS injection) closes #1698245
Arthur Lutz <arthur.lutz@logilab.fr>
parents: 6109
diff changeset
   122
        cwmsgid = self._cw.set_redirect_message(submitmsg)
cab99ccdb774 [ui messages, xss] Start migration towards use of _msgid instead of __message (prone to XSS injection) closes #1698245
Arthur Lutz <arthur.lutz@logilab.fr>
parents: 6109
diff changeset
   123
        self.add_hidden(u'_cwmsgid', cwmsgid)
3512
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   124
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   125
    @property
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   126
    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
   127
        """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
   128
        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
   129
            return self
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   130
        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
   131
3998
94cc7cad3d2d backport stable into default
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3524 3925
diff changeset
   132
    @property
4224
5998df006968 refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4165
diff changeset
   133
    def form_valerror(self):
5998df006968 refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4165
diff changeset
   134
        """the validation error exception if any"""
5998df006968 refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4165
diff changeset
   135
        if self.parent_form is None:
5358
d4d294610ee7 [forms] no crash if restore_previous_post has not be called, has in report bug form in management.py for instance
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5223
diff changeset
   136
            # unset if restore_previous_post has not be called
d4d294610ee7 [forms] no crash if restore_previous_post has not be called, has in report bug form in management.py for instance
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5223
diff changeset
   137
            return getattr(self, '_form_valerror', None)
4224
5998df006968 refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4165
diff changeset
   138
        return self.parent_form.form_valerror
5998df006968 refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4165
diff changeset
   139
5998df006968 refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4165
diff changeset
   140
    @property
3998
94cc7cad3d2d backport stable into default
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3524 3925
diff changeset
   141
    def form_previous_values(self):
4224
5998df006968 refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4165
diff changeset
   142
        """previously posted values (on validation error)"""
3998
94cc7cad3d2d backport stable into default
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3524 3925
diff changeset
   143
        if self.parent_form is None:
5358
d4d294610ee7 [forms] no crash if restore_previous_post has not be called, has in report bug form in management.py for instance
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5223
diff changeset
   144
            # unset if restore_previous_post has not be called
d4d294610ee7 [forms] no crash if restore_previous_post has not be called, has in report bug form in management.py for instance
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5223
diff changeset
   145
            return getattr(self, '_form_previous_values', {})
3998
94cc7cad3d2d backport stable into default
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3524 3925
diff changeset
   146
        return self.parent_form.form_previous_values
94cc7cad3d2d backport stable into default
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3524 3925
diff changeset
   147
3512
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   148
    @iclassmethod
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   149
    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
   150
        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
   151
            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
   152
        else:
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   153
            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
   154
        return fields
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   155
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   156
    @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
   157
    def field_by_name(cls_or_self, name, role=None):
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   158
        """Return field with the given name and role.
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   159
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   160
        Raise :exc:`FieldNotFound` if the field can't be found.
3512
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   161
        """
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   162
        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
   163
            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
   164
                return field
4235
49eb7e87d36d specify name *and* role when raising FieldNotFound helps debugging
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4224
diff changeset
   165
        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
   166
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   167
    @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
   168
    def fields_by_name(cls_or_self, name, role=None):
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   169
        """Return a list of fields with the given name and role."""
3512
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   170
        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
   171
                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
   172
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   173
    @iclassmethod
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   174
    def remove_field(cls_or_self, field):
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   175
        """Remove the given field."""
3512
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   176
        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
   177
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   178
    @iclassmethod
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   179
    def append_field(cls_or_self, field):
5368
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   180
        """Append the given field."""
3512
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   181
        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
   182
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   183
    @iclassmethod
5367
4176a50c81c9 [form] small api cleanup and refactoring before documenting the form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4779
diff changeset
   184
    def insert_field_before(cls_or_self, field, name, role=None):
4176a50c81c9 [form] small api cleanup and refactoring before documenting the form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4779
diff changeset
   185
        """Insert the given field before the field of given name and role."""
4176a50c81c9 [form] small api cleanup and refactoring before documenting the form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4779
diff changeset
   186
        bfield = cls_or_self.field_by_name(name, role)
3512
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   187
        fields = cls_or_self._fieldsattr()
5367
4176a50c81c9 [form] small api cleanup and refactoring before documenting the form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4779
diff changeset
   188
        fields.insert(fields.index(bfield), field)
4176a50c81c9 [form] small api cleanup and refactoring before documenting the form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4779
diff changeset
   189
4176a50c81c9 [form] small api cleanup and refactoring before documenting the form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4779
diff changeset
   190
    @iclassmethod
4176a50c81c9 [form] small api cleanup and refactoring before documenting the form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4779
diff changeset
   191
    def insert_field_after(cls_or_self, field, name, role=None):
4176a50c81c9 [form] small api cleanup and refactoring before documenting the form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4779
diff changeset
   192
        """Insert the given field after the field of given name and role."""
4176a50c81c9 [form] small api cleanup and refactoring before documenting the form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4779
diff changeset
   193
        afield = cls_or_self.field_by_name(name, role)
4176a50c81c9 [form] small api cleanup and refactoring before documenting the form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4779
diff changeset
   194
        fields = cls_or_self._fieldsattr()
4176a50c81c9 [form] small api cleanup and refactoring before documenting the form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4779
diff changeset
   195
        fields.insert(fields.index(afield)+1, field)
3512
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   196
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   197
    @iclassmethod
5367
4176a50c81c9 [form] small api cleanup and refactoring before documenting the form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4779
diff changeset
   198
    def add_hidden(cls_or_self, name, value=None, **kwargs):
4176a50c81c9 [form] small api cleanup and refactoring before documenting the form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4779
diff changeset
   199
        """Append an hidden field to the form. `name`, `value` and extra keyword
4176a50c81c9 [form] small api cleanup and refactoring before documenting the form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4779
diff changeset
   200
        arguments will be given to the field constructor. The inserted field is
4176a50c81c9 [form] small api cleanup and refactoring before documenting the form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4779
diff changeset
   201
        returned.
4176a50c81c9 [form] small api cleanup and refactoring before documenting the form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4779
diff changeset
   202
        """
4176a50c81c9 [form] small api cleanup and refactoring before documenting the form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4779
diff changeset
   203
        kwargs.setdefault('ignore_req_params', True)
4176a50c81c9 [form] small api cleanup and refactoring before documenting the form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4779
diff changeset
   204
        kwargs.setdefault('widget', fwdgs.HiddenInput)
4176a50c81c9 [form] small api cleanup and refactoring before documenting the form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4779
diff changeset
   205
        field = formfields.StringField(name=name, value=value, **kwargs)
4176a50c81c9 [form] small api cleanup and refactoring before documenting the form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4779
diff changeset
   206
        if 'id' in kwargs:
4176a50c81c9 [form] small api cleanup and refactoring before documenting the form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4779
diff changeset
   207
            # by default, hidden input don't set id attribute. If one is
4176a50c81c9 [form] small api cleanup and refactoring before documenting the form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4779
diff changeset
   208
            # explicitly specified, ensure it will be set
4176a50c81c9 [form] small api cleanup and refactoring before documenting the form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4779
diff changeset
   209
            field.widget.setdomid = True
4176a50c81c9 [form] small api cleanup and refactoring before documenting the form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4779
diff changeset
   210
        cls_or_self.append_field(field)
4176a50c81c9 [form] small api cleanup and refactoring before documenting the form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4779
diff changeset
   211
        return field
3524
a3431f4e2f40 backport stable branch
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3475 3512
diff changeset
   212
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
   213
    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
   214
        """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
   215
        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
   216
        """
3998
94cc7cad3d2d backport stable into default
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3524 3925
diff changeset
   217
        if self.force_session_key is None:
4082
c7117119e215 3.6 api update
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4023
diff changeset
   218
            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
   219
        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
   220
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
   221
    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
   222
        # 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
   223
        # 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
   224
        # 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
   225
        # method on successful commit
5223
6abd6e3599f4 #773448: refactor session and 'no connection' handling, by introducing proper web session. We should now be able to see page even when no anon is configured, and be redirected to the login form as soon as one tries to do a query.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4779
diff changeset
   226
        forminfo = self._cw.session.data.pop(sessionkey, None)
1318
50e1a778c5ee new FormViewMixIn class, cleanup FormMixIn (to remove once cubes doesn't use it anymore)
sylvain.thenault@logilab.fr
parents: 1315
diff changeset
   227
        if forminfo:
4224
5998df006968 refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4165
diff changeset
   228
            self._form_previous_values = forminfo['values']
5998df006968 refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4165
diff changeset
   229
            self._form_valerror = forminfo['error']
6109
47d9c0e0f7b7 integrate Celso's work on translation file: proper/complete spanish translation, fixed some typos in french translation, occured -> occurred fix in various places
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5588
diff changeset
   230
            # if some validation error occurred on entity creation, we have to
1318
50e1a778c5ee new FormViewMixIn class, cleanup FormMixIn (to remove once cubes doesn't use it anymore)
sylvain.thenault@logilab.fr
parents: 1315
diff changeset
   231
            # 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
   232
            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
   233
            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
   234
                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
   235
                    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
   236
                    break
50e1a778c5ee new FormViewMixIn class, cleanup FormMixIn (to remove once cubes doesn't use it anymore)
sylvain.thenault@logilab.fr
parents: 1315
diff changeset
   237
            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
   238
                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
   239
        else:
3998
94cc7cad3d2d backport stable into default
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3524 3925
diff changeset
   240
            self._form_previous_values = {}
94cc7cad3d2d backport stable into default
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3524 3925
diff changeset
   241
            self._form_valerror = None
4224
5998df006968 refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4165
diff changeset
   242
5998df006968 refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4165
diff changeset
   243
    def field_error(self, field):
5998df006968 refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4165
diff changeset
   244
        """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
   245
        if self.form_valerror:
5998df006968 refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4165
diff changeset
   246
            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
   247
                return None
5998df006968 refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4165
diff changeset
   248
            try:
5998df006968 refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4165
diff changeset
   249
                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
   250
            except KeyError:
5998df006968 refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4165
diff changeset
   251
                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
   252
                    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
   253
                         % self.form_valerror.__class__, DeprecationWarning)
5998df006968 refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4165
diff changeset
   254
                    return self.form_valerror.errors.pop(field.name)
5998df006968 refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4165
diff changeset
   255
        return None
5998df006968 refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4165
diff changeset
   256
5998df006968 refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4165
diff changeset
   257
    def remaining_errors(self):
5998df006968 refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4165
diff changeset
   258
        return sorted(self.form_valerror.errors.items())
5998df006968 refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4165
diff changeset
   259