web/form.py
author Sylvain Thénault <sylvain.thenault@logilab.fr>
Mon, 30 Nov 2009 10:24:01 +0100
branchstable
changeset 3947 8d06bce45c02
parent 3925 25d5830b9531
child 3998 94cc7cad3d2d
child 4212 ab6573088b4a
permissions -rw-r--r--
when one is adding an inline entity for a relation of a single card, the 'add a new xxx' link disappears. If the user then cancel the addition, we have to make this link appears back. This is done by giving add new link id to removeInlineForm.
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
3512
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
    10
from logilab.common.decorators import iclassmethod
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
    11
2656
a93ae0f6c0ad R [base classes] only AppObject remaning, no more AppRsetObject
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2005
diff changeset
    12
from cubicweb.appobject import AppObject
1133
8a409ea0c9ec more linting
sylvain.thenault@logilab.fr
parents: 1132
diff changeset
    13
from cubicweb.view import NOINDEX, NOFOLLOW
1097
611bacbbe001 pylint fixes, media definitions on form as well
sylvain.thenault@logilab.fr
parents: 1082
diff changeset
    14
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
    15
from cubicweb.web import stdmsgs, httpcache, formfields
1995
ec95eaa2b711 turn renderers into appobjects
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
    16
1097
611bacbbe001 pylint fixes, media definitions on form as well
sylvain.thenault@logilab.fr
parents: 1082
diff changeset
    17
1318
50e1a778c5ee new FormViewMixIn class, cleanup FormMixIn (to remove once cubes doesn't use it anymore)
sylvain.thenault@logilab.fr
parents: 1315
diff changeset
    18
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
    19
    """abstract form view mix-in"""
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    20
    category = 'form'
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    21
    controller = 'edit'
1995
ec95eaa2b711 turn renderers into appobjects
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
    22
    http_cache_manager = httpcache.NoHTTPCacheManager
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    23
    add_to_breadcrumbs = False
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1406
diff changeset
    24
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    25
    def html_headers(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    26
        """return a list of html headers (eg something to be inserted between
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    27
        <head> and </head> of the returned page
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    28
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    29
        by default forms are neither indexed nor followed
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    30
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    31
        return [NOINDEX, NOFOLLOW]
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1406
diff changeset
    32
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    33
    def linkable(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    34
        """override since forms are usually linked by an action,
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    35
        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
    36
        """
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    37
        return False
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    38
1318
50e1a778c5ee new FormViewMixIn class, cleanup FormMixIn (to remove once cubes doesn't use it anymore)
sylvain.thenault@logilab.fr
parents: 1315
diff changeset
    39
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1406
diff changeset
    40
# XXX should disappear
1318
50e1a778c5ee new FormViewMixIn class, cleanup FormMixIn (to remove once cubes doesn't use it anymore)
sylvain.thenault@logilab.fr
parents: 1315
diff changeset
    41
class FormMixIn(object):
50e1a778c5ee new FormViewMixIn class, cleanup FormMixIn (to remove once cubes doesn't use it anymore)
sylvain.thenault@logilab.fr
parents: 1315
diff changeset
    42
    """abstract form mix-in
50e1a778c5ee new FormViewMixIn class, cleanup FormMixIn (to remove once cubes doesn't use it anymore)
sylvain.thenault@logilab.fr
parents: 1315
diff changeset
    43
    XXX: you should inherit from this FIRST (obscure pb with super call)
50e1a778c5ee new FormViewMixIn class, cleanup FormMixIn (to remove once cubes doesn't use it anymore)
sylvain.thenault@logilab.fr
parents: 1315
diff changeset
    44
    """
3922
69020a7c234a refactor session_key (__errorurl) to handle cases where the form is generated throuhg an ajax call: in case of an entity form, return the entity's absolute url. Also allow to force session key value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3512
diff changeset
    45
    force_session_key = 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
    46
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
    47
    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
    48
        """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
    49
        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
    50
        """
3925
25d5830b9531 force_session_key default to None
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3923
diff changeset
    51
        if self.force_session_key is None:
3922
69020a7c234a refactor session_key (__errorurl) to handle cases where the form is generated throuhg an ajax call: in case of an entity form, return the entity's absolute url. Also allow to force session key value
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3512
diff changeset
    52
            return '%s#%s' % (self.req.url(), self.domid)
3925
25d5830b9531 force_session_key default to None
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3923
diff changeset
    53
        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
    54
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
    55
    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
    56
        # 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
    57
        # 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
    58
        # 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
    59
        # method on successful commit
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
    60
        forminfo = self.req.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
    61
        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
    62
            # XXX remove req.data assigment once cw.web.widget is killed
3923
be05eeeb2db1 fix previous post values handling (eg on validation error) for sub-forms
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3922
diff changeset
    63
            self.req.data['formvalues'] = self._form_previous_values = forminfo['values']
be05eeeb2db1 fix previous post values handling (eg on validation error) for sub-forms
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3922
diff changeset
    64
            self.req.data['formerrors'] = self._form_valerror = forminfo['errors']
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
    65
            self.req.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
    66
            # 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
    67
            # 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
    68
            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
    69
            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
    70
                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
    71
                    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
    72
                    break
50e1a778c5ee new FormViewMixIn class, cleanup FormMixIn (to remove once cubes doesn't use it anymore)
sylvain.thenault@logilab.fr
parents: 1315
diff changeset
    73
            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
    74
                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
    75
        else:
3923
be05eeeb2db1 fix previous post values handling (eg on validation error) for sub-forms
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3922
diff changeset
    76
            self._form_previous_values = {}
be05eeeb2db1 fix previous post values handling (eg on validation error) for sub-forms
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3922
diff changeset
    77
            self._form_valerror = None
be05eeeb2db1 fix previous post values handling (eg on validation error) for sub-forms
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3922
diff changeset
    78
be05eeeb2db1 fix previous post values handling (eg on validation error) for sub-forms
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3922
diff changeset
    79
    @property
be05eeeb2db1 fix previous post values handling (eg on validation error) for sub-forms
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3922
diff changeset
    80
    def form_previous_values(self):
be05eeeb2db1 fix previous post values handling (eg on validation error) for sub-forms
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3922
diff changeset
    81
        if self.parent_form is None:
be05eeeb2db1 fix previous post values handling (eg on validation error) for sub-forms
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3922
diff changeset
    82
            return self._form_previous_values
be05eeeb2db1 fix previous post values handling (eg on validation error) for sub-forms
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3922
diff changeset
    83
        return self.parent_form.form_previous_values
be05eeeb2db1 fix previous post values handling (eg on validation error) for sub-forms
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3922
diff changeset
    84
be05eeeb2db1 fix previous post values handling (eg on validation error) for sub-forms
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3922
diff changeset
    85
    @property
be05eeeb2db1 fix previous post values handling (eg on validation error) for sub-forms
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3922
diff changeset
    86
    def form_valerror(self):
be05eeeb2db1 fix previous post values handling (eg on validation error) for sub-forms
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3922
diff changeset
    87
        if self.parent_form is None:
be05eeeb2db1 fix previous post values handling (eg on validation error) for sub-forms
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3922
diff changeset
    88
            return self._form_valerror
be05eeeb2db1 fix previous post values handling (eg on validation error) for sub-forms
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3922
diff changeset
    89
        return self.parent_form.form_valerror
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1406
diff changeset
    90
1519
5cfc5cc1dd20 fix retreival of previously submitted error for entity forms
sylvain.thenault@logilab.fr
parents: 1451
diff changeset
    91
    # XXX deprecated with new form system. Should disappear
5cfc5cc1dd20 fix retreival of previously submitted error for entity forms
sylvain.thenault@logilab.fr
parents: 1451
diff changeset
    92
5cfc5cc1dd20 fix retreival of previously submitted error for entity forms
sylvain.thenault@logilab.fr
parents: 1451
diff changeset
    93
    domid = 'entityForm'
5cfc5cc1dd20 fix retreival of previously submitted error for entity forms
sylvain.thenault@logilab.fr
parents: 1451
diff changeset
    94
    category = 'form'
5cfc5cc1dd20 fix retreival of previously submitted error for entity forms
sylvain.thenault@logilab.fr
parents: 1451
diff changeset
    95
    controller = 'edit'
1995
ec95eaa2b711 turn renderers into appobjects
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
    96
    http_cache_manager = httpcache.NoHTTPCacheManager
1519
5cfc5cc1dd20 fix retreival of previously submitted error for entity forms
sylvain.thenault@logilab.fr
parents: 1451
diff changeset
    97
    add_to_breadcrumbs = False
5cfc5cc1dd20 fix retreival of previously submitted error for entity forms
sylvain.thenault@logilab.fr
parents: 1451
diff changeset
    98
1318
50e1a778c5ee new FormViewMixIn class, cleanup FormMixIn (to remove once cubes doesn't use it anymore)
sylvain.thenault@logilab.fr
parents: 1315
diff changeset
    99
    def html_headers(self):
50e1a778c5ee new FormViewMixIn class, cleanup FormMixIn (to remove once cubes doesn't use it anymore)
sylvain.thenault@logilab.fr
parents: 1315
diff changeset
   100
        """return a list of html headers (eg something to be inserted between
50e1a778c5ee new FormViewMixIn class, cleanup FormMixIn (to remove once cubes doesn't use it anymore)
sylvain.thenault@logilab.fr
parents: 1315
diff changeset
   101
        <head> and </head> of the returned page
50e1a778c5ee new FormViewMixIn class, cleanup FormMixIn (to remove once cubes doesn't use it anymore)
sylvain.thenault@logilab.fr
parents: 1315
diff changeset
   102
50e1a778c5ee new FormViewMixIn class, cleanup FormMixIn (to remove once cubes doesn't use it anymore)
sylvain.thenault@logilab.fr
parents: 1315
diff changeset
   103
        by default forms are neither indexed nor followed
50e1a778c5ee new FormViewMixIn class, cleanup FormMixIn (to remove once cubes doesn't use it anymore)
sylvain.thenault@logilab.fr
parents: 1315
diff changeset
   104
        """
50e1a778c5ee new FormViewMixIn class, cleanup FormMixIn (to remove once cubes doesn't use it anymore)
sylvain.thenault@logilab.fr
parents: 1315
diff changeset
   105
        return [NOINDEX, NOFOLLOW]
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1406
diff changeset
   106
1318
50e1a778c5ee new FormViewMixIn class, cleanup FormMixIn (to remove once cubes doesn't use it anymore)
sylvain.thenault@logilab.fr
parents: 1315
diff changeset
   107
    def linkable(self):
50e1a778c5ee new FormViewMixIn class, cleanup FormMixIn (to remove once cubes doesn't use it anymore)
sylvain.thenault@logilab.fr
parents: 1315
diff changeset
   108
        """override since forms are usually linked by an action,
50e1a778c5ee new FormViewMixIn class, cleanup FormMixIn (to remove once cubes doesn't use it anymore)
sylvain.thenault@logilab.fr
parents: 1315
diff changeset
   109
        so we don't want them to be listed by appli.possible_views
50e1a778c5ee new FormViewMixIn class, cleanup FormMixIn (to remove once cubes doesn't use it anymore)
sylvain.thenault@logilab.fr
parents: 1315
diff changeset
   110
        """
50e1a778c5ee new FormViewMixIn class, cleanup FormMixIn (to remove once cubes doesn't use it anymore)
sylvain.thenault@logilab.fr
parents: 1315
diff changeset
   111
        return False
50e1a778c5ee new FormViewMixIn class, cleanup FormMixIn (to remove once cubes doesn't use it anymore)
sylvain.thenault@logilab.fr
parents: 1315
diff changeset
   112
50e1a778c5ee new FormViewMixIn class, cleanup FormMixIn (to remove once cubes doesn't use it anymore)
sylvain.thenault@logilab.fr
parents: 1315
diff changeset
   113
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1133
diff changeset
   114
    def button(self, label, klass='validateButton', tabindex=None, **kwargs):
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1133
diff changeset
   115
        if tabindex is None:
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1133
diff changeset
   116
            tabindex = self.req.next_tabindex()
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1133
diff changeset
   117
        return tags.input(value=label, klass=klass, **kwargs)
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1133
diff changeset
   118
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1133
diff changeset
   119
    def action_button(self, label, onclick=None, __action=None, **kwargs):
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1133
diff changeset
   120
        if onclick is None:
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1133
diff changeset
   121
            onclick = "postForm('__action_%s', \'%s\', \'%s\')" % (
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1133
diff changeset
   122
                __action, label, self.domid)
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1133
diff changeset
   123
        return self.button(label, onclick=onclick, **kwargs)
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1133
diff changeset
   124
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1133
diff changeset
   125
    def button_ok(self, label=None, type='submit', name='defaultsubmit',
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1133
diff changeset
   126
                  **kwargs):
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1133
diff changeset
   127
        label = self.req._(label or stdmsgs.BUTTON_OK).capitalize()
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1133
diff changeset
   128
        return self.button(label, name=name, type=type, **kwargs)
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1406
diff changeset
   129
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1133
diff changeset
   130
    def button_apply(self, label=None, type='button', **kwargs):
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1133
diff changeset
   131
        label = self.req._(label or stdmsgs.BUTTON_APPLY).capitalize()
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1133
diff changeset
   132
        return self.action_button(label, __action='apply', type=type, **kwargs)
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1133
diff changeset
   133
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1133
diff changeset
   134
    def button_delete(self, label=None, type='button', **kwargs):
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1133
diff changeset
   135
        label = self.req._(label or stdmsgs.BUTTON_DELETE).capitalize()
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1133
diff changeset
   136
        return self.action_button(label, __action='delete', type=type, **kwargs)
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1406
diff changeset
   137
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1133
diff changeset
   138
    def button_cancel(self, label=None, type='button', **kwargs):
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1133
diff changeset
   139
        label = self.req._(label or stdmsgs.BUTTON_CANCEL).capitalize()
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1133
diff changeset
   140
        return self.action_button(label, __action='cancel', type=type, **kwargs)
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1406
diff changeset
   141
1147
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1133
diff changeset
   142
    def button_reset(self, label=None, type='reset', name='__action_cancel',
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1133
diff changeset
   143
                     **kwargs):
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1133
diff changeset
   144
        label = self.req._(label or stdmsgs.BUTTON_CANCEL).capitalize()
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1133
diff changeset
   145
        return self.button(label, type=type, **kwargs)
402e8a8b1d6a more form works
sylvain.thenault@logilab.fr
parents: 1133
diff changeset
   146
1305
395ef7f2b95b cleanup, remove some unnecessary (sometime buggy) stuff
sylvain.thenault@logilab.fr
parents: 1304
diff changeset
   147
    def need_multipart(self, entity, categories=('primary', 'secondary')):
395ef7f2b95b cleanup, remove some unnecessary (sometime buggy) stuff
sylvain.thenault@logilab.fr
parents: 1304
diff changeset
   148
        """return a boolean indicating if form's enctype should be multipart
395ef7f2b95b cleanup, remove some unnecessary (sometime buggy) stuff
sylvain.thenault@logilab.fr
parents: 1304
diff changeset
   149
        """
395ef7f2b95b cleanup, remove some unnecessary (sometime buggy) stuff
sylvain.thenault@logilab.fr
parents: 1304
diff changeset
   150
        for rschema, _, x in entity.relations_by_category(categories):
395ef7f2b95b cleanup, remove some unnecessary (sometime buggy) stuff
sylvain.thenault@logilab.fr
parents: 1304
diff changeset
   151
            if entity.get_widget(rschema, x).need_multipart:
395ef7f2b95b cleanup, remove some unnecessary (sometime buggy) stuff
sylvain.thenault@logilab.fr
parents: 1304
diff changeset
   152
                return True
395ef7f2b95b cleanup, remove some unnecessary (sometime buggy) stuff
sylvain.thenault@logilab.fr
parents: 1304
diff changeset
   153
        # let's find if any of our inlined entities needs multipart
395ef7f2b95b cleanup, remove some unnecessary (sometime buggy) stuff
sylvain.thenault@logilab.fr
parents: 1304
diff changeset
   154
        for rschema, targettypes, x in entity.relations_by_category('inlineview'):
395ef7f2b95b cleanup, remove some unnecessary (sometime buggy) stuff
sylvain.thenault@logilab.fr
parents: 1304
diff changeset
   155
            assert len(targettypes) == 1, \
395ef7f2b95b cleanup, remove some unnecessary (sometime buggy) stuff
sylvain.thenault@logilab.fr
parents: 1304
diff changeset
   156
                   "I'm not able to deal with several targets and inlineview"
395ef7f2b95b cleanup, remove some unnecessary (sometime buggy) stuff
sylvain.thenault@logilab.fr
parents: 1304
diff changeset
   157
            ttype = targettypes[0]
395ef7f2b95b cleanup, remove some unnecessary (sometime buggy) stuff
sylvain.thenault@logilab.fr
parents: 1304
diff changeset
   158
            inlined_entity = self.vreg.etype_class(ttype)(self.req, None, None)
395ef7f2b95b cleanup, remove some unnecessary (sometime buggy) stuff
sylvain.thenault@logilab.fr
parents: 1304
diff changeset
   159
            for irschema, _, x in inlined_entity.relations_by_category(categories):
395ef7f2b95b cleanup, remove some unnecessary (sometime buggy) stuff
sylvain.thenault@logilab.fr
parents: 1304
diff changeset
   160
                if inlined_entity.get_widget(irschema, x).need_multipart:
395ef7f2b95b cleanup, remove some unnecessary (sometime buggy) stuff
sylvain.thenault@logilab.fr
parents: 1304
diff changeset
   161
                    return True
395ef7f2b95b cleanup, remove some unnecessary (sometime buggy) stuff
sylvain.thenault@logilab.fr
parents: 1304
diff changeset
   162
        return False
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1406
diff changeset
   163
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   164
    def error_message(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   165
        """return formatted error message
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   166
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   167
        This method should be called once inlined field errors has been consumed
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   168
        """
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
   169
        errex = self.req.data.get('formerrors') or self.form_valerror
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   170
        # get extra errors
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   171
        if errex is not None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   172
            errormsg = self.req._('please correct the following errors:')
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
   173
            displayed = self.req.data.get('displayederrors') or self.form_displayed_errors
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   174
            errors = sorted((field, err) for field, err in errex.errors.items()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   175
                            if not field in displayed)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   176
            if errors:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   177
                if len(errors) > 1:
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1406
diff changeset
   178
                    templstr = '<li>%s</li>\n'
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   179
                else:
2996
866a2c135c33 B #345282 xhtml requires to use &#160; instead of &nbsp;
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 2656
diff changeset
   180
                    templstr = '&#160;%s\n'
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   181
                for field, err in errors:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   182
                    if field is None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   183
                        errormsg += templstr % err
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   184
                    else:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   185
                        errormsg += templstr % '%s: %s' % (self.req._(field), err)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   186
                if len(errors) > 1:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   187
                    errormsg = '<ul>%s</ul>' % errormsg
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   188
            return u'<div class="errorMessage">%s</div>' % errormsg
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   189
        return u''
844
8ab6f64c3750 start django like forms
sylvain.thenault@logilab.fr
parents: 765
diff changeset
   190
8ab6f64c3750 start django like forms
sylvain.thenault@logilab.fr
parents: 765
diff changeset
   191
8ab6f64c3750 start django like forms
sylvain.thenault@logilab.fr
parents: 765
diff changeset
   192
###############################################################################
8ab6f64c3750 start django like forms
sylvain.thenault@logilab.fr
parents: 765
diff changeset
   193
8ab6f64c3750 start django like forms
sylvain.thenault@logilab.fr
parents: 765
diff changeset
   194
class metafieldsform(type):
1406
133476216f4a define self.fields before it is used ...
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 1400
diff changeset
   195
    """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
   196
    and put them into a single ordered list: '_fields_'.
1393
ff6758d7b96f cleanup, more docstring
sylvain.thenault@logilab.fr
parents: 1392
diff changeset
   197
    """
844
8ab6f64c3750 start django like forms
sylvain.thenault@logilab.fr
parents: 765
diff changeset
   198
    def __new__(mcs, name, bases, classdict):
8ab6f64c3750 start django like forms
sylvain.thenault@logilab.fr
parents: 765
diff changeset
   199
        allfields = []
8ab6f64c3750 start django like forms
sylvain.thenault@logilab.fr
parents: 765
diff changeset
   200
        for base in bases:
8ab6f64c3750 start django like forms
sylvain.thenault@logilab.fr
parents: 765
diff changeset
   201
            if hasattr(base, '_fields_'):
8ab6f64c3750 start django like forms
sylvain.thenault@logilab.fr
parents: 765
diff changeset
   202
                allfields += base._fields_
8ab6f64c3750 start django like forms
sylvain.thenault@logilab.fr
parents: 765
diff changeset
   203
        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
   204
                     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
   205
        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
   206
            if not field.name:
869
168ad6d424d1 form to edit multiple entities, use it in DeleteConfForm
sylvain.thenault@logilab.fr
parents: 867
diff changeset
   207
                field.set_name(fieldname)
844
8ab6f64c3750 start django like forms
sylvain.thenault@logilab.fr
parents: 765
diff changeset
   208
            allfields.append(field)
8ab6f64c3750 start django like forms
sylvain.thenault@logilab.fr
parents: 765
diff changeset
   209
        classdict['_fields_'] = allfields
8ab6f64c3750 start django like forms
sylvain.thenault@logilab.fr
parents: 765
diff changeset
   210
        return super(metafieldsform, mcs).__new__(mcs, name, bases, classdict)
1270
53f35db66f88 raise specific exception
sylvain.thenault@logilab.fr
parents: 1265
diff changeset
   211
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1406
diff changeset
   212
1270
53f35db66f88 raise specific exception
sylvain.thenault@logilab.fr
parents: 1265
diff changeset
   213
class FieldNotFound(Exception):
53f35db66f88 raise specific exception
sylvain.thenault@logilab.fr
parents: 1265
diff changeset
   214
    """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
   215
    found
53f35db66f88 raise specific exception
sylvain.thenault@logilab.fr
parents: 1265
diff changeset
   216
    """
1437
ea75dfe32317 delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1406
diff changeset
   217
2656
a93ae0f6c0ad R [base classes] only AppObject remaning, no more AppRsetObject
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2005
diff changeset
   218
class Form(FormMixIn, AppObject):
844
8ab6f64c3750 start django like forms
sylvain.thenault@logilab.fr
parents: 765
diff changeset
   219
    __metaclass__ = metafieldsform
1047
21d4d5e6aa45 make forms selectable (appobject)
sylvain.thenault@logilab.fr
parents: 1032
diff changeset
   220
    __registry__ = 'forms'
3512
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   221
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   222
    parent_form = None
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   223
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   224
    @property
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   225
    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
   226
        """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
   227
        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
   228
            return self
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   229
        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
   230
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   231
    @iclassmethod
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   232
    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
   233
        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
   234
            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
   235
        else:
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   236
            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
   237
        return fields
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   238
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   239
    @iclassmethod
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   240
    def field_by_name(cls_or_self, name, role='subject'):
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   241
        """return field with the given name and role.
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   242
        Raise FieldNotFound if the field can't be found.
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   243
        """
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   244
        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
   245
            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
   246
                return field
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   247
        raise FieldNotFound(name)
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   248
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   249
    @iclassmethod
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   250
    def fields_by_name(cls_or_self, name, role='subject'):
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   251
        """return a list of fields with the given name and role"""
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   252
        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
   253
                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
   254
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   255
    @iclassmethod
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   256
    def remove_field(cls_or_self, field):
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   257
        """remove a field from form class or instance"""
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   258
        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
   259
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   260
    @iclassmethod
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   261
    def append_field(cls_or_self, field):
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   262
        """append a field to form class or instance"""
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   263
        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
   264
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   265
    @iclassmethod
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   266
    def insert_field_before(cls_or_self, new_field, name, role='subject'):
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   267
        field = cls_or_self.field_by_name(name, role)
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   268
        fields = cls_or_self._fieldsattr()
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   269
        fields.insert(fields.index(field), new_field)
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   270
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   271
    @iclassmethod
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   272
    def insert_field_after(cls_or_self, new_field, name, role='subject'):
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   273
        field = cls_or_self.field_by_name(name, role)
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   274
        fields = cls_or_self._fieldsattr()
2ceaa4e40348 move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2996
diff changeset
   275
        fields.insert(fields.index(field)+1, new_field)