web/form.py
author Sylvain Thénault <sylvain.thenault@logilab.fr>
Thu, 01 Aug 2013 13:58:48 +0200
branchstable
changeset 9273 f3795da61959
parent 8511 f15e90b914cd
child 10080 bc7c3b0f439b
permissions -rw-r--r--
[test] use assertCountEqual instead of assertItemsEqual
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):
8511
f15e90b914cd [web form] refactor Form.__init__ so that extra kwargs are set earlier in the process. Closes #2443040
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8337
diff changeset
    91
        # process kwargs first so we can properly pass them to Form and match
f15e90b914cd [web form] refactor Form.__init__ so that extra kwargs are set earlier in the process. Closes #2443040
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8337
diff changeset
    92
        # order expectation (ie cw_extra_kwargs populated almost first)
f15e90b914cd [web form] refactor Form.__init__ so that extra kwargs are set earlier in the process. Closes #2443040
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8337
diff changeset
    93
        hiddens, extrakw = self._process_kwargs(kwargs)
f15e90b914cd [web form] refactor Form.__init__ so that extra kwargs are set earlier in the process. Closes #2443040
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8337
diff changeset
    94
        # now call ancestor init
f15e90b914cd [web form] refactor Form.__init__ so that extra kwargs are set earlier in the process. Closes #2443040
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8337
diff changeset
    95
        super(Form, self).__init__(req, rset=rset, row=row, col=col, **extrakw)
f15e90b914cd [web form] refactor Form.__init__ so that extra kwargs are set earlier in the process. Closes #2443040
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8337
diff changeset
    96
        # then continue with further specific initialization
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
    97
        self.fields = list(self.__class__._fields_)
8511
f15e90b914cd [web form] refactor Form.__init__ so that extra kwargs are set earlier in the process. Closes #2443040
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8337
diff changeset
    98
        for key, val in hiddens:
f15e90b914cd [web form] refactor Form.__init__ so that extra kwargs are set earlier in the process. Closes #2443040
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8337
diff changeset
    99
            self.add_hidden(key, val)
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
   100
        if mainform:
8337
b5275e739a44 [form] add a new property telling if the form is being generated or posted. Closes #2262340
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7990
diff changeset
   101
            formid = kwargs.pop('formvid', self.__regid__)
b5275e739a44 [form] add a new property telling if the form is being generated or posted. Closes #2262340
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7990
diff changeset
   102
            self.add_hidden(u'__form_id', formid)
b5275e739a44 [form] add a new property telling if the form is being generated or posted. Closes #2262340
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7990
diff changeset
   103
            self._posting = self._cw.form.get('__form_id') == formid
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
   104
        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
   105
            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
   106
            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
   107
            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
   108
        # 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
   109
        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
   110
            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
   111
                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
   112
                    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
   113
                    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
   114
                        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
   115
        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
   116
            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
   117
8511
f15e90b914cd [web form] refactor Form.__init__ so that extra kwargs are set earlier in the process. Closes #2443040
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8337
diff changeset
   118
    def _process_kwargs(self, kwargs):
f15e90b914cd [web form] refactor Form.__init__ so that extra kwargs are set earlier in the process. Closes #2443040
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8337
diff changeset
   119
        hiddens = []
f15e90b914cd [web form] refactor Form.__init__ so that extra kwargs are set earlier in the process. Closes #2443040
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8337
diff changeset
   120
        extrakw = {}
f15e90b914cd [web form] refactor Form.__init__ so that extra kwargs are set earlier in the process. Closes #2443040
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8337
diff changeset
   121
        # search for navigation parameters and customization of existing
f15e90b914cd [web form] refactor Form.__init__ so that extra kwargs are set earlier in the process. Closes #2443040
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8337
diff changeset
   122
        # attributes; remaining stuff goes in extrakwargs
f15e90b914cd [web form] refactor Form.__init__ so that extra kwargs are set earlier in the process. Closes #2443040
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8337
diff changeset
   123
        for key, val in kwargs.iteritems():
f15e90b914cd [web form] refactor Form.__init__ so that extra kwargs are set earlier in the process. Closes #2443040
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8337
diff changeset
   124
            if key in controller.NAV_FORM_PARAMETERS:
f15e90b914cd [web form] refactor Form.__init__ so that extra kwargs are set earlier in the process. Closes #2443040
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8337
diff changeset
   125
                hiddens.append( (key, val) )
f15e90b914cd [web form] refactor Form.__init__ so that extra kwargs are set earlier in the process. Closes #2443040
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8337
diff changeset
   126
            elif key == 'redirect_path':
f15e90b914cd [web form] refactor Form.__init__ so that extra kwargs are set earlier in the process. Closes #2443040
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8337
diff changeset
   127
                hiddens.append( (u'__redirectpath', val) )
f15e90b914cd [web form] refactor Form.__init__ so that extra kwargs are set earlier in the process. Closes #2443040
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8337
diff changeset
   128
            elif hasattr(self.__class__, key) and not key[0] == '_':
f15e90b914cd [web form] refactor Form.__init__ so that extra kwargs are set earlier in the process. Closes #2443040
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8337
diff changeset
   129
                setattr(self, key, val)
f15e90b914cd [web form] refactor Form.__init__ so that extra kwargs are set earlier in the process. Closes #2443040
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8337
diff changeset
   130
            else:
f15e90b914cd [web form] refactor Form.__init__ so that extra kwargs are set earlier in the process. Closes #2443040
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8337
diff changeset
   131
                extrakw[key] = val
f15e90b914cd [web form] refactor Form.__init__ so that extra kwargs are set earlier in the process. Closes #2443040
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8337
diff changeset
   132
        return hiddens, extrakw
f15e90b914cd [web form] refactor Form.__init__ so that extra kwargs are set earlier in the process. Closes #2443040
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8337
diff changeset
   133
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
   134
    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
   135
        """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
   136
        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
   137
        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
   138
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   139
    @property
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   140
    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
   141
        """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
   142
        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
   143
            return self
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   144
        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
   145
3998
94cc7cad3d2d backport stable into default
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3524 3925
diff changeset
   146
    @property
4224
5998df006968 refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4165
diff changeset
   147
    def form_valerror(self):
5998df006968 refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4165
diff changeset
   148
        """the validation error exception if any"""
5998df006968 refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4165
diff changeset
   149
        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
   150
            # 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
   151
            return getattr(self, '_form_valerror', None)
4224
5998df006968 refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4165
diff changeset
   152
        return self.parent_form.form_valerror
5998df006968 refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4165
diff changeset
   153
5998df006968 refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4165
diff changeset
   154
    @property
3998
94cc7cad3d2d backport stable into default
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3524 3925
diff changeset
   155
    def form_previous_values(self):
4224
5998df006968 refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4165
diff changeset
   156
        """previously posted values (on validation error)"""
3998
94cc7cad3d2d backport stable into default
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3524 3925
diff changeset
   157
        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
   158
            # 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
   159
            return getattr(self, '_form_previous_values', {})
3998
94cc7cad3d2d backport stable into default
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3524 3925
diff changeset
   160
        return self.parent_form.form_previous_values
94cc7cad3d2d backport stable into default
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3524 3925
diff changeset
   161
8337
b5275e739a44 [form] add a new property telling if the form is being generated or posted. Closes #2262340
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7990
diff changeset
   162
    @property
b5275e739a44 [form] add a new property telling if the form is being generated or posted. Closes #2262340
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7990
diff changeset
   163
    def posting(self):
b5275e739a44 [form] add a new property telling if the form is being generated or posted. Closes #2262340
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7990
diff changeset
   164
        """return True if the form is being posted, False if it is being
b5275e739a44 [form] add a new property telling if the form is being generated or posted. Closes #2262340
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7990
diff changeset
   165
        generated.
b5275e739a44 [form] add a new property telling if the form is being generated or posted. Closes #2262340
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7990
diff changeset
   166
        """
b5275e739a44 [form] add a new property telling if the form is being generated or posted. Closes #2262340
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7990
diff changeset
   167
        # XXX check behaviour on regeneration after error
b5275e739a44 [form] add a new property telling if the form is being generated or posted. Closes #2262340
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7990
diff changeset
   168
        if self.parent_form is None:
b5275e739a44 [form] add a new property telling if the form is being generated or posted. Closes #2262340
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7990
diff changeset
   169
            return self._posting
b5275e739a44 [form] add a new property telling if the form is being generated or posted. Closes #2262340
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7990
diff changeset
   170
        return self.parent_form.posting
b5275e739a44 [form] add a new property telling if the form is being generated or posted. Closes #2262340
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7990
diff changeset
   171
3512
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   172
    @iclassmethod
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   173
    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
   174
        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
   175
            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
   176
        else:
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   177
            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
   178
        return fields
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   179
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   180
    @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
   181
    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
   182
        """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
   183
d321e4b62a10 [book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5367
diff changeset
   184
        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
   185
        """
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   186
        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
   187
            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
   188
                return field
4235
49eb7e87d36d specify name *and* role when raising FieldNotFound helps debugging
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4224
diff changeset
   189
        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
   190
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   191
    @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
   192
    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
   193
        """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
   194
        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
   195
                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
   196
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   197
    @iclassmethod
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   198
    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
   199
        """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
   200
        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
   201
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   202
    @iclassmethod
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   203
    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
   204
        """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
   205
        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
   206
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   207
    @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
   208
    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
   209
        """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
   210
        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
   211
        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
   212
        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
   213
4176a50c81c9 [form] small api cleanup and refactoring before documenting the form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4779
diff changeset
   214
    @iclassmethod
4176a50c81c9 [form] small api cleanup and refactoring before documenting the form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4779
diff changeset
   215
    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
   216
        """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
   217
        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
   218
        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
   219
        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
   220
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   221
    @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
   222
    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
   223
        """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
   224
        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
   225
        returned.
4176a50c81c9 [form] small api cleanup and refactoring before documenting the form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4779
diff changeset
   226
        """
4176a50c81c9 [form] small api cleanup and refactoring before documenting the form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4779
diff changeset
   227
        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
   228
        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
   229
        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
   230
        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
   231
            # 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
   232
            # 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
   233
            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
   234
        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
   235
        return field
3524
a3431f4e2f40 backport stable branch
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3475 3512
diff changeset
   236
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
   237
    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
   238
        """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
   239
        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
   240
        """
3998
94cc7cad3d2d backport stable into default
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3524 3925
diff changeset
   241
        if self.force_session_key is None:
4082
c7117119e215 3.6 api update
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4023
diff changeset
   242
            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
   243
        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
   244
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
   245
    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
   246
        # 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
   247
        # 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
   248
        # 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
   249
        # 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
   250
        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
   251
        if forminfo:
4224
5998df006968 refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4165
diff changeset
   252
            self._form_previous_values = forminfo['values']
5998df006968 refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4165
diff changeset
   253
            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
   254
            # 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
   255
            # 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
   256
            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
   257
            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
   258
                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
   259
                    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
   260
                    break
50e1a778c5ee new FormViewMixIn class, cleanup FormMixIn (to remove once cubes doesn't use it anymore)
sylvain.thenault@logilab.fr
parents: 1315
diff changeset
   261
            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
   262
                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
   263
        else:
3998
94cc7cad3d2d backport stable into default
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3524 3925
diff changeset
   264
            self._form_previous_values = {}
94cc7cad3d2d backport stable into default
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3524 3925
diff changeset
   265
            self._form_valerror = None
4224
5998df006968 refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4165
diff changeset
   266
5998df006968 refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4165
diff changeset
   267
    def field_error(self, field):
5998df006968 refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4165
diff changeset
   268
        """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
   269
        if self.form_valerror:
5998df006968 refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4165
diff changeset
   270
            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
   271
                return None
5998df006968 refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4165
diff changeset
   272
            try:
5998df006968 refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4165
diff changeset
   273
                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
   274
            except KeyError:
5998df006968 refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4165
diff changeset
   275
                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
   276
                    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
   277
                         % self.form_valerror.__class__, DeprecationWarning)
5998df006968 refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4165
diff changeset
   278
                    return self.form_valerror.errors.pop(field.name)
5998df006968 refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4165
diff changeset
   279
        return None
5998df006968 refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4165
diff changeset
   280
5998df006968 refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4165
diff changeset
   281
    def remaining_errors(self):
5998df006968 refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4165
diff changeset
   282
        return sorted(self.form_valerror.errors.items())
5998df006968 refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4165
diff changeset
   283