web/form.py
author Sylvain Thénault <sylvain.thenault@logilab.fr>
Fri, 25 Sep 2009 11:30:59 +0200
changeset 3475 9c07e6c48e35
parent 3451 6b46d73823f5
child 3524 a3431f4e2f40
permissions -rw-r--r--
[forms] drop FormMixIn deprecated in 3.2
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
     1
"""abstract form classes for CubicWeb web client
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
     2
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
     3
:organization: Logilab
1977
606923dff11b big bunch of copyright / docstring update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1962
diff changeset
     4
:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), license is LGPL v2.
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
     5
:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
1977
606923dff11b big bunch of copyright / docstring update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1962
diff changeset
     6
:license: GNU Lesser General Public License, v2.1 - http://www.gnu.org/licenses
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
     7
"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
     8
__docformat__ = "restructuredtext en"
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
     9
2656
a93ae0f6c0ad R [base classes] only AppObject remaning, no more AppRsetObject
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2005
diff changeset
    10
from cubicweb.appobject import AppObject
1133
8a409ea0c9ec more linting
sylvain.thenault@logilab.fr
parents: 1132
diff changeset
    11
from cubicweb.view import NOINDEX, NOFOLLOW
1097
611bacbbe001 pylint fixes, media definitions on form as well
sylvain.thenault@logilab.fr
parents: 1082
diff changeset
    12
from cubicweb.common import tags
2005
e8032965f37a turn every form class into appobject. They should not be instantiated manually anymore.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1995
diff changeset
    13
from cubicweb.web import stdmsgs, httpcache, formfields
1995
ec95eaa2b711 turn renderers into appobjects
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
    14
1097
611bacbbe001 pylint fixes, media definitions on form as well
sylvain.thenault@logilab.fr
parents: 1082
diff changeset
    15
1318
50e1a778c5ee new FormViewMixIn class, cleanup FormMixIn (to remove once cubes doesn't use it anymore)
sylvain.thenault@logilab.fr
parents: 1315
diff changeset
    16
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
    17
    """abstract form view mix-in"""
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    18
    category = 'form'
1995
ec95eaa2b711 turn renderers into appobjects
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
    19
    http_cache_manager = httpcache.NoHTTPCacheManager
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    20
    add_to_breadcrumbs = False
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1406
diff changeset
    21
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    22
    def html_headers(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    23
        """return a list of html headers (eg something to be inserted between
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    24
        <head> and </head> of the returned page
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    25
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    26
        by default forms are neither indexed nor followed
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    27
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    28
        return [NOINDEX, NOFOLLOW]
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1406
diff changeset
    29
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    30
    def linkable(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    31
        """override since forms are usually linked by an action,
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    32
        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
    33
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    34
        return False
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    35
1318
50e1a778c5ee new FormViewMixIn class, cleanup FormMixIn (to remove once cubes doesn't use it anymore)
sylvain.thenault@logilab.fr
parents: 1315
diff changeset
    36
3475
9c07e6c48e35 [forms] drop FormMixIn deprecated in 3.2
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3451
diff changeset
    37
class metafieldsform(type):
9c07e6c48e35 [forms] drop FormMixIn deprecated in 3.2
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3451
diff changeset
    38
    """metaclass for FieldsForm to retrieve fields defined as class attributes
9c07e6c48e35 [forms] drop FormMixIn deprecated in 3.2
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3451
diff changeset
    39
    and put them into a single ordered list: '_fields_'.
1318
50e1a778c5ee new FormViewMixIn class, cleanup FormMixIn (to remove once cubes doesn't use it anymore)
sylvain.thenault@logilab.fr
parents: 1315
diff changeset
    40
    """
3475
9c07e6c48e35 [forms] drop FormMixIn deprecated in 3.2
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3451
diff changeset
    41
    def __new__(mcs, name, bases, classdict):
9c07e6c48e35 [forms] drop FormMixIn deprecated in 3.2
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3451
diff changeset
    42
        allfields = []
9c07e6c48e35 [forms] drop FormMixIn deprecated in 3.2
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3451
diff changeset
    43
        for base in bases:
9c07e6c48e35 [forms] drop FormMixIn deprecated in 3.2
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3451
diff changeset
    44
            if hasattr(base, '_fields_'):
9c07e6c48e35 [forms] drop FormMixIn deprecated in 3.2
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3451
diff changeset
    45
                allfields += base._fields_
9c07e6c48e35 [forms] drop FormMixIn deprecated in 3.2
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3451
diff changeset
    46
        clsfields = (item for item in classdict.items()
9c07e6c48e35 [forms] drop FormMixIn deprecated in 3.2
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3451
diff changeset
    47
                     if isinstance(item[1], formfields.Field))
9c07e6c48e35 [forms] drop FormMixIn deprecated in 3.2
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3451
diff changeset
    48
        for fieldname, field in sorted(clsfields, key=lambda x: x[1].creation_rank):
9c07e6c48e35 [forms] drop FormMixIn deprecated in 3.2
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3451
diff changeset
    49
            if not field.name:
9c07e6c48e35 [forms] drop FormMixIn deprecated in 3.2
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3451
diff changeset
    50
                field.set_name(fieldname)
9c07e6c48e35 [forms] drop FormMixIn deprecated in 3.2
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3451
diff changeset
    51
            allfields.append(field)
9c07e6c48e35 [forms] drop FormMixIn deprecated in 3.2
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3451
diff changeset
    52
        classdict['_fields_'] = allfields
9c07e6c48e35 [forms] drop FormMixIn deprecated in 3.2
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3451
diff changeset
    53
        return super(metafieldsform, mcs).__new__(mcs, name, bases, classdict)
9c07e6c48e35 [forms] drop FormMixIn deprecated in 3.2
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3451
diff changeset
    54
9c07e6c48e35 [forms] drop FormMixIn deprecated in 3.2
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3451
diff changeset
    55
9c07e6c48e35 [forms] drop FormMixIn deprecated in 3.2
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3451
diff changeset
    56
class FieldNotFound(Exception):
9c07e6c48e35 [forms] drop FormMixIn deprecated in 3.2
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3451
diff changeset
    57
    """raised by field_by_name when a field with the given name has not been
9c07e6c48e35 [forms] drop FormMixIn deprecated in 3.2
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3451
diff changeset
    58
    found
9c07e6c48e35 [forms] drop FormMixIn deprecated in 3.2
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3451
diff changeset
    59
    """
9c07e6c48e35 [forms] drop FormMixIn deprecated in 3.2
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3451
diff changeset
    60
9c07e6c48e35 [forms] drop FormMixIn deprecated in 3.2
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3451
diff changeset
    61
class Form(AppObject):
9c07e6c48e35 [forms] drop FormMixIn deprecated in 3.2
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3451
diff changeset
    62
    __metaclass__ = metafieldsform
9c07e6c48e35 [forms] drop FormMixIn deprecated in 3.2
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3451
diff changeset
    63
    __registry__ = 'forms'
9c07e6c48e35 [forms] drop FormMixIn deprecated in 3.2
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3451
diff changeset
    64
9c07e6c48e35 [forms] drop FormMixIn deprecated in 3.2
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3451
diff changeset
    65
    def __init__(self, req, rset, **kwargs):
9c07e6c48e35 [forms] drop FormMixIn deprecated in 3.2
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3451
diff changeset
    66
        super(Form, self).__init__(req, rset=rset, **kwargs)
9c07e6c48e35 [forms] drop FormMixIn deprecated in 3.2
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3451
diff changeset
    67
        self.restore_previous_post(self.session_key())
1318
50e1a778c5ee new FormViewMixIn class, cleanup FormMixIn (to remove once cubes doesn't use it anymore)
sylvain.thenault@logilab.fr
parents: 1315
diff changeset
    68
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
    69
    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
    70
        """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
    71
        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
    72
        """
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3023
diff changeset
    73
        return '%s#%s' % (self._cw.url(), self.domid)
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
    74
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
    75
    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
    76
        # 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
    77
        # 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
    78
        # 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
    79
        # method on successful commit
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3023
diff changeset
    80
        forminfo = self._cw.get_session_data(sessionkey, pop=True)
1318
50e1a778c5ee new FormViewMixIn class, cleanup FormMixIn (to remove once cubes doesn't use it anymore)
sylvain.thenault@logilab.fr
parents: 1315
diff changeset
    81
        if forminfo:
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
    82
            # XXX remove req.data assigment once cw.web.widget is killed
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3023
diff changeset
    83
            self._cw.data['formvalues'] = self.form_previous_values = forminfo['values']
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3023
diff changeset
    84
            self._cw.data['formerrors'] = self.form_valerror = forminfo['errors']
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3023
diff changeset
    85
            self._cw.data['displayederrors'] = self.form_displayed_errors = set()
1318
50e1a778c5ee new FormViewMixIn class, cleanup FormMixIn (to remove once cubes doesn't use it anymore)
sylvain.thenault@logilab.fr
parents: 1315
diff changeset
    86
            # if some validation error occured on entity creation, we have to
50e1a778c5ee new FormViewMixIn class, cleanup FormMixIn (to remove once cubes doesn't use it anymore)
sylvain.thenault@logilab.fr
parents: 1315
diff changeset
    87
            # 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
    88
            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
    89
            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
    90
                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
    91
                    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
    92
                    break
50e1a778c5ee new FormViewMixIn class, cleanup FormMixIn (to remove once cubes doesn't use it anymore)
sylvain.thenault@logilab.fr
parents: 1315
diff changeset
    93
            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
    94
                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
    95
        else:
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
    96
            self.form_previous_values = {}
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
    97
            self.form_valerror = None