dynamicforms 0.76.14__py3-none-any.whl

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 (287) hide show
  1. dynamicforms/__init__.py +8 -0
  2. dynamicforms/action.py +521 -0
  3. dynamicforms/apps.py +5 -0
  4. dynamicforms/fields.py +1570 -0
  5. dynamicforms/filters.py +44 -0
  6. dynamicforms/locale/en/LC_MESSAGES/django.po +67 -0
  7. dynamicforms/locale/en/LC_MESSAGES/djangojs.po +31 -0
  8. dynamicforms/locale/sl/LC_MESSAGES/django.po +71 -0
  9. dynamicforms/locale/sl/LC_MESSAGES/djangojs.po +36 -0
  10. dynamicforms/management/__init__.py +0 -0
  11. dynamicforms/management/commands/__init__.py +0 -0
  12. dynamicforms/management/commands/clean_dfpreuploaded_files.py +26 -0
  13. dynamicforms/migrations/__init__.py +0 -0
  14. dynamicforms/mixins/__init__.py +27 -0
  15. dynamicforms/mixins/action.py +14 -0
  16. dynamicforms/mixins/choice/__init__.py +94 -0
  17. dynamicforms/mixins/choice/allow_tags.py +79 -0
  18. dynamicforms/mixins/choice/null_choice.py +26 -0
  19. dynamicforms/mixins/choice/single_choice.py +21 -0
  20. dynamicforms/mixins/color_field.py +4 -0
  21. dynamicforms/mixins/conditional_visibility.py +193 -0
  22. dynamicforms/mixins/enable_copy.py +4 -0
  23. dynamicforms/mixins/field_render.py +209 -0
  24. dynamicforms/mixins/file_field.py +5 -0
  25. dynamicforms/mixins/help_text.py +46 -0
  26. dynamicforms/mixins/implicit_hidden.py +7 -0
  27. dynamicforms/mixins/implicit_natural_date.py +88 -0
  28. dynamicforms/mixins/null_value.py +15 -0
  29. dynamicforms/mixins/password_field.py +23 -0
  30. dynamicforms/mixins/related_field_ajax.py +142 -0
  31. dynamicforms/mixins/rtf_field.py +58 -0
  32. dynamicforms/models.py +5 -0
  33. dynamicforms/models_utils.py +33 -0
  34. dynamicforms/pagination.py +175 -0
  35. dynamicforms/preupload_files.py +42 -0
  36. dynamicforms/progress.py +71 -0
  37. dynamicforms/renderers.py +1 -0
  38. dynamicforms/routers.py +36 -0
  39. dynamicforms/serializers.py +486 -0
  40. dynamicforms/struct.py +40 -0
  41. dynamicforms/template_render/__init__.py +10 -0
  42. dynamicforms/template_render/layout.py +178 -0
  43. dynamicforms/template_render/mixins/__init__.py +0 -0
  44. dynamicforms/template_render/mixins/base.py +39 -0
  45. dynamicforms/template_render/mixins/field.py +74 -0
  46. dynamicforms/template_render/mixins/listserializer.py +100 -0
  47. dynamicforms/template_render/mixins/render_mode_enum.py +8 -0
  48. dynamicforms/template_render/mixins/serializer.py +301 -0
  49. dynamicforms/template_render/mixins/serializer_filter.py +19 -0
  50. dynamicforms/template_render/mixins/serializer_render_actions.py +21 -0
  51. dynamicforms/template_render/mixins/serializer_render_fields.py +57 -0
  52. dynamicforms/template_render/mixins/util.py +9 -0
  53. dynamicforms/template_render/renderer.py +38 -0
  54. dynamicforms/template_render/responsive_table_layout.py +64 -0
  55. dynamicforms/urls.py +9 -0
  56. dynamicforms/utils.py +32 -0
  57. dynamicforms/views.py +1 -0
  58. dynamicforms/viewsets.py +421 -0
  59. dynamicforms-0.76.14.dist-info/METADATA +129 -0
  60. dynamicforms-0.76.14.dist-info/RECORD +287 -0
  61. dynamicforms-0.76.14.dist-info/WHEEL +4 -0
  62. dynamicforms-0.76.14.dist-info/licenses/LICENSE +21 -0
  63. dynamicforms_legacy/__init__.py +8 -0
  64. dynamicforms_legacy/action.py +561 -0
  65. dynamicforms_legacy/apps.py +5 -0
  66. dynamicforms_legacy/context_processors.py +27 -0
  67. dynamicforms_legacy/dynamicforms_migration_mixin.py +42 -0
  68. dynamicforms_legacy/fields.py +1108 -0
  69. dynamicforms_legacy/filters.py +44 -0
  70. dynamicforms_legacy/migrations/__init__.py +0 -0
  71. dynamicforms_legacy/mixins/__init__.py +16 -0
  72. dynamicforms_legacy/mixins/action.py +14 -0
  73. dynamicforms_legacy/mixins/allow_tags.py +85 -0
  74. dynamicforms_legacy/mixins/enable_copy.py +4 -0
  75. dynamicforms_legacy/mixins/file_field.py +5 -0
  76. dynamicforms_legacy/mixins/help_text.py +38 -0
  77. dynamicforms_legacy/mixins/implicit_hidden.py +7 -0
  78. dynamicforms_legacy/mixins/implicit_natural_date.py +86 -0
  79. dynamicforms_legacy/mixins/null_choice.py +26 -0
  80. dynamicforms_legacy/mixins/null_value.py +15 -0
  81. dynamicforms_legacy/mixins/password_field.py +19 -0
  82. dynamicforms_legacy/mixins/related_field_ajax.py +58 -0
  83. dynamicforms_legacy/mixins/render.py +203 -0
  84. dynamicforms_legacy/mixins/rtf_field.py +52 -0
  85. dynamicforms_legacy/mixins/single_choice.py +21 -0
  86. dynamicforms_legacy/models.py +5 -0
  87. dynamicforms_legacy/pagination.py +168 -0
  88. dynamicforms_legacy/progress.py +71 -0
  89. dynamicforms_legacy/renderers.py +183 -0
  90. dynamicforms_legacy/serializers.py +335 -0
  91. dynamicforms_legacy/settings.py +196 -0
  92. dynamicforms_legacy/static/bootstrap-3.4.1-dist/css/bootstrap-theme.css +587 -0
  93. dynamicforms_legacy/static/bootstrap-3.4.1-dist/css/bootstrap-theme.css.map +1 -0
  94. dynamicforms_legacy/static/bootstrap-3.4.1-dist/css/bootstrap-theme.min.css +6 -0
  95. dynamicforms_legacy/static/bootstrap-3.4.1-dist/css/bootstrap-theme.min.css.map +1 -0
  96. dynamicforms_legacy/static/bootstrap-3.4.1-dist/css/bootstrap.css +6834 -0
  97. dynamicforms_legacy/static/bootstrap-3.4.1-dist/css/bootstrap.css.map +1 -0
  98. dynamicforms_legacy/static/bootstrap-3.4.1-dist/css/bootstrap.min.css +6 -0
  99. dynamicforms_legacy/static/bootstrap-3.4.1-dist/css/bootstrap.min.css.map +1 -0
  100. dynamicforms_legacy/static/bootstrap-3.4.1-dist/fonts/glyphicons-halflings-regular.eot +0 -0
  101. dynamicforms_legacy/static/bootstrap-3.4.1-dist/fonts/glyphicons-halflings-regular.svg +288 -0
  102. dynamicforms_legacy/static/bootstrap-3.4.1-dist/fonts/glyphicons-halflings-regular.ttf +0 -0
  103. dynamicforms_legacy/static/bootstrap-3.4.1-dist/fonts/glyphicons-halflings-regular.woff +0 -0
  104. dynamicforms_legacy/static/bootstrap-3.4.1-dist/fonts/glyphicons-halflings-regular.woff2 +0 -0
  105. dynamicforms_legacy/static/bootstrap-3.4.1-dist/js/bootstrap.js +2580 -0
  106. dynamicforms_legacy/static/bootstrap-3.4.1-dist/js/bootstrap.min.js +6 -0
  107. dynamicforms_legacy/static/bootstrap-3.4.1-dist/js/npm.js +13 -0
  108. dynamicforms_legacy/static/bootstrap-4.3.1-dist/css/bootstrap-grid.css +3719 -0
  109. dynamicforms_legacy/static/bootstrap-4.3.1-dist/css/bootstrap-grid.css.map +1 -0
  110. dynamicforms_legacy/static/bootstrap-4.3.1-dist/css/bootstrap-grid.min.css +7 -0
  111. dynamicforms_legacy/static/bootstrap-4.3.1-dist/css/bootstrap-grid.min.css.map +1 -0
  112. dynamicforms_legacy/static/bootstrap-4.3.1-dist/css/bootstrap-reboot.css +331 -0
  113. dynamicforms_legacy/static/bootstrap-4.3.1-dist/css/bootstrap-reboot.css.map +1 -0
  114. dynamicforms_legacy/static/bootstrap-4.3.1-dist/css/bootstrap-reboot.min.css +8 -0
  115. dynamicforms_legacy/static/bootstrap-4.3.1-dist/css/bootstrap-reboot.min.css.map +1 -0
  116. dynamicforms_legacy/static/bootstrap-4.3.1-dist/css/bootstrap.css +10038 -0
  117. dynamicforms_legacy/static/bootstrap-4.3.1-dist/css/bootstrap.css.map +1 -0
  118. dynamicforms_legacy/static/bootstrap-4.3.1-dist/css/bootstrap.min.css +7 -0
  119. dynamicforms_legacy/static/bootstrap-4.3.1-dist/css/bootstrap.min.css.map +1 -0
  120. dynamicforms_legacy/static/bootstrap-4.3.1-dist/js/bootstrap.bundle.js +7013 -0
  121. dynamicforms_legacy/static/bootstrap-4.3.1-dist/js/bootstrap.bundle.js.map +1 -0
  122. dynamicforms_legacy/static/bootstrap-4.3.1-dist/js/bootstrap.bundle.min.js +7 -0
  123. dynamicforms_legacy/static/bootstrap-4.3.1-dist/js/bootstrap.bundle.min.js.map +1 -0
  124. dynamicforms_legacy/static/bootstrap-4.3.1-dist/js/bootstrap.js +4435 -0
  125. dynamicforms_legacy/static/bootstrap-4.3.1-dist/js/bootstrap.js.map +1 -0
  126. dynamicforms_legacy/static/bootstrap-4.3.1-dist/js/bootstrap.min.js +7 -0
  127. dynamicforms_legacy/static/bootstrap-4.3.1-dist/js/bootstrap.min.js.map +1 -0
  128. dynamicforms_legacy/static/ckeditor-df/ckEditorCustomBuildReadMe.txt +255 -0
  129. dynamicforms_legacy/static/ckeditor-df/ckeditor.js +6 -0
  130. dynamicforms_legacy/static/dynamicforms/dynamicforms.js +1883 -0
  131. dynamicforms_legacy/static/dynamicforms/icons/copy.svg +7 -0
  132. dynamicforms_legacy/static/dynamicforms/icons/eye-off-outline.svg +10 -0
  133. dynamicforms_legacy/static/dynamicforms/icons/eye-outline.svg +7 -0
  134. dynamicforms_legacy/static/jquery_ui/css/images/ui-bg_diagonals-thick_18_b81900_40x40.png +0 -0
  135. dynamicforms_legacy/static/jquery_ui/css/images/ui-bg_diagonals-thick_20_666666_40x40.png +0 -0
  136. dynamicforms_legacy/static/jquery_ui/css/images/ui-bg_glass_100_f6f6f6_1x400.png +0 -0
  137. dynamicforms_legacy/static/jquery_ui/css/images/ui-bg_glass_100_fdf5ce_1x400.png +0 -0
  138. dynamicforms_legacy/static/jquery_ui/css/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
  139. dynamicforms_legacy/static/jquery_ui/css/images/ui-bg_gloss-wave_35_f6a828_500x100.png +0 -0
  140. dynamicforms_legacy/static/jquery_ui/css/images/ui-bg_highlight-soft_100_eeeeee_1x100.png +0 -0
  141. dynamicforms_legacy/static/jquery_ui/css/images/ui-bg_highlight-soft_75_ffe45c_1x100.png +0 -0
  142. dynamicforms_legacy/static/jquery_ui/css/images/ui-icons_222222_256x240.png +0 -0
  143. dynamicforms_legacy/static/jquery_ui/css/images/ui-icons_228ef1_256x240.png +0 -0
  144. dynamicforms_legacy/static/jquery_ui/css/images/ui-icons_ef8c08_256x240.png +0 -0
  145. dynamicforms_legacy/static/jquery_ui/css/images/ui-icons_ffd27a_256x240.png +0 -0
  146. dynamicforms_legacy/static/jquery_ui/css/images/ui-icons_ffffff_256x240.png +0 -0
  147. dynamicforms_legacy/static/jquery_ui/css/jquery-ui.min.css +7 -0
  148. dynamicforms_legacy/static/jquery_ui/css/jquery-ui.structure.min.css +5 -0
  149. dynamicforms_legacy/static/jquery_ui/css/jquery-ui.theme.min.css +5 -0
  150. dynamicforms_legacy/static/jquery_ui/js/jquery-3.3.1.min.js +2 -0
  151. dynamicforms_legacy/static/jquery_ui/js/jquery-ui.min.js +13 -0
  152. dynamicforms_legacy/static/select2/css/select2-bootstrap3.min.css +7 -0
  153. dynamicforms_legacy/static/select2/css/select2-bootstrap4.min.css +578 -0
  154. dynamicforms_legacy/static/select2/select2-4.0.5/css/select2.min.css +1 -0
  155. dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/af.js +3 -0
  156. dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/ar.js +3 -0
  157. dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/az.js +3 -0
  158. dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/bg.js +3 -0
  159. dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/bs.js +3 -0
  160. dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/ca.js +3 -0
  161. dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/cs.js +3 -0
  162. dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/da.js +3 -0
  163. dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/de.js +3 -0
  164. dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/dsb.js +3 -0
  165. dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/el.js +3 -0
  166. dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/en.js +3 -0
  167. dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/es.js +3 -0
  168. dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/et.js +3 -0
  169. dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/eu.js +3 -0
  170. dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/fa.js +3 -0
  171. dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/fi.js +3 -0
  172. dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/fr.js +3 -0
  173. dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/gl.js +3 -0
  174. dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/he.js +3 -0
  175. dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/hi.js +3 -0
  176. dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/hr.js +3 -0
  177. dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/hsb.js +3 -0
  178. dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/hu.js +3 -0
  179. dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/hy.js +3 -0
  180. dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/id.js +3 -0
  181. dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/is.js +3 -0
  182. dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/it.js +3 -0
  183. dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/ja.js +3 -0
  184. dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/km.js +3 -0
  185. dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/ko.js +3 -0
  186. dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/lt.js +3 -0
  187. dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/lv.js +3 -0
  188. dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/mk.js +3 -0
  189. dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/ms.js +3 -0
  190. dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/nb.js +3 -0
  191. dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/nl.js +3 -0
  192. dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/pl.js +3 -0
  193. dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/ps.js +3 -0
  194. dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/pt-BR.js +3 -0
  195. dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/pt.js +3 -0
  196. dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/ro.js +3 -0
  197. dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/ru.js +3 -0
  198. dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/sk.js +3 -0
  199. dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/sl.js +3 -0
  200. dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/sr-Cyrl.js +3 -0
  201. dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/sr.js +3 -0
  202. dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/sv.js +3 -0
  203. dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/th.js +3 -0
  204. dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/tr.js +3 -0
  205. dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/uk.js +3 -0
  206. dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/vi.js +3 -0
  207. dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/zh-CN.js +3 -0
  208. dynamicforms_legacy/static/select2/select2-4.0.5/js/i18n/zh-TW.js +3 -0
  209. dynamicforms_legacy/static/select2/select2-4.0.5/js/select2.full.js +6457 -0
  210. dynamicforms_legacy/static/select2/select2-4.0.5/js/select2.full.min.js +1 -0
  211. dynamicforms_legacy/static/select2/select2-4.0.5/js/select2.js +5746 -0
  212. dynamicforms_legacy/static/select2/select2-4.0.5/js/select2.min.js +1 -0
  213. dynamicforms_legacy/struct.py +40 -0
  214. dynamicforms_legacy/templates/dynamicforms/base.html +12 -0
  215. dynamicforms_legacy/templates/dynamicforms/base_form.html +44 -0
  216. dynamicforms_legacy/templates/dynamicforms/base_includes.html +51 -0
  217. dynamicforms_legacy/templates/dynamicforms/base_includes_select2.html +6 -0
  218. dynamicforms_legacy/templates/dynamicforms/base_list.html +47 -0
  219. dynamicforms_legacy/templates/dynamicforms/base_table_body.html +46 -0
  220. dynamicforms_legacy/templates/dynamicforms/base_table_filter.html +44 -0
  221. dynamicforms_legacy/templates/dynamicforms/bootstrap/base_form.html +10 -0
  222. dynamicforms_legacy/templates/dynamicforms/bootstrap/base_includes.html +46 -0
  223. dynamicforms_legacy/templates/dynamicforms/bootstrap/base_includes_v3.html +90 -0
  224. dynamicforms_legacy/templates/dynamicforms/bootstrap/base_includes_v4.html +77 -0
  225. dynamicforms_legacy/templates/dynamicforms/bootstrap/base_list.html +9 -0
  226. dynamicforms_legacy/templates/dynamicforms/bootstrap/base_table_body.html +4 -0
  227. dynamicforms_legacy/templates/dynamicforms/bootstrap/base_table_filter.html +5 -0
  228. dynamicforms_legacy/templates/dynamicforms/bootstrap/field/base_field.html +41 -0
  229. dynamicforms_legacy/templates/dynamicforms/bootstrap/field/base_field_v3.html +11 -0
  230. dynamicforms_legacy/templates/dynamicforms/bootstrap/field/base_field_v4.html +11 -0
  231. dynamicforms_legacy/templates/dynamicforms/bootstrap/field/checkbox.html +7 -0
  232. dynamicforms_legacy/templates/dynamicforms/bootstrap/field/checkbox_multiple.html +7 -0
  233. dynamicforms_legacy/templates/dynamicforms/bootstrap/field/fieldset.html +21 -0
  234. dynamicforms_legacy/templates/dynamicforms/bootstrap/field/form.html +4 -0
  235. dynamicforms_legacy/templates/dynamicforms/bootstrap/field/input.html +31 -0
  236. dynamicforms_legacy/templates/dynamicforms/bootstrap/field/list_fieldset.html +18 -0
  237. dynamicforms_legacy/templates/dynamicforms/bootstrap/field/radio.html +8 -0
  238. dynamicforms_legacy/templates/dynamicforms/bootstrap/field/rtf_field.html +4 -0
  239. dynamicforms_legacy/templates/dynamicforms/bootstrap/field/select.html +46 -0
  240. dynamicforms_legacy/templates/dynamicforms/bootstrap/field/select_multiple.html +17 -0
  241. dynamicforms_legacy/templates/dynamicforms/bootstrap/field/textarea.html +4 -0
  242. dynamicforms_legacy/templates/dynamicforms/bootstrap/modal_dialog.html +13 -0
  243. dynamicforms_legacy/templates/dynamicforms/bootstrap/modal_dialog_rest.html +23 -0
  244. dynamicforms_legacy/templates/dynamicforms/bootstrap/page.html +11 -0
  245. dynamicforms_legacy/templates/dynamicforms/field/base_field.html +55 -0
  246. dynamicforms_legacy/templates/dynamicforms/field/checkbox.html +28 -0
  247. dynamicforms_legacy/templates/dynamicforms/field/checkbox_multiple.html +16 -0
  248. dynamicforms_legacy/templates/dynamicforms/field/dict_field.html +4 -0
  249. dynamicforms_legacy/templates/dynamicforms/field/fieldset.html +4 -0
  250. dynamicforms_legacy/templates/dynamicforms/field/form.html +18 -0
  251. dynamicforms_legacy/templates/dynamicforms/field/input.html +31 -0
  252. dynamicforms_legacy/templates/dynamicforms/field/list_field.html +4 -0
  253. dynamicforms_legacy/templates/dynamicforms/field/list_fieldset.html +4 -0
  254. dynamicforms_legacy/templates/dynamicforms/field/radio.html +24 -0
  255. dynamicforms_legacy/templates/dynamicforms/field/rtf_field.html +14 -0
  256. dynamicforms_legacy/templates/dynamicforms/field/select.html +97 -0
  257. dynamicforms_legacy/templates/dynamicforms/field/select_multiple.html +67 -0
  258. dynamicforms_legacy/templates/dynamicforms/field/textarea.html +13 -0
  259. dynamicforms_legacy/templates/dynamicforms/jquery_ui/base_form.html +13 -0
  260. dynamicforms_legacy/templates/dynamicforms/jquery_ui/base_includes.html +225 -0
  261. dynamicforms_legacy/templates/dynamicforms/jquery_ui/base_list.html +9 -0
  262. dynamicforms_legacy/templates/dynamicforms/jquery_ui/base_table_body.html +4 -0
  263. dynamicforms_legacy/templates/dynamicforms/jquery_ui/base_table_filter.html +5 -0
  264. dynamicforms_legacy/templates/dynamicforms/jquery_ui/field/base_field.html +16 -0
  265. dynamicforms_legacy/templates/dynamicforms/jquery_ui/field/checkbox.html +7 -0
  266. dynamicforms_legacy/templates/dynamicforms/jquery_ui/field/checkbox_multiple.html +9 -0
  267. dynamicforms_legacy/templates/dynamicforms/jquery_ui/field/fieldset.html +11 -0
  268. dynamicforms_legacy/templates/dynamicforms/jquery_ui/field/form.html +4 -0
  269. dynamicforms_legacy/templates/dynamicforms/jquery_ui/field/input.html +17 -0
  270. dynamicforms_legacy/templates/dynamicforms/jquery_ui/field/list_fieldset.html +6 -0
  271. dynamicforms_legacy/templates/dynamicforms/jquery_ui/field/radio.html +8 -0
  272. dynamicforms_legacy/templates/dynamicforms/jquery_ui/field/rtf_field.html +4 -0
  273. dynamicforms_legacy/templates/dynamicforms/jquery_ui/field/select.html +37 -0
  274. dynamicforms_legacy/templates/dynamicforms/jquery_ui/field/select_multiple.html +18 -0
  275. dynamicforms_legacy/templates/dynamicforms/jquery_ui/field/textarea.html +4 -0
  276. dynamicforms_legacy/templates/dynamicforms/jquery_ui/modal_dialog.html +2 -0
  277. dynamicforms_legacy/templates/dynamicforms/jquery_ui/modal_dialog_rest.html +27 -0
  278. dynamicforms_legacy/templates/dynamicforms/jquery_ui/page.html +20 -0
  279. dynamicforms_legacy/templates/dynamicforms/modal_dialog.html +4 -0
  280. dynamicforms_legacy/templates/dynamicforms/modal_dialog_rest.html +18 -0
  281. dynamicforms_legacy/templates/dynamicforms/page.html +25 -0
  282. dynamicforms_legacy/templates/dynamicforms/rtf_field_style.html +41 -0
  283. dynamicforms_legacy/templatetags/__init__.py +0 -0
  284. dynamicforms_legacy/templatetags/dynamicforms.py +475 -0
  285. dynamicforms_legacy/urls.py +8 -0
  286. dynamicforms_legacy/views.py +1 -0
  287. dynamicforms_legacy/viewsets.py +366 -0
@@ -0,0 +1,486 @@
1
+ from collections import OrderedDict
2
+ from typing import Any, Dict, List
3
+
4
+ from django.core.exceptions import FieldDoesNotExist
5
+ from django.db import models
6
+ from django.db.models.fields.related import RelatedField
7
+ from rest_framework import serializers
8
+ from rest_framework.fields import get_attribute, SkipField
9
+
10
+ from dynamicforms.action import Actions
11
+ from dynamicforms.template_render import ViewModeSerializer
12
+
13
+ from . import fields
14
+ from .mixins import ActionMixin, DisplayMode, FieldRenderMixin
15
+ from .struct import StructDefault
16
+ from .utils import get_pk_name
17
+
18
+
19
+ class DynamicFormsSerializer(ViewModeSerializer, FieldRenderMixin, ActionMixin):
20
+ template_context = {} # see ViewSet.template_context
21
+ actions = Actions(add_default_crud=True, add_form_buttons=True)
22
+ form_titles = {
23
+ "table": "",
24
+ "new": "",
25
+ "edit": "",
26
+ }
27
+
28
+ def __init__(self, *args, is_filter: bool = False, **kwds):
29
+ self.master = None
30
+ self.is_filter = is_filter
31
+ if self.is_filter:
32
+ try:
33
+ instance = self.Meta.model()
34
+ for fld in instance._meta.fields:
35
+ setattr(instance, fld.name, None)
36
+ except:
37
+ instance = StructDefault(_default_=None)
38
+ kwds.setdefault("instance", instance)
39
+ super().__init__(*args, **kwds)
40
+ if self.is_filter:
41
+ for field_name, field in self.fields.items():
42
+ field.default = None
43
+ field.allow_blank = True
44
+ field.allow_null = True
45
+ field.read_only = False
46
+ # the following ifs are actually redundant because front-end code currently doesn't even obey this
47
+ # it always renders the columns as visible in the table, except that in filter row, it takes
48
+ # the non-display fields for filtering instead of the resolved texts that can't be filtered
49
+ if (field_name + "-display") in self.fields.keys():
50
+ # if field has a resolved display counterpart (Choice, Related), show the original field
51
+ pass
52
+ elif field_name.endswith("-display"):
53
+ # if field is the resolved display counterpart, don't show it in filter row
54
+ pass
55
+ else:
56
+ field.display_form = field.display_table # filter's form is same as non-filter's table
57
+ field.allow_tags = False
58
+ field.password_field = False
59
+
60
+ @property
61
+ def has_non_field_errors(self):
62
+ """
63
+ Reports whether validation turned up any form-wide validation errors. Used in templates to render the form-wide
64
+ error message
65
+
66
+ :return: True | False depending on whether form validation failed
67
+ """
68
+ if hasattr(self, "_errors"):
69
+ return "non_field_errors" in self.errors
70
+ return False
71
+
72
+ @property
73
+ def page_title(self):
74
+ """
75
+ Returns page title from form_titles based on the rendered data
76
+ :return string: page title
77
+ """
78
+ if self.render_type == "table":
79
+ return self.form_titles.get("table", "")
80
+ elif self.data.get("id", None):
81
+ return self.form_titles.get("edit", "")
82
+ else:
83
+ return self.form_titles.get("new", "")
84
+
85
+ # noinspection PyProtectedMember
86
+ @property
87
+ def filter_data(self):
88
+ """
89
+ Returns serializer for filter row in table
90
+ :return: Serializer
91
+ """
92
+ if self.view_mode == ViewModeSerializer.ViewMode.FORM:
93
+ return None
94
+ if getattr(self, "_filter_ser", None) is None:
95
+ # noinspection PyAttributeOutsideInit
96
+ self._filter_ser = type(self)(is_filter=True, context=getattr(self, "context", {}))
97
+ self._filter_ser.master = self
98
+ return self._filter_ser # Just create the same serializer in filter mode (None values, allow_nulls)
99
+
100
+ # noinspection PyUnusedLocal
101
+ def suppress_action(self, action, request, viewset):
102
+ """
103
+ Determines whether rendering an action into the DOM should be suppressed. Use when some users don't have access
104
+ to some of the functionality, e.g. when CRUD functionality is only enabled for administrative users
105
+ :param action: action to be checked
106
+ :param request: request that triggered the render (may be None)
107
+ :param viewset: viewset that provided the serialized data (may be None)
108
+ :return: boolean whether action should render (False) or not (True)
109
+ """
110
+ return False
111
+
112
+ @property
113
+ def renderable_actions(self: "serializers.Serializer"):
114
+ """
115
+ Returns those actions that are not suppressed
116
+ :return: List[Action]
117
+ """
118
+ # TODO: Ta funkcija po mojem mora odletet (self.*controls*.actions). Sam zakaj ne? Ali se sploh ne uporablja?
119
+ request = self.context.get("request", None)
120
+ viewset = self.context.get("view", None)
121
+ return [action for action in self.controls.actions if not self.suppress_action(action, request, viewset)]
122
+
123
+ # noinspection PyUnresolvedReferences
124
+ def get_initial(self) -> Any:
125
+ if getattr(self, "_errors", None):
126
+ # This basically reproduces BaseSerializer.data property except that it disregards the _errors member
127
+ if self.instance:
128
+ res = self.to_representation(self.instance)
129
+ # elif hasattr(self, '_validated_data'):
130
+ # res = self.to_representation(self.validated_data)
131
+ else:
132
+ res = {}
133
+ res.update(super().get_initial())
134
+
135
+ return res
136
+
137
+ return super().get_initial()
138
+
139
+ # noinspection PyUnresolvedReferences
140
+ @property
141
+ def _writable_fields(self):
142
+ """
143
+ Overrides DRF.serializers.Serializer._writable_fields
144
+ This one in particular should return exactly the same list as DRF's version (as of 17.4.2020, DRF version 3.11
145
+ """
146
+ return (field for field in self.fields.values() if not field.read_only)
147
+
148
+ # noinspection PyUnresolvedReferences
149
+ @property
150
+ def _readable_fields(self):
151
+ """
152
+ Overrides DRF.serializers.Serializer._readable_fields
153
+ This one adds additional checks on top of DRF's ones - checking if the field is renderable to table or form
154
+ """
155
+ return (
156
+ field
157
+ for field in self.fields.values()
158
+ if not (
159
+ field.write_only
160
+ or (self.display_table == DisplayMode.SUPPRESS and self.display_form == DisplayMode.SUPPRESS)
161
+ )
162
+ )
163
+
164
+ def to_representation(self, instance, row_data=None):
165
+ """
166
+ Object instance -> Dict of primitive datatypes.
167
+ """
168
+ ret = OrderedDict()
169
+ for field in self._readable_fields:
170
+ try:
171
+ attribute = field.get_attribute(instance)
172
+ if not isinstance(field, FieldRenderMixin):
173
+ ret[field.field_name] = field.to_representation(attribute)
174
+ else:
175
+ try:
176
+ ret[field.field_name] = field.to_representation(attribute, instance)
177
+ except:
178
+ if attribute is None and not field.required:
179
+ # DRF makes a special check for none and then always returns None if the check is None.
180
+ # We still want to process custom field to_representation, even if value is None.
181
+ # But when field is a sub-serializer and it (it's FK reference) is none, it's OK
182
+ # to pass None as result of serialization of such field
183
+ raise SkipField()
184
+ else:
185
+ raise
186
+ except SkipField:
187
+ pass
188
+
189
+ return ret
190
+
191
+ # noinspection PyMethodMayBeStatic
192
+ def get_row_css_style(self, obj):
193
+ return ""
194
+
195
+
196
+ class ModelSerializer(DynamicFormsSerializer, serializers.ModelSerializer):
197
+ """
198
+ DynamicForms' ModelSerializer overrides the following behaviour over DRF's implementation:
199
+
200
+ * Uses own field types for construction
201
+ * Adds form UUID (rendered in html too)
202
+ * Adds processing for form-wide errors
203
+
204
+ DRF's docstring copied verbatim:
205
+
206
+ A `ModelSerializer` is just a regular `Serializer`, except that:
207
+
208
+ * A set of default fields are automatically populated.
209
+ * A set of default validators are automatically populated.
210
+ * Default `.create()` and `.update()` implementations are provided.
211
+
212
+ The process of automatically determining a set of serializer fields
213
+ based on the model fields is reasonably complex, but you almost certainly
214
+ don't need to dig into the implementation.
215
+
216
+ If the `ModelSerializer` class *doesn't* generate the set of fields that
217
+ you need you should either declare the extra/differing fields explicitly on
218
+ the serializer class, or simply use a `Serializer` class.
219
+ """
220
+
221
+ def __init__(self, *args, is_filter: bool = False, **kwds):
222
+ if hasattr(self, "Meta") and hasattr(self.Meta, "fields"):
223
+ self._make_df_special_fields_present_in_fields(["df_prev_id", "row_css_style", "df_control_data"])
224
+ super().__init__(*args, is_filter=is_filter, **kwds)
225
+ self.manage_changed_flds()
226
+ self._decorate_fields()
227
+
228
+ def _decorate_fields(self):
229
+ def pop(self, name: str, default):
230
+ super(self.__class__, self).pop(name, default)
231
+ super(self.__class__, self).pop(name + "-display", None)
232
+
233
+ self.fields.pop = pop.__get__(self.fields)
234
+ # copy the labels to resolved -display fields
235
+ for field in self.fields:
236
+ if field.endswith("-display"):
237
+ self.fields[field].label = self.fields[field[:-8]].label
238
+
239
+ def _make_df_special_fields_present_in_fields(self, fields):
240
+ for f in fields:
241
+ if self.Meta.fields != "__all__" and f not in self.Meta.fields:
242
+ self.Meta.fields += (f,)
243
+
244
+ serializer_field_mapping = {
245
+ models.AutoField: fields.IntegerField,
246
+ models.BigIntegerField: fields.IntegerField,
247
+ models.BooleanField: fields.BooleanField,
248
+ models.NullBooleanField: fields.BooleanField,
249
+ models.CharField: fields.CharField,
250
+ models.CommaSeparatedIntegerField: fields.CharField,
251
+ models.DateField: fields.DateField,
252
+ models.DateTimeField: fields.DateTimeField,
253
+ models.DecimalField: fields.DecimalField,
254
+ models.EmailField: fields.EmailField,
255
+ models.Field: fields.ModelField,
256
+ models.FileField: fields.FileField,
257
+ models.FloatField: fields.FloatField,
258
+ models.ImageField: fields.ImageField,
259
+ models.IntegerField: fields.IntegerField,
260
+ models.PositiveIntegerField: fields.IntegerField,
261
+ models.PositiveSmallIntegerField: fields.IntegerField,
262
+ models.SlugField: fields.SlugField,
263
+ models.SmallIntegerField: fields.IntegerField,
264
+ models.TextField: fields.CharField,
265
+ models.TimeField: fields.TimeField,
266
+ models.URLField: fields.URLField,
267
+ models.GenericIPAddressField: fields.IPAddressField,
268
+ models.FilePathField: fields.FilePathField,
269
+ models.JSONField: fields.JSONField,
270
+ }
271
+ if models.DurationField is not None:
272
+ serializer_field_mapping[models.DurationField] = fields.DurationField
273
+
274
+ serializer_related_field = fields.PrimaryKeyRelatedField
275
+ serializer_related_to_field = fields.SlugRelatedField
276
+ serializer_url_field = fields.HyperlinkedIdentityField
277
+ serializer_choice_field = fields.ChoiceField
278
+
279
+ def get_field_names(self, declared_fields, info):
280
+ # we're just converting DRF's tuple to list here because we need it modifiable in get_uniqueness_extra_kwargs
281
+ return list(super().get_field_names(declared_fields, info))
282
+
283
+ def get_extra_kwargs(self):
284
+ res = super().get_extra_kwargs()
285
+ # noinspection PyUnresolvedReferences
286
+ for fld in self.Meta.model._meta.fields:
287
+ # We're exploiting DRF design "feature" here where DRF only perceives a field as declared if it's a Field
288
+ # instance. AutoGeneratedField is not a Field instance and will thus be overwritten by auto generated field
289
+ # Note how Field instances are already removed from the class here.
290
+ # They reappear in the get_uniqueness_extra_kwargs method below
291
+ fld_name = fld.db_column or fld.name
292
+ value = getattr(self, fld_name, None)
293
+ if isinstance(value, fields.AutoGeneratedField):
294
+ res.setdefault(fld_name, {})
295
+ res[fld_name].update(value)
296
+ return res
297
+
298
+ def get_uniqueness_extra_kwargs(self, field_names: List[str], declared_fields: Dict, extra_kwargs: Dict):
299
+ """
300
+ Finds all ChoiceFields and RelatedFields and creates additional "-display" fields to show
301
+ resolved display value in table
302
+ """
303
+ for field_name in field_names[:]:
304
+ # serializer field: either what is declared as a Field instance in Serializer or AutogeneratedField
305
+ s_field = declared_fields.get(field_name, getattr(self, field_name, None))
306
+ # existing extra as provided by get_extra_kwargs
307
+ extra = extra_kwargs.get(field_name, dict())
308
+ # model field, if it exists
309
+ try:
310
+ d_field = self.Meta.model._meta.get_field(field_name)
311
+ except FieldDoesNotExist:
312
+ d_field = None
313
+
314
+ if d_field and d_field.name == get_pk_name(self.Meta.model):
315
+ # hide the primary key field (DRF only marks it as R/O)
316
+ field_name = get_pk_name(self.Meta.model)
317
+ if field_name not in declared_fields and "display" not in extra:
318
+ extra.setdefault("display_form", fields.DisplayMode.HIDDEN)
319
+ extra.setdefault("display_table", fields.DisplayMode.FULL)
320
+ extra_kwargs[field_name] = extra
321
+
322
+ if isinstance(s_field, (fields.ChoiceMixin, fields.RelatedFieldAJAXMixin)) or (
323
+ # if custom field properties are declared and they are either ChoiceField or RelatedField
324
+ isinstance(d_field, RelatedField) # DB field is a relation
325
+ or getattr(d_field, "choices", None) # DB field has choices
326
+ ):
327
+ if (s_field and getattr(s_field, "display_table", DisplayMode.SUPPRESS) == DisplayMode.SUPPRESS) or (
328
+ hasattr(self, "Meta") and hasattr(self.Meta, "exclude") and field_name in self.Meta.exclude
329
+ ):
330
+ # if the field is set to not display in the table, don't create the resolved field
331
+ continue
332
+
333
+ # original field does not display in the table
334
+ if field_name in declared_fields:
335
+ # declared fields cannot also have extra_kwargs (there is a continue in the loop)
336
+ s_field.display_table = DisplayMode.HIDDEN
337
+ else:
338
+ extra["display_table"] = DisplayMode.HIDDEN
339
+ extra_kwargs[field_name] = extra
340
+
341
+ resolved_field_name = f"{field_name}-display"
342
+ # if resolved_field_name in declared_fields or resolved_field_name in extra_kwargs:
343
+ # raise ValueError(f"We were going to add a table resolved field '{resolved_field_name}' but "
344
+ # f"a field with this name is already declared in "
345
+ # f"the serializer {self.__class__.__name__")
346
+ field_names.insert(field_names.index(field_name) + 1, resolved_field_name)
347
+ declared_fields[resolved_field_name] = fields.SerializerMethodField(
348
+ source="*",
349
+ display_form=DisplayMode.HIDDEN,
350
+ display_table=DisplayMode.FULL,
351
+ render_params=s_field.render_params if s_field else None,
352
+ )
353
+
354
+ def get_resolve_method(fld_nm, res_fld):
355
+ def resolve_choice_field(self, value):
356
+ from dynamicforms.fields import ManyRelatedField
357
+
358
+ if (
359
+ isinstance(self.fields[fld_nm], ManyRelatedField)
360
+ and value
361
+ and not getattr(value, "pk", None)
362
+ ):
363
+ return None
364
+
365
+ source_attr = self.fields[fld_nm].source_attrs
366
+ row_data = value
367
+ try:
368
+ value = get_attribute(value, source_attr)
369
+ except:
370
+ value = None
371
+
372
+ return self.fields[fld_nm].render_to_table(
373
+ # getattr has a default == None because the object might be a new init and
374
+ # will not have relations
375
+ value,
376
+ row_data,
377
+ )
378
+
379
+ return resolve_choice_field
380
+
381
+ setattr(
382
+ self,
383
+ f"get_{resolved_field_name}",
384
+ get_resolve_method(field_name, resolved_field_name).__get__(self),
385
+ )
386
+
387
+ if hasattr(self, "Meta") and hasattr(self.Meta, "fields"):
388
+ if isinstance(self.Meta.fields, tuple):
389
+ self.Meta.fields = list(self.Meta.fields)
390
+ self.Meta.fields.append(resolved_field_name)
391
+
392
+ # print(
393
+ # f"We will be creating a resolved field for field {field_name}. "
394
+ # f"Field is already custom-declared: {bool(s_field)}"
395
+ # )
396
+ pass
397
+
398
+ return super().get_uniqueness_extra_kwargs(field_names, declared_fields, extra_kwargs)
399
+
400
+ # noinspection PyUnresolvedReferences
401
+ def manage_changed_flds(self):
402
+ """
403
+ When there is a need to only change few parameters of a field put those fields and changed parameters in
404
+ serializers Meta class in parameter changed_flds.
405
+
406
+ Example:
407
+
408
+ .. code-block:: python
409
+
410
+ changed_flds = {
411
+ 'id': dict(display=DisplayMode.HIDDEN),
412
+ 'comment': dict(label='Comm', help_text='Help text for comment field')
413
+ }
414
+
415
+ :return:
416
+
417
+ """
418
+ if hasattr(self.Meta, "changed_flds"):
419
+ import warnings
420
+
421
+ warnings.warn(
422
+ f"""
423
+ {self.__class__.__module__}.{self.__class__.__name__}:
424
+ changed_flds has been found to be a duplicate of DRF's extra_kwargs Meta member. Either use
425
+ extra_kwargs or the preferred field = AutoGeneratedField(**kwargs) declaration.
426
+ """,
427
+ DeprecationWarning,
428
+ stacklevel=6,
429
+ )
430
+ for field, params in self.Meta.changed_flds.items():
431
+ field_def = self.fields.get(field, None)
432
+ if field_def:
433
+ for key, val in params.items():
434
+ setattr(field_def, key, val)
435
+
436
+ # Dynamic forms default field that is used to contain data for positioning (id of previous record)
437
+ df_prev_id = fields.SerializerMethodField(display=DisplayMode.HIDDEN)
438
+
439
+ # this is a calculated field that returns css style for table row
440
+ row_css_style = fields.SerializerMethodField(display=DisplayMode.HIDDEN)
441
+
442
+ def fetch_prev_id(self, obj, view):
443
+ ordering = "id"
444
+ try:
445
+ ordering = view.pagination_class.ordering
446
+ except:
447
+ pass
448
+ if ordering != "id":
449
+ query_params = self.context["request"].query_params
450
+ query_params._mutable = True
451
+ query_params.pop("id", "")
452
+ queryset = view.filter_queryset(queryset=view.get_queryset(), query_params=query_params)
453
+ records = list(queryset.order_by(ordering))
454
+ curr_index = records.index(obj)
455
+ prev_id = None
456
+ if curr_index > 0:
457
+ prev_id = records[curr_index - 1].id
458
+
459
+ return prev_id
460
+
461
+ return ""
462
+
463
+ # noinspection PyMethodMayBeStatic
464
+ def get_df_prev_id(self, obj):
465
+ try:
466
+ if self.context["request"].META.get("HTTP_X_DF_CALLTYPE", "") == "refresh_record":
467
+ view = self.context.get("view", None)
468
+ if view:
469
+ return self.fetch_prev_id(obj, view)
470
+ except:
471
+ pass
472
+
473
+ return ""
474
+
475
+ def render_to_table(self, value, row_data):
476
+ return str(value) if value is not None else None
477
+
478
+
479
+ class Serializer(DynamicFormsSerializer, serializers.Serializer):
480
+ def update(self, instance, validated_data):
481
+ # Implemented just so IDE doesn't complain. Normally this will be handled in SingleRecordViewSet
482
+ pass
483
+
484
+ def create(self, validated_data):
485
+ # Implemented just so IDE doesn't complain. Normally this will be handled in SingleRecordViewSet
486
+ pass
dynamicforms/struct.py ADDED
@@ -0,0 +1,40 @@
1
+ class Struct(object):
2
+ def __init__(self, data=None, **kwds):
3
+ if not data:
4
+ data = {}
5
+ for name, value in data.items():
6
+ if name:
7
+ setattr(self, name, self._wrap(value))
8
+ for name, value in kwds.items():
9
+ if name:
10
+ setattr(self, name, self._wrap(value))
11
+
12
+ def _wrap(self, value):
13
+ if isinstance(value, (tuple, list, set, frozenset)):
14
+ return type(value)([self._wrap(v) for v in value])
15
+ else:
16
+ return Struct(value) if isinstance(value, dict) else value
17
+
18
+ def clone(self, **kwds):
19
+ return Struct(self.__to_dict__(), **kwds)
20
+
21
+ def __repr__(self):
22
+ return "Struct: " + repr(self.__dict__)
23
+
24
+ def __len__(self):
25
+ return len(self.__dict__)
26
+
27
+ def __to_dict__(self):
28
+ res = {}
29
+ res.update(self.__dict__)
30
+ for k in res.keys():
31
+ if isinstance(res[k], Struct):
32
+ res[k] = res[k].__to_dict__()
33
+ elif isinstance(res[k], (tuple, list, set, frozenset)):
34
+ res[k] = [i.__to_dict__() if isinstance(i, Struct) else i for i in res[k]]
35
+ return res
36
+
37
+
38
+ class StructDefault(Struct):
39
+ def __getattr__(self, item):
40
+ return self._default_
@@ -0,0 +1,10 @@
1
+ """
2
+ What DynamicForms is about: ability to render a Serializer directly in Django template --> HTML
3
+ This module allows for it. It defines __str__ method on Serializer, ListSerializer and Field instances to render to HTML
4
+ """
5
+ from .mixins.field import ViewModeField
6
+ from .mixins.listserializer import ViewModeListSerializer
7
+ from .mixins.serializer import ViewModeSerializer
8
+ from .renderer import ComponentDefRenderer
9
+
10
+ __all__ = (ViewModeField, ViewModeSerializer, ViewModeListSerializer, ComponentDefRenderer)