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.
Files changed (145) hide show
  1. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/CHANGELOG.md +13 -0
  2. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/PKG-INFO +1 -1
  3. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/pyproject.toml +1 -1
  4. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/auth.py +9 -9
  5. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/forms/base.py +38 -6
  6. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/grids/base.py +49 -19
  7. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/templates/form.mako +4 -5
  8. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/templates/grids/vue_template.mako +1 -1
  9. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/templates/master/index.mako +1 -4
  10. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/util.py +7 -8
  11. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/views/master.py +1 -1
  12. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/views/people.py +1 -0
  13. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/views/roles.py +1 -0
  14. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/tests/forms/test_base.py +6 -0
  15. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/tests/grids/test_base.py +6 -0
  16. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/.gitignore +0 -0
  17. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/COPYING.txt +0 -0
  18. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/README.md +0 -0
  19. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/docs/Makefile +0 -0
  20. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/docs/_static/.keepme +0 -0
  21. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/docs/api/index.rst +0 -0
  22. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/docs/api/wuttaweb/app.rst +0 -0
  23. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/docs/api/wuttaweb/auth.rst +0 -0
  24. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/docs/api/wuttaweb/db.rst +0 -0
  25. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/docs/api/wuttaweb/forms.base.rst +0 -0
  26. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/docs/api/wuttaweb/forms.rst +0 -0
  27. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/docs/api/wuttaweb/forms.schema.rst +0 -0
  28. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/docs/api/wuttaweb/forms.widgets.rst +0 -0
  29. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/docs/api/wuttaweb/grids.base.rst +0 -0
  30. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/docs/api/wuttaweb/grids.rst +0 -0
  31. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/docs/api/wuttaweb/handler.rst +0 -0
  32. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/docs/api/wuttaweb/helpers.rst +0 -0
  33. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/docs/api/wuttaweb/index.rst +0 -0
  34. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/docs/api/wuttaweb/menus.rst +0 -0
  35. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/docs/api/wuttaweb/static.rst +0 -0
  36. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/docs/api/wuttaweb/subscribers.rst +0 -0
  37. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/docs/api/wuttaweb/util.rst +0 -0
  38. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/docs/api/wuttaweb/views.auth.rst +0 -0
  39. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/docs/api/wuttaweb/views.base.rst +0 -0
  40. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/docs/api/wuttaweb/views.common.rst +0 -0
  41. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/docs/api/wuttaweb/views.essential.rst +0 -0
  42. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/docs/api/wuttaweb/views.master.rst +0 -0
  43. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/docs/api/wuttaweb/views.people.rst +0 -0
  44. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/docs/api/wuttaweb/views.roles.rst +0 -0
  45. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/docs/api/wuttaweb/views.rst +0 -0
  46. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/docs/api/wuttaweb/views.settings.rst +0 -0
  47. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/docs/api/wuttaweb/views.users.rst +0 -0
  48. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/docs/conf.py +0 -0
  49. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/docs/glossary.rst +0 -0
  50. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/docs/index.rst +0 -0
  51. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/docs/make.bat +0 -0
  52. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/docs/narr/index.rst +0 -0
  53. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/__init__.py +0 -0
  54. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/_version.py +0 -0
  55. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/app.py +0 -0
  56. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/db.py +0 -0
  57. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/forms/__init__.py +0 -0
  58. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/forms/schema.py +0 -0
  59. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/forms/widgets.py +0 -0
  60. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/grids/__init__.py +0 -0
  61. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/handler.py +0 -0
  62. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/helpers.py +0 -0
  63. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/menus.py +0 -0
  64. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/static/__init__.py +0 -0
  65. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/static/img/favicon.ico +0 -0
  66. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/static/img/logo.png +0 -0
  67. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/static/img/testing.png +0 -0
  68. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/subscribers.py +0 -0
  69. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/templates/appinfo/configure.mako +0 -0
  70. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/templates/appinfo/index.mako +0 -0
  71. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/templates/auth/change_password.mako +0 -0
  72. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/templates/auth/login.mako +0 -0
  73. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/templates/base.mako +0 -0
  74. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/templates/base_meta.mako +0 -0
  75. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/templates/configure.mako +0 -0
  76. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/templates/deform/checkbox.pt +0 -0
  77. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/templates/deform/checkbox_choice.pt +0 -0
  78. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/templates/deform/checked_password.pt +0 -0
  79. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/templates/deform/password.pt +0 -0
  80. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/templates/deform/permissions.pt +0 -0
  81. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/templates/deform/readonly/notes.pt +0 -0
  82. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/templates/deform/readonly/objectref.pt +0 -0
  83. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/templates/deform/readonly/permissions.pt +0 -0
  84. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/templates/deform/select.pt +0 -0
  85. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/templates/deform/textarea.pt +0 -0
  86. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/templates/deform/textinput.pt +0 -0
  87. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/templates/forbidden.mako +0 -0
  88. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/templates/forms/vue_template.mako +0 -0
  89. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/templates/home.mako +0 -0
  90. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/templates/master/configure.mako +0 -0
  91. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/templates/master/create.mako +0 -0
  92. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/templates/master/delete.mako +0 -0
  93. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/templates/master/edit.mako +0 -0
  94. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/templates/master/form.mako +0 -0
  95. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/templates/master/view.mako +0 -0
  96. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/templates/notfound.mako +0 -0
  97. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/templates/page.mako +0 -0
  98. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/templates/people/view_profile.mako +0 -0
  99. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/templates/setup.mako +0 -0
  100. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/templates/wutta-components.mako +0 -0
  101. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/views/__init__.py +0 -0
  102. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/views/auth.py +0 -0
  103. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/views/base.py +0 -0
  104. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/views/common.py +0 -0
  105. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/views/essential.py +0 -0
  106. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/views/settings.py +0 -0
  107. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/src/wuttaweb/views/users.py +0 -0
  108. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/tasks.py +0 -0
  109. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/tests/__init__.py +0 -0
  110. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/tests/forms/__init__.py +0 -0
  111. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/tests/forms/test_schema.py +0 -0
  112. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/tests/forms/test_widgets.py +0 -0
  113. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/tests/grids/__init__.py +0 -0
  114. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/tests/libcache/bb_fontawesome_svg_core.js +0 -0
  115. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/tests/libcache/bb_free_solid_svg_icons.js +0 -0
  116. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/tests/libcache/bb_oruga.js +0 -0
  117. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/tests/libcache/bb_oruga_bulma.css +0 -0
  118. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/tests/libcache/bb_oruga_bulma.js +0 -0
  119. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/tests/libcache/bb_vue.js +0 -0
  120. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/tests/libcache/bb_vue_fontawesome.js +0 -0
  121. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/tests/libcache/buefy.css +0 -0
  122. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/tests/libcache/buefy.js +0 -0
  123. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/tests/libcache/fontawesome.js +0 -0
  124. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/tests/libcache/vue.js +0 -0
  125. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/tests/libcache/vue_resource.js +0 -0
  126. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/tests/test_app.py +0 -0
  127. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/tests/test_auth.py +0 -0
  128. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/tests/test_handler.py +0 -0
  129. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/tests/test_helpers.py +0 -0
  130. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/tests/test_menus.py +0 -0
  131. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/tests/test_static.py +0 -0
  132. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/tests/test_subscribers.py +0 -0
  133. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/tests/test_util.py +0 -0
  134. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/tests/util.py +0 -0
  135. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/tests/views/__init__.py +0 -0
  136. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/tests/views/test___init__.py +0 -0
  137. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/tests/views/test_auth.py +0 -0
  138. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/tests/views/test_base.py +0 -0
  139. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/tests/views/test_common.py +0 -0
  140. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/tests/views/test_master.py +0 -0
  141. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/tests/views/test_people.py +0 -0
  142. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/tests/views/test_roles.py +0 -0
  143. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/tests/views/test_settings.py +0 -0
  144. {wuttaweb-0.10.0 → wuttaweb-0.10.2}/tests/views/test_users.py +0 -0
  145. {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
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: WuttaWeb
3
- Version: 0.10.0
3
+ Version: 0.10.2
4
4
  Summary: Web App for Wutta Framework
5
5
  Project-URL: Homepage, https://wuttaproject.org/
6
6
  Project-URL: Repository, https://forgejo.wuttaproject.org/wutta/wuttaweb
@@ -6,7 +6,7 @@ build-backend = "hatchling.build"
6
6
 
7
7
  [project]
8
8
  name = "WuttaWeb"
9
- version = "0.10.0"
9
+ version = "0.10.2"
10
10
  description = "Web App for Wutta Framework"
11
11
  readme = "README.md"
12
12
  authors = [{name = "Lance Edgar", email = "lance@edbob.org"}]
@@ -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, key, label=None, overwrite=True):
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 key: Unique key for the permission group. In the context
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 ``key``.
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 key not in perms:
190
- group = perms.setdefault(key, {'key': key})
191
- group['label'] = label or app.make_title(key)
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 key: Unique key for the permission group. In the context
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
- Note that the values need not be "converted" (to be
918
- JSON-compatible) at this stage, for instance ``colander.null``
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
- The dict should have a key/value for each field in the form.
953
+ It also converts each as needed, to ensure it is
954
+ JSON-serializable.
922
955
 
923
- This method is called by :meth:`render_vue_model_data()` which
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.forms.base.FieldList` instance containing
90
- string column names for the grid. Columns will appear in the
91
- same order as they are in this list.
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
- vs. all data shown at once. Default is ``False`` which means
244
- the full set of grid data is sent for each request.
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.forms.base.FieldList` instance.
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 link depending
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 isinstance(prop.property, orm.ColumnProperty):
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 = self.app.model
613
- grid = Grid(self.request, model_class=model.Person)
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(self.request, columns=['foo', 'bar'], data=data)
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 = self.app.model
729
- grid = Grid(self.request, model_class=model.Person)
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
- ${form.render_vue_tag()}
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
- <script>
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
 
@@ -37,7 +37,7 @@
37
37
  ## paging
38
38
  % if grid.paginated:
39
39
  paginated
40
- pagination-size="is-small"
40
+ pagination-size="${'small' if request.use_oruga else 'is-small'}"
41
41
  :per-page="perPage"
42
42
  :current-page="currentPage"
43
43
  @page-change="onPageChange"
@@ -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
- <script>
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
- app = config.get_app()
466
- model = app.model
467
- if not issubclass(model_class, model.Base):
468
- return
469
-
470
- mapper = sa.inspect(model_class)
471
- fields = [prop.key for prop in mapper.iterate_properties]
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):
@@ -259,7 +259,7 @@ class MasterView(View):
259
259
 
260
260
  .. attribute:: form_fields
261
261
 
262
- List of columns for the model form.
262
+ List of fields for the model form.
263
263
 
264
264
  This is optional; see also :meth:`get_form_fields()`.
265
265
 
@@ -101,6 +101,7 @@ class PersonView(MasterView):
101
101
 
102
102
  @classmethod
103
103
  def defaults(cls, config):
104
+ """ """
104
105
  cls._defaults(config)
105
106
  cls._people_defaults(config)
106
107
 
@@ -246,6 +246,7 @@ class RoleView(MasterView):
246
246
 
247
247
  @classmethod
248
248
  def defaults(cls, config):
249
+ """ """
249
250
  cls._defaults(config)
250
251
  cls._role_defaults(config)
251
252
 
@@ -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