author | Aurelien Campeas <aurelien.campeas@logilab.fr> |
Wed, 21 Apr 2010 17:25:26 +0200 | |
branch | stable |
changeset 5369 | 68c33344581c |
parent 5368 | d321e4b62a10 |
child 5385 | b6e250dd7a7d |
child 5421 | 8167de96c523 |
permissions | -rw-r--r-- |
0 | 1 |
"""abstract form classes for CubicWeb web client |
2 |
||
3 |
:organization: Logilab |
|
4212
ab6573088b4a
update copyright: welcome 2010
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
3925
diff
changeset
|
4 |
:copyright: 2001-2010 LOGILAB S.A. (Paris, FRANCE), license is LGPL v2. |
0 | 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 | 7 |
""" |
8 |
__docformat__ = "restructuredtext en" |
|
9 |
||
4224
5998df006968
refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4165
diff
changeset
|
10 |
from warnings import warn |
5998df006968
refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4165
diff
changeset
|
11 |
|
3512
2ceaa4e40348
move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2996
diff
changeset
|
12 |
from logilab.common.decorators import iclassmethod |
4224
5998df006968
refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4165
diff
changeset
|
13 |
from logilab.common.deprecation import deprecated |
3512
2ceaa4e40348
move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2996
diff
changeset
|
14 |
|
2656
a93ae0f6c0ad
R [base classes] only AppObject remaning, no more AppRsetObject
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2005
diff
changeset
|
15 |
from cubicweb.appobject import AppObject |
1133 | 16 |
from cubicweb.view import NOINDEX, NOFOLLOW |
5369
68c33344581c
fix NameError
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5368
diff
changeset
|
17 |
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
|
18 |
|
1318
50e1a778c5ee
new FormViewMixIn class, cleanup FormMixIn (to remove once cubes doesn't use it anymore)
sylvain.thenault@logilab.fr
parents:
1315
diff
changeset
|
19 |
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
|
20 |
"""abstract form view mix-in""" |
0 | 21 |
category = 'form' |
1995
ec95eaa2b711
turn renderers into appobjects
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
1977
diff
changeset
|
22 |
http_cache_manager = httpcache.NoHTTPCacheManager |
0 | 23 |
add_to_breadcrumbs = False |
1437 | 24 |
|
0 | 25 |
def html_headers(self): |
26 |
"""return a list of html headers (eg something to be inserted between |
|
27 |
<head> and </head> of the returned page |
|
28 |
||
29 |
by default forms are neither indexed nor followed |
|
30 |
""" |
|
31 |
return [NOINDEX, NOFOLLOW] |
|
1437 | 32 |
|
0 | 33 |
def linkable(self): |
34 |
"""override since forms are usually linked by an action, |
|
35 |
so we don't want them to be listed by appli.possible_views |
|
36 |
""" |
|
37 |
return False |
|
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 |
|
844 | 40 |
############################################################################### |
41 |
||
42 |
class metafieldsform(type): |
|
1406
133476216f4a
define self.fields before it is used ...
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
1400
diff
changeset
|
43 |
"""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
|
44 |
and put them into a single ordered list: '_fields_'. |
1393 | 45 |
""" |
844 | 46 |
def __new__(mcs, name, bases, classdict): |
47 |
allfields = [] |
|
48 |
for base in bases: |
|
49 |
if hasattr(base, '_fields_'): |
|
50 |
allfields += base._fields_ |
|
51 |
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
|
52 |
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
|
53 |
for fieldname, field in sorted(clsfields, key=lambda x: x[1].creation_rank): |
844 | 54 |
if not field.name: |
869
168ad6d424d1
form to edit multiple entities, use it in DeleteConfForm
sylvain.thenault@logilab.fr
parents:
867
diff
changeset
|
55 |
field.set_name(fieldname) |
844 | 56 |
allfields.append(field) |
57 |
classdict['_fields_'] = allfields |
|
58 |
return super(metafieldsform, mcs).__new__(mcs, name, bases, classdict) |
|
1270 | 59 |
|
1437 | 60 |
|
1270 | 61 |
class FieldNotFound(Exception): |
62 |
"""raised by field_by_name when a field with the given name has not been |
|
63 |
found |
|
64 |
""" |
|
1437 | 65 |
|
3475
9c07e6c48e35
[forms] drop FormMixIn deprecated in 3.2
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3451
diff
changeset
|
66 |
class Form(AppObject): |
844 | 67 |
__metaclass__ = metafieldsform |
1047
21d4d5e6aa45
make forms selectable (appobject)
sylvain.thenault@logilab.fr
parents:
1032
diff
changeset
|
68 |
__registry__ = 'forms' |
3512
2ceaa4e40348
move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2996
diff
changeset
|
69 |
|
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
|
70 |
internal_fields = ('__errorurl',) + 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
|
71 |
|
3512
2ceaa4e40348
move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2996
diff
changeset
|
72 |
parent_form = None |
3998
94cc7cad3d2d
backport stable into default
Sylvain Thénault <sylvain.thenault@logilab.fr>
diff
changeset
|
73 |
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
|
74 |
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
|
75 |
copy_nav_params = False |
3512
2ceaa4e40348
move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2996
diff
changeset
|
76 |
|
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
|
77 |
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
|
78 |
submitmsg=None, mainform=True, **kwargs): |
9f82f81bf13d
[form] fix #719285, due to multiple calls to restore_previous_post, by proper refactorings
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4252
diff
changeset
|
79 |
super(Form, self).__init__(req, rset=rset, row=row, col=col) |
9f82f81bf13d
[form] fix #719285, due to multiple calls to restore_previous_post, by proper refactorings
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4252
diff
changeset
|
80 |
self.fields = list(self.__class__._fields_) |
4683
c375d50eaad3
[form] only set __form_id for the main form, not for sub-forms. Should fix regression introduced by 4668:9f82f81bf13d
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4668
diff
changeset
|
81 |
if mainform: |
c375d50eaad3
[form] only set __form_id for the main form, not for sub-forms. Should fix regression introduced by 4668:9f82f81bf13d
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4668
diff
changeset
|
82 |
self.add_hidden(u'__form_id', kwargs.pop('formvid', self.__regid__)) |
4668
9f82f81bf13d
[form] fix #719285, due to multiple calls to restore_previous_post, by proper refactorings
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4252
diff
changeset
|
83 |
for key, val in kwargs.iteritems(): |
9f82f81bf13d
[form] fix #719285, due to multiple calls to restore_previous_post, by proper refactorings
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4252
diff
changeset
|
84 |
if key in controller.NAV_FORM_PARAMETERS: |
9f82f81bf13d
[form] fix #719285, due to multiple calls to restore_previous_post, by proper refactorings
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4252
diff
changeset
|
85 |
self.add_hidden(key, val) |
9f82f81bf13d
[form] fix #719285, due to multiple calls to restore_previous_post, by proper refactorings
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4252
diff
changeset
|
86 |
elif key == 'redirect_path': |
9f82f81bf13d
[form] fix #719285, due to multiple calls to restore_previous_post, by proper refactorings
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4252
diff
changeset
|
87 |
self.add_hidden(u'__redirectpath', val) |
9f82f81bf13d
[form] fix #719285, due to multiple calls to restore_previous_post, by proper refactorings
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4252
diff
changeset
|
88 |
elif hasattr(self.__class__, key) and not key[0] == '_': |
9f82f81bf13d
[form] fix #719285, due to multiple calls to restore_previous_post, by proper refactorings
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4252
diff
changeset
|
89 |
setattr(self, key, val) |
9f82f81bf13d
[form] fix #719285, due to multiple calls to restore_previous_post, by proper refactorings
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4252
diff
changeset
|
90 |
else: |
9f82f81bf13d
[form] fix #719285, due to multiple calls to restore_previous_post, by proper refactorings
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4252
diff
changeset
|
91 |
self.cw_extra_kwargs[key] = val |
9f82f81bf13d
[form] fix #719285, due to multiple calls to restore_previous_post, by proper refactorings
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4252
diff
changeset
|
92 |
# skip other parameters, usually given for selection |
9f82f81bf13d
[form] fix #719285, due to multiple calls to restore_previous_post, by proper refactorings
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4252
diff
changeset
|
93 |
# (else write a custom class to handle them) |
9f82f81bf13d
[form] fix #719285, due to multiple calls to restore_previous_post, by proper refactorings
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4252
diff
changeset
|
94 |
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
|
95 |
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
|
96 |
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
|
97 |
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
|
98 |
# 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
|
99 |
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
|
100 |
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
|
101 |
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
|
102 |
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
|
103 |
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
|
104 |
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
|
105 |
if submitmsg is not 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
|
106 |
self.add_hidden(u'__message', submitmsg) |
3512
2ceaa4e40348
move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2996
diff
changeset
|
107 |
|
2ceaa4e40348
move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2996
diff
changeset
|
108 |
@property |
2ceaa4e40348
move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2996
diff
changeset
|
109 |
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
|
110 |
"""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
|
111 |
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
|
112 |
return self |
2ceaa4e40348
move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2996
diff
changeset
|
113 |
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
|
114 |
|
3998
94cc7cad3d2d
backport stable into default
Sylvain Thénault <sylvain.thenault@logilab.fr>
diff
changeset
|
115 |
@property |
4224
5998df006968
refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4165
diff
changeset
|
116 |
def form_valerror(self): |
5998df006968
refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4165
diff
changeset
|
117 |
"""the validation error exception if any""" |
5998df006968
refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4165
diff
changeset
|
118 |
if self.parent_form is None: |
5998df006968
refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4165
diff
changeset
|
119 |
return self._form_valerror |
5998df006968
refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4165
diff
changeset
|
120 |
return self.parent_form.form_valerror |
5998df006968
refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4165
diff
changeset
|
121 |
|
5998df006968
refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4165
diff
changeset
|
122 |
@property |
3998
94cc7cad3d2d
backport stable into default
Sylvain Thénault <sylvain.thenault@logilab.fr>
diff
changeset
|
123 |
def form_previous_values(self): |
4224
5998df006968
refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4165
diff
changeset
|
124 |
"""previously posted values (on validation error)""" |
3998
94cc7cad3d2d
backport stable into default
Sylvain Thénault <sylvain.thenault@logilab.fr>
diff
changeset
|
125 |
if self.parent_form is None: |
94cc7cad3d2d
backport stable into default
Sylvain Thénault <sylvain.thenault@logilab.fr>
diff
changeset
|
126 |
return self._form_previous_values |
94cc7cad3d2d
backport stable into default
Sylvain Thénault <sylvain.thenault@logilab.fr>
diff
changeset
|
127 |
return self.parent_form.form_previous_values |
94cc7cad3d2d
backport stable into default
Sylvain Thénault <sylvain.thenault@logilab.fr>
diff
changeset
|
128 |
|
3512
2ceaa4e40348
move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2996
diff
changeset
|
129 |
@iclassmethod |
2ceaa4e40348
move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2996
diff
changeset
|
130 |
def _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
|
131 |
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
|
132 |
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
|
133 |
else: |
2ceaa4e40348
move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2996
diff
changeset
|
134 |
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
|
135 |
return fields |
2ceaa4e40348
move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2996
diff
changeset
|
136 |
|
2ceaa4e40348
move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2996
diff
changeset
|
137 |
@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
|
138 |
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
|
139 |
"""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
|
140 |
|
d321e4b62a10
[book] start documenting the HTML form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5367
diff
changeset
|
141 |
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
|
142 |
""" |
2ceaa4e40348
move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2996
diff
changeset
|
143 |
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
|
144 |
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
|
145 |
return field |
4235
49eb7e87d36d
specify name *and* role when raising FieldNotFound helps debugging
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4224
diff
changeset
|
146 |
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
|
147 |
|
2ceaa4e40348
move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2996
diff
changeset
|
148 |
@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
|
149 |
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
|
150 |
"""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
|
151 |
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
|
152 |
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
|
153 |
|
2ceaa4e40348
move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2996
diff
changeset
|
154 |
@iclassmethod |
2ceaa4e40348
move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2996
diff
changeset
|
155 |
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
|
156 |
"""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
|
157 |
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
|
158 |
|
2ceaa4e40348
move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2996
diff
changeset
|
159 |
@iclassmethod |
2ceaa4e40348
move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2996
diff
changeset
|
160 |
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
|
161 |
"""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
|
162 |
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
|
163 |
|
2ceaa4e40348
move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2996
diff
changeset
|
164 |
@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
|
165 |
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
|
166 |
"""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
|
167 |
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
|
168 |
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
|
169 |
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
|
170 |
|
4176a50c81c9
[form] small api cleanup and refactoring before documenting the form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4779
diff
changeset
|
171 |
@iclassmethod |
4176a50c81c9
[form] small api cleanup and refactoring before documenting the form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4779
diff
changeset
|
172 |
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
|
173 |
"""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
|
174 |
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
|
175 |
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
|
176 |
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
|
177 |
|
2ceaa4e40348
move low-level form handling to base form class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2996
diff
changeset
|
178 |
@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
|
179 |
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
|
180 |
"""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
|
181 |
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
|
182 |
returned. |
4176a50c81c9
[form] small api cleanup and refactoring before documenting the form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4779
diff
changeset
|
183 |
""" |
4176a50c81c9
[form] small api cleanup and refactoring before documenting the form system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4779
diff
changeset
|
184 |
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
|
185 |
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
|
186 |
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
|
187 |
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
|
188 |
# 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
|
189 |
# 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
|
190 |
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
|
191 |
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
|
192 |
return field |
3524 | 193 |
|
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
|
194 |
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
|
195 |
"""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
|
196 |
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
|
197 |
""" |
3998
94cc7cad3d2d
backport stable into default
Sylvain Thénault <sylvain.thenault@logilab.fr>
diff
changeset
|
198 |
if self.force_session_key is None: |
4082
c7117119e215
3.6 api update
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4023
diff
changeset
|
199 |
return '%s#%s' % (self._cw.url(), self.domid) |
3998
94cc7cad3d2d
backport stable into default
Sylvain Thénault <sylvain.thenault@logilab.fr>
diff
changeset
|
200 |
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
|
201 |
|
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
|
202 |
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
|
203 |
# 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
|
204 |
# 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
|
205 |
# 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
|
206 |
# method on successful commit |
4779
dce36da37d40
fix: Prevent multi pass in restore_previous_post
Alain Leufroy <alain.leufroy@logilab.fr>
parents:
4719
diff
changeset
|
207 |
if hasattr(self, '_form_previous_values'): |
dce36da37d40
fix: Prevent multi pass in restore_previous_post
Alain Leufroy <alain.leufroy@logilab.fr>
parents:
4719
diff
changeset
|
208 |
# XXX behaviour changed in 3.6.1, warn |
dce36da37d40
fix: Prevent multi pass in restore_previous_post
Alain Leufroy <alain.leufroy@logilab.fr>
parents:
4719
diff
changeset
|
209 |
warn('[3.6.1] restore_previous_post already called, remove this call', |
dce36da37d40
fix: Prevent multi pass in restore_previous_post
Alain Leufroy <alain.leufroy@logilab.fr>
parents:
4719
diff
changeset
|
210 |
DeprecationWarning, stacklevel=2) |
dce36da37d40
fix: Prevent multi pass in restore_previous_post
Alain Leufroy <alain.leufroy@logilab.fr>
parents:
4719
diff
changeset
|
211 |
return |
3451
6b46d73823f5
[api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
3023
diff
changeset
|
212 |
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
|
213 |
if forminfo: |
4224
5998df006968
refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4165
diff
changeset
|
214 |
self._form_previous_values = forminfo['values'] |
5998df006968
refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4165
diff
changeset
|
215 |
self._form_valerror = forminfo['error'] |
1318
50e1a778c5ee
new FormViewMixIn class, cleanup FormMixIn (to remove once cubes doesn't use it anymore)
sylvain.thenault@logilab.fr
parents:
1315
diff
changeset
|
216 |
# 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
|
217 |
# 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
|
218 |
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
|
219 |
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
|
220 |
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
|
221 |
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
|
222 |
break |
50e1a778c5ee
new FormViewMixIn class, cleanup FormMixIn (to remove once cubes doesn't use it anymore)
sylvain.thenault@logilab.fr
parents:
1315
diff
changeset
|
223 |
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
|
224 |
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
|
225 |
else: |
3998
94cc7cad3d2d
backport stable into default
Sylvain Thénault <sylvain.thenault@logilab.fr>
diff
changeset
|
226 |
self._form_previous_values = {} |
94cc7cad3d2d
backport stable into default
Sylvain Thénault <sylvain.thenault@logilab.fr>
diff
changeset
|
227 |
self._form_valerror = None |
4224
5998df006968
refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4165
diff
changeset
|
228 |
|
5998df006968
refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4165
diff
changeset
|
229 |
def field_error(self, field): |
5998df006968
refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4165
diff
changeset
|
230 |
"""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
|
231 |
if self.form_valerror: |
5998df006968
refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4165
diff
changeset
|
232 |
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
|
233 |
return None |
5998df006968
refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4165
diff
changeset
|
234 |
try: |
5998df006968
refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4165
diff
changeset
|
235 |
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
|
236 |
except KeyError: |
5998df006968
refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4165
diff
changeset
|
237 |
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
|
238 |
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
|
239 |
% self.form_valerror.__class__, DeprecationWarning) |
5998df006968
refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4165
diff
changeset
|
240 |
return self.form_valerror.errors.pop(field.name) |
5998df006968
refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4165
diff
changeset
|
241 |
return None |
5998df006968
refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4165
diff
changeset
|
242 |
|
5998df006968
refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4165
diff
changeset
|
243 |
def remaining_errors(self): |
5998df006968
refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4165
diff
changeset
|
244 |
return sorted(self.form_valerror.errors.items()) |
5998df006968
refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4165
diff
changeset
|
245 |
|
5998df006968
refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4165
diff
changeset
|
246 |
@deprecated('[3.6] use form.field_error and/or new renderer.render_error method') |
5998df006968
refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4165
diff
changeset
|
247 |
def form_field_error(self, field): |
5998df006968
refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4165
diff
changeset
|
248 |
"""return validation error for widget's field, if any""" |
5998df006968
refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4165
diff
changeset
|
249 |
err = self.field_error(field) |
5998df006968
refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4165
diff
changeset
|
250 |
if err: |
5998df006968
refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4165
diff
changeset
|
251 |
return u'<span class="error">%s</span>' % err |
5998df006968
refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4165
diff
changeset
|
252 |
return u'' |
5998df006968
refactor form error handling:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4165
diff
changeset
|
253 |