WuttaWeb 0.10.0__tar.gz → 0.10.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/CHANGELOG.md +13 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/PKG-INFO +1 -1
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/pyproject.toml +1 -1
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/auth.py +9 -9
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/forms/base.py +38 -6
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/grids/base.py +49 -19
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/templates/form.mako +4 -5
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/templates/grids/vue_template.mako +1 -1
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/templates/master/index.mako +1 -4
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/util.py +7 -8
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/views/master.py +1 -1
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/views/people.py +1 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/views/roles.py +1 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/tests/forms/test_base.py +6 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/tests/grids/test_base.py +6 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/.gitignore +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/COPYING.txt +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/README.md +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/docs/Makefile +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/docs/_static/.keepme +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/docs/api/index.rst +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/docs/api/wuttaweb/app.rst +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/docs/api/wuttaweb/auth.rst +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/docs/api/wuttaweb/db.rst +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/docs/api/wuttaweb/forms.base.rst +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/docs/api/wuttaweb/forms.rst +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/docs/api/wuttaweb/forms.schema.rst +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/docs/api/wuttaweb/forms.widgets.rst +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/docs/api/wuttaweb/grids.base.rst +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/docs/api/wuttaweb/grids.rst +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/docs/api/wuttaweb/handler.rst +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/docs/api/wuttaweb/helpers.rst +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/docs/api/wuttaweb/index.rst +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/docs/api/wuttaweb/menus.rst +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/docs/api/wuttaweb/static.rst +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/docs/api/wuttaweb/subscribers.rst +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/docs/api/wuttaweb/util.rst +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/docs/api/wuttaweb/views.auth.rst +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/docs/api/wuttaweb/views.base.rst +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/docs/api/wuttaweb/views.common.rst +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/docs/api/wuttaweb/views.essential.rst +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/docs/api/wuttaweb/views.master.rst +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/docs/api/wuttaweb/views.people.rst +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/docs/api/wuttaweb/views.roles.rst +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/docs/api/wuttaweb/views.rst +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/docs/api/wuttaweb/views.settings.rst +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/docs/api/wuttaweb/views.users.rst +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/docs/conf.py +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/docs/glossary.rst +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/docs/index.rst +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/docs/make.bat +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/docs/narr/index.rst +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/__init__.py +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/_version.py +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/app.py +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/db.py +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/forms/__init__.py +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/forms/schema.py +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/forms/widgets.py +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/grids/__init__.py +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/handler.py +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/helpers.py +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/menus.py +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/static/__init__.py +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/static/img/favicon.ico +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/static/img/logo.png +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/static/img/testing.png +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/subscribers.py +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/templates/appinfo/configure.mako +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/templates/appinfo/index.mako +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/templates/auth/change_password.mako +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/templates/auth/login.mako +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/templates/base.mako +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/templates/base_meta.mako +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/templates/configure.mako +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/templates/deform/checkbox.pt +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/templates/deform/checkbox_choice.pt +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/templates/deform/checked_password.pt +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/templates/deform/password.pt +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/templates/deform/permissions.pt +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/templates/deform/readonly/notes.pt +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/templates/deform/readonly/objectref.pt +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/templates/deform/readonly/permissions.pt +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/templates/deform/select.pt +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/templates/deform/textarea.pt +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/templates/deform/textinput.pt +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/templates/forbidden.mako +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/templates/forms/vue_template.mako +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/templates/home.mako +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/templates/master/configure.mako +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/templates/master/create.mako +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/templates/master/delete.mako +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/templates/master/edit.mako +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/templates/master/form.mako +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/templates/master/view.mako +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/templates/notfound.mako +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/templates/page.mako +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/templates/people/view_profile.mako +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/templates/setup.mako +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/templates/wutta-components.mako +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/views/__init__.py +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/views/auth.py +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/views/base.py +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/views/common.py +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/views/essential.py +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/views/settings.py +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/views/users.py +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/tasks.py +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/tests/__init__.py +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/tests/forms/__init__.py +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/tests/forms/test_schema.py +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/tests/forms/test_widgets.py +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/tests/grids/__init__.py +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/tests/libcache/bb_fontawesome_svg_core.js +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/tests/libcache/bb_free_solid_svg_icons.js +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/tests/libcache/bb_oruga.js +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/tests/libcache/bb_oruga_bulma.css +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/tests/libcache/bb_oruga_bulma.js +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/tests/libcache/bb_vue.js +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/tests/libcache/bb_vue_fontawesome.js +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/tests/libcache/buefy.css +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/tests/libcache/buefy.js +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/tests/libcache/fontawesome.js +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/tests/libcache/vue.js +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/tests/libcache/vue_resource.js +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/tests/test_app.py +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/tests/test_auth.py +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/tests/test_handler.py +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/tests/test_helpers.py +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/tests/test_menus.py +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/tests/test_static.py +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/tests/test_subscribers.py +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/tests/test_util.py +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/tests/util.py +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/tests/views/__init__.py +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/tests/views/test___init__.py +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/tests/views/test_auth.py +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/tests/views/test_base.py +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/tests/views/test_common.py +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/tests/views/test_master.py +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/tests/views/test_people.py +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/tests/views/test_roles.py +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/tests/views/test_settings.py +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/tests/views/test_users.py +0 -0
- {wuttaweb-0.10.0 → wuttaweb-0.10.2}/tox.ini +0 -0
|
@@ -5,6 +5,19 @@ All notable changes to wuttaweb will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
|
|
6
6
|
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## v0.10.2 (2024-08-19)
|
|
9
|
+
|
|
10
|
+
### Fix
|
|
11
|
+
|
|
12
|
+
- add `render_vue_finalize()` methods for grids, forms
|
|
13
|
+
- avoid error when checking model for column property
|
|
14
|
+
|
|
15
|
+
## v0.10.1 (2024-08-19)
|
|
16
|
+
|
|
17
|
+
### Fix
|
|
18
|
+
|
|
19
|
+
- make `util.get_model_fields()` work with more model classes
|
|
20
|
+
|
|
8
21
|
## v0.10.0 (2024-08-18)
|
|
9
22
|
|
|
10
23
|
### Feat
|
|
@@ -150,7 +150,7 @@ class WuttaSecurityPolicy:
|
|
|
150
150
|
return auth.has_permission(self.db_session, user, permission)
|
|
151
151
|
|
|
152
152
|
|
|
153
|
-
def add_permission_group(pyramid_config,
|
|
153
|
+
def add_permission_group(pyramid_config, groupkey, label=None, overwrite=True):
|
|
154
154
|
"""
|
|
155
155
|
Pyramid directive to add a "permission group" to the app's
|
|
156
156
|
awareness.
|
|
@@ -169,12 +169,12 @@ def add_permission_group(pyramid_config, key, label=None, overwrite=True):
|
|
|
169
169
|
|
|
170
170
|
pyramid_config.add_permission_group('widgets', label="Widgets")
|
|
171
171
|
|
|
172
|
-
:param
|
|
173
|
-
of a master view, this will be the same as
|
|
172
|
+
:param groupkey: Unique key for the permission group. In the
|
|
173
|
+
context of a master view, this will be the same as
|
|
174
174
|
:attr:`~wuttaweb.views.master.MasterView.permission_prefix`.
|
|
175
175
|
|
|
176
176
|
:param label: Optional label for the permission group. If not
|
|
177
|
-
specified, it is derived from ``
|
|
177
|
+
specified, it is derived from ``groupkey``.
|
|
178
178
|
|
|
179
179
|
:param overwrite: If the permission group was already established,
|
|
180
180
|
this flag controls whether the group's label should be
|
|
@@ -186,9 +186,9 @@ def add_permission_group(pyramid_config, key, label=None, overwrite=True):
|
|
|
186
186
|
app = config.get_app()
|
|
187
187
|
def action():
|
|
188
188
|
perms = pyramid_config.get_settings().get('wutta_permissions', {})
|
|
189
|
-
if overwrite or
|
|
190
|
-
group = perms.setdefault(
|
|
191
|
-
group['label'] = label or app.make_title(
|
|
189
|
+
if overwrite or groupkey not in perms:
|
|
190
|
+
group = perms.setdefault(groupkey, {'key': groupkey})
|
|
191
|
+
group['label'] = label or app.make_title(groupkey)
|
|
192
192
|
pyramid_config.add_settings({'wutta_permissions': perms})
|
|
193
193
|
pyramid_config.action(None, action)
|
|
194
194
|
|
|
@@ -215,8 +215,8 @@ def add_permission(pyramid_config, groupkey, key, label=None):
|
|
|
215
215
|
pyramid_config.add_permission('widgets', 'widgets.polish',
|
|
216
216
|
label="Polish all the widgets")
|
|
217
217
|
|
|
218
|
-
:param
|
|
219
|
-
of a master view, this will be the same as
|
|
218
|
+
:param groupkey: Unique key for the permission group. In the
|
|
219
|
+
context of a master view, this will be the same as
|
|
220
220
|
:attr:`~wuttaweb.views.master.MasterView.permission_prefix`.
|
|
221
221
|
|
|
222
222
|
:param key: Unique key for the permission. This should be the
|
|
@@ -182,6 +182,8 @@ class Form:
|
|
|
182
182
|
String name for Vue component tag. By default this is
|
|
183
183
|
``'wutta-form'``. See also :meth:`render_vue_tag()`.
|
|
184
184
|
|
|
185
|
+
See also :attr:`vue_component`.
|
|
186
|
+
|
|
185
187
|
.. attribute:: align_buttons_right
|
|
186
188
|
|
|
187
189
|
Flag indicating whether the buttons (submit, cancel etc.)
|
|
@@ -784,6 +786,13 @@ class Form:
|
|
|
784
786
|
</form>
|
|
785
787
|
</script>
|
|
786
788
|
|
|
789
|
+
<script>
|
|
790
|
+
WuttaFormData = {}
|
|
791
|
+
WuttaForm = {
|
|
792
|
+
template: 'wutta-form-template',
|
|
793
|
+
}
|
|
794
|
+
</script>
|
|
795
|
+
|
|
787
796
|
.. todo::
|
|
788
797
|
|
|
789
798
|
Why can't Sphinx render the above code block as 'html' ?
|
|
@@ -909,19 +918,42 @@ class Form:
|
|
|
909
918
|
|
|
910
919
|
return HTML.tag('b-field', c=[html], **attrs)
|
|
911
920
|
|
|
921
|
+
def render_vue_finalize(self):
|
|
922
|
+
"""
|
|
923
|
+
Render the Vue "finalize" script for the form.
|
|
924
|
+
|
|
925
|
+
By default this simply returns:
|
|
926
|
+
|
|
927
|
+
.. code-block:: html
|
|
928
|
+
|
|
929
|
+
<script>
|
|
930
|
+
WuttaForm.data = function() { return WuttaFormData }
|
|
931
|
+
Vue.component('wutta-form', WuttaForm)
|
|
932
|
+
</script>
|
|
933
|
+
|
|
934
|
+
The actual output may depend on various form attributes, in
|
|
935
|
+
particular :attr:`vue_tagname`.
|
|
936
|
+
"""
|
|
937
|
+
set_data = f"{self.vue_component}.data = function() {{ return {self.vue_component}Data }}"
|
|
938
|
+
make_component = f"Vue.component('{self.vue_tagname}', {self.vue_component})"
|
|
939
|
+
return HTML.tag('script', c=['\n',
|
|
940
|
+
HTML.literal(set_data),
|
|
941
|
+
'\n',
|
|
942
|
+
HTML.literal(make_component),
|
|
943
|
+
'\n'])
|
|
944
|
+
|
|
912
945
|
def get_vue_model_data(self):
|
|
913
946
|
"""
|
|
914
947
|
Returns a dict with form model data. Values may be nested
|
|
915
948
|
depending on the types of fields contained in the form.
|
|
916
949
|
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
is not a problem here. The point is to collect the raw data.
|
|
950
|
+
This collects the ``cstruct`` values for all fields which are
|
|
951
|
+
present both in :attr:`fields` as well as the Deform schema.
|
|
920
952
|
|
|
921
|
-
|
|
953
|
+
It also converts each as needed, to ensure it is
|
|
954
|
+
JSON-serializable.
|
|
922
955
|
|
|
923
|
-
|
|
924
|
-
is responsible for ensuring JSON compatibility.
|
|
956
|
+
:returns: Dict of field/value items.
|
|
925
957
|
"""
|
|
926
958
|
dform = self.get_deform()
|
|
927
959
|
model_data = {}
|
|
@@ -86,9 +86,9 @@ class Grid:
|
|
|
86
86
|
|
|
87
87
|
.. attribute:: columns
|
|
88
88
|
|
|
89
|
-
:class:`~wuttaweb.
|
|
90
|
-
|
|
91
|
-
|
|
89
|
+
:class:`~wuttaweb.util.FieldList` instance containing string
|
|
90
|
+
column names for the grid. Columns will appear in the same
|
|
91
|
+
order as they are in this list.
|
|
92
92
|
|
|
93
93
|
See also :meth:`set_columns()` and :meth:`get_columns()`.
|
|
94
94
|
|
|
@@ -239,9 +239,9 @@ class Grid:
|
|
|
239
239
|
|
|
240
240
|
.. attribute:: paginated
|
|
241
241
|
|
|
242
|
-
Boolean indicating whether the grid data should be paginated
|
|
243
|
-
|
|
244
|
-
|
|
242
|
+
Boolean indicating whether the grid data should be paginated,
|
|
243
|
+
i.e. split up into pages. Default is ``False`` which means all
|
|
244
|
+
data is shown at once.
|
|
245
245
|
|
|
246
246
|
See also :attr:`pagesize` and :attr:`page`, and
|
|
247
247
|
:attr:`paginate_on_backend`.
|
|
@@ -392,7 +392,7 @@ class Grid:
|
|
|
392
392
|
Explicitly set the list of grid columns.
|
|
393
393
|
|
|
394
394
|
This will overwrite :attr:`columns` with a new
|
|
395
|
-
:class:`~wuttaweb.
|
|
395
|
+
:class:`~wuttaweb.util.FieldList` instance.
|
|
396
396
|
|
|
397
397
|
:param columns: List of string column names.
|
|
398
398
|
"""
|
|
@@ -440,9 +440,8 @@ class Grid:
|
|
|
440
440
|
|
|
441
441
|
:param label: New label for the column header.
|
|
442
442
|
|
|
443
|
-
See also :meth:`get_label()`.
|
|
444
|
-
|
|
445
|
-
Label overrides are tracked via :attr:`labels`.
|
|
443
|
+
See also :meth:`get_label()`. Label overrides are tracked via
|
|
444
|
+
:attr:`labels`.
|
|
446
445
|
"""
|
|
447
446
|
self.labels[key] = label
|
|
448
447
|
|
|
@@ -490,7 +489,7 @@ class Grid:
|
|
|
490
489
|
def render_foo(record, key, value):
|
|
491
490
|
return HTML.literal("<p>this is the final cell value</p>")
|
|
492
491
|
|
|
493
|
-
grid = Grid(columns=['foo', 'bar'])
|
|
492
|
+
grid = Grid(request, columns=['foo', 'bar'])
|
|
494
493
|
grid.set_renderer('foo', render_foo)
|
|
495
494
|
|
|
496
495
|
Renderer overrides are tracked via :attr:`renderers`.
|
|
@@ -509,8 +508,8 @@ class Grid:
|
|
|
509
508
|
URL for this will be the same as for the "View"
|
|
510
509
|
:class:`GridAction`
|
|
511
510
|
(aka. :meth:`~wuttaweb.views.master.MasterView.view()`).
|
|
512
|
-
Although of course each cell gets a different
|
|
513
|
-
on which data record it points to.
|
|
511
|
+
Although of course each cell in the column gets a different
|
|
512
|
+
link depending on which data record it points to.
|
|
514
513
|
|
|
515
514
|
It is typical to enable auto-link for fields relating to ID,
|
|
516
515
|
description etc. or some may prefer to auto-link all columns.
|
|
@@ -579,7 +578,8 @@ class Grid:
|
|
|
579
578
|
if key in sorters:
|
|
580
579
|
continue
|
|
581
580
|
prop = getattr(self.model_class, key, None)
|
|
582
|
-
if prop and
|
|
581
|
+
if (prop and hasattr(prop, 'property')
|
|
582
|
+
and isinstance(prop.property, orm.ColumnProperty)):
|
|
583
583
|
sorters[prop.key] = self.make_sorter(prop)
|
|
584
584
|
|
|
585
585
|
return sorters
|
|
@@ -609,8 +609,8 @@ class Grid:
|
|
|
609
609
|
The term "model property" is a bit technical, an example
|
|
610
610
|
should help to clarify::
|
|
611
611
|
|
|
612
|
-
model =
|
|
613
|
-
grid = Grid(
|
|
612
|
+
model = app.model
|
|
613
|
+
grid = Grid(request, model_class=model.Person)
|
|
614
614
|
|
|
615
615
|
# explicit property
|
|
616
616
|
sorter = grid.make_sorter(model.Person.full_name)
|
|
@@ -633,7 +633,7 @@ class Grid:
|
|
|
633
633
|
]
|
|
634
634
|
|
|
635
635
|
# nb. no model_class, just as an example
|
|
636
|
-
grid = Grid(
|
|
636
|
+
grid = Grid(request, columns=['foo', 'bar'], data=data)
|
|
637
637
|
|
|
638
638
|
def getkey(obj):
|
|
639
639
|
if obj.get('foo')
|
|
@@ -725,8 +725,8 @@ class Grid:
|
|
|
725
725
|
A backend sorter callable must accept ``(data, direction)``
|
|
726
726
|
args and return the sorted data/query, for example::
|
|
727
727
|
|
|
728
|
-
model =
|
|
729
|
-
grid = Grid(
|
|
728
|
+
model = app.model
|
|
729
|
+
grid = Grid(request, model_class=model.Person)
|
|
730
730
|
|
|
731
731
|
def sort_full_name(query, direction):
|
|
732
732
|
sortspec = getattr(model.Person.full_name, direction)
|
|
@@ -750,6 +750,10 @@ class Grid:
|
|
|
750
750
|
"""
|
|
751
751
|
Remove the backend sorter for a column.
|
|
752
752
|
|
|
753
|
+
Note that this removes the sorter *function*, so there is
|
|
754
|
+
no way to sort by this column unless another sorter is
|
|
755
|
+
later defined for it.
|
|
756
|
+
|
|
753
757
|
See also :meth:`set_sorter()`.
|
|
754
758
|
"""
|
|
755
759
|
self.sorters.pop(key, None)
|
|
@@ -1140,6 +1144,7 @@ class Grid:
|
|
|
1140
1144
|
|
|
1141
1145
|
See also these methods which may be called by this one:
|
|
1142
1146
|
|
|
1147
|
+
* :meth:`sort_data()`
|
|
1143
1148
|
* :meth:`paginate_data()`
|
|
1144
1149
|
"""
|
|
1145
1150
|
data = self.data or []
|
|
@@ -1273,6 +1278,30 @@ class Grid:
|
|
|
1273
1278
|
output = render(template, context)
|
|
1274
1279
|
return HTML.literal(output)
|
|
1275
1280
|
|
|
1281
|
+
def render_vue_finalize(self):
|
|
1282
|
+
"""
|
|
1283
|
+
Render the Vue "finalize" script for the grid.
|
|
1284
|
+
|
|
1285
|
+
By default this simply returns:
|
|
1286
|
+
|
|
1287
|
+
.. code-block:: html
|
|
1288
|
+
|
|
1289
|
+
<script>
|
|
1290
|
+
WuttaGrid.data = function() { return WuttaGridData }
|
|
1291
|
+
Vue.component('wutta-grid', WuttaGrid)
|
|
1292
|
+
</script>
|
|
1293
|
+
|
|
1294
|
+
The actual output may depend on various grid attributes, in
|
|
1295
|
+
particular :attr:`vue_tagname`.
|
|
1296
|
+
"""
|
|
1297
|
+
set_data = f"{self.vue_component}.data = function() {{ return {self.vue_component}Data }}"
|
|
1298
|
+
make_component = f"Vue.component('{self.vue_tagname}', {self.vue_component})"
|
|
1299
|
+
return HTML.tag('script', c=['\n',
|
|
1300
|
+
HTML.literal(set_data),
|
|
1301
|
+
'\n',
|
|
1302
|
+
HTML.literal(make_component),
|
|
1303
|
+
'\n'])
|
|
1304
|
+
|
|
1276
1305
|
def get_vue_columns(self):
|
|
1277
1306
|
"""
|
|
1278
1307
|
Returns a list of Vue-compatible column definitions.
|
|
@@ -1283,6 +1312,7 @@ class Grid:
|
|
|
1283
1312
|
{
|
|
1284
1313
|
'field': 'foo',
|
|
1285
1314
|
'label': "Foo",
|
|
1315
|
+
'sortable': True,
|
|
1286
1316
|
}
|
|
1287
1317
|
|
|
1288
1318
|
See also :meth:`get_vue_data()`.
|
|
@@ -3,7 +3,9 @@
|
|
|
3
3
|
|
|
4
4
|
<%def name="page_content()">
|
|
5
5
|
<div style="margin-top: 2rem; width: 50%;">
|
|
6
|
-
|
|
6
|
+
% if form is not Undefined:
|
|
7
|
+
${form.render_vue_tag()}
|
|
8
|
+
% endif
|
|
7
9
|
</div>
|
|
8
10
|
</%def>
|
|
9
11
|
|
|
@@ -17,10 +19,7 @@
|
|
|
17
19
|
<%def name="finalize_this_page_vars()">
|
|
18
20
|
${parent.finalize_this_page_vars()}
|
|
19
21
|
% if form is not Undefined:
|
|
20
|
-
|
|
21
|
-
${form.vue_component}.data = function() { return ${form.vue_component}Data }
|
|
22
|
-
Vue.component('${form.vue_tagname}', ${form.vue_component})
|
|
23
|
-
</script>
|
|
22
|
+
${form.render_vue_finalize()}
|
|
24
23
|
% endif
|
|
25
24
|
</%def>
|
|
26
25
|
|
|
@@ -22,10 +22,7 @@
|
|
|
22
22
|
<%def name="finalize_this_page_vars()">
|
|
23
23
|
${parent.finalize_this_page_vars()}
|
|
24
24
|
% if grid is not Undefined:
|
|
25
|
-
|
|
26
|
-
${grid.vue_component}.data = function() { return ${grid.vue_component}Data }
|
|
27
|
-
Vue.component('${grid.vue_tagname}', ${grid.vue_component})
|
|
28
|
-
</script>
|
|
25
|
+
${grid.render_vue_finalize()}
|
|
29
26
|
% endif
|
|
30
27
|
</%def>
|
|
31
28
|
|
|
@@ -462,14 +462,13 @@ def get_model_fields(config, model_class=None):
|
|
|
462
462
|
if not model_class:
|
|
463
463
|
return
|
|
464
464
|
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
return fields
|
|
465
|
+
try:
|
|
466
|
+
mapper = sa.inspect(model_class)
|
|
467
|
+
except sa.exc.NoInspectionAvailable:
|
|
468
|
+
pass
|
|
469
|
+
else:
|
|
470
|
+
fields = [prop.key for prop in mapper.iterate_properties]
|
|
471
|
+
return fields
|
|
473
472
|
|
|
474
473
|
|
|
475
474
|
def make_json_safe(value, key=None, warn=True):
|
|
@@ -405,6 +405,12 @@ class TestForm(TestCase):
|
|
|
405
405
|
self.assertIn('<script type="text/x-template" id="wutta-form-template">', html)
|
|
406
406
|
self.assertNotIn('@submit', html)
|
|
407
407
|
|
|
408
|
+
def test_render_vue_finalize(self):
|
|
409
|
+
form = self.make_form()
|
|
410
|
+
html = form.render_vue_finalize()
|
|
411
|
+
self.assertIn('<script>', html)
|
|
412
|
+
self.assertIn("Vue.component('wutta-form', WuttaForm)", html)
|
|
413
|
+
|
|
408
414
|
def test_render_vue_field(self):
|
|
409
415
|
self.pyramid_config.include('pyramid_deform')
|
|
410
416
|
schema = self.make_schema()
|
|
@@ -855,6 +855,12 @@ class TestGrid(WebTestCase):
|
|
|
855
855
|
html = grid.render_vue_template()
|
|
856
856
|
self.assertIn('<script type="text/x-template" id="wutta-grid-template">', html)
|
|
857
857
|
|
|
858
|
+
def test_render_vue_finalize(self):
|
|
859
|
+
grid = self.make_grid()
|
|
860
|
+
html = grid.render_vue_finalize()
|
|
861
|
+
self.assertIn('<script>', html)
|
|
862
|
+
self.assertIn("Vue.component('wutta-grid', WuttaGrid)", html)
|
|
863
|
+
|
|
858
864
|
def test_get_vue_columns(self):
|
|
859
865
|
|
|
860
866
|
# error if no columns are set
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|