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,366 @@
1
+ from datetime import datetime, timedelta
2
+ from typing import List, Union
3
+
4
+ import pytz
5
+
6
+ from django.conf import settings
7
+ from django.contrib.auth.views import redirect_to_login
8
+ from django.db import models
9
+ from django.http import Http404
10
+ from rest_framework import status, viewsets
11
+ from rest_framework.exceptions import ValidationError
12
+ from rest_framework.renderers import JSONRenderer
13
+ from rest_framework.response import Response
14
+ from rest_framework.serializers import ListSerializer
15
+ from rest_framework.utils.serializer_helpers import ReturnDict, ReturnList
16
+
17
+ from dynamicforms_legacy.fields import BooleanField
18
+
19
+ from .renderers import TemplateHTMLRenderer
20
+ from .settings import DYNAMICFORMS
21
+
22
+
23
+ class NewMixin(object):
24
+ """
25
+ Provides support for retrieving default values for a new record.
26
+
27
+ Caution: Do not use directly. This is only a mixin and is used in final ViewSet derivatives.
28
+ """
29
+
30
+ def new_object(self: viewsets.ModelViewSet):
31
+ """
32
+ Returns a new model instance. If you need it pre-populated with default values, this is the method to override.
33
+
34
+ :return: model instance
35
+ """
36
+ # TODO: This function must return an object that has its field values correctly / realistically filled out
37
+ # Example: if a certain field's value hides (sets another field to None), then that second field can't be
38
+ # set to 42, can it?
39
+ # can we run some kind of validation to enforce this?
40
+ # Not that easy: the returned record may not validate for its (correctly) empty fields
41
+ # Maybe we will have to run JavaScript onchange for all fields displayed to ensure at least some consistency?
42
+ # If we do not, subsequent validation may fail because a hidden field has a value
43
+ field_names = [
44
+ (f.name + "_id") if isinstance(f, models.ForeignKey) else f.name
45
+ for f in self.get_queryset().model._meta.fields
46
+ ]
47
+ instantiation_params = {k: v for k, v in self.request.GET.items() if k in field_names}
48
+ return self.get_queryset().model(**instantiation_params)
49
+
50
+ # noinspection PyUnresolvedReferences
51
+ def retrieve(self: viewsets.ModelViewSet, request, *args, **kwargs):
52
+ try:
53
+ if not hasattr(super(), "retrieve"):
54
+ raise Http404() # This is not a ModelViewSet, so we don't have a retrieval mechanism
55
+ return super().retrieve(request, *args, **kwargs)
56
+ except Http404:
57
+ lookup_url_kwarg = self.lookup_url_kwarg or self.lookup_field
58
+ filter_kwargs = {self.lookup_field: self.kwargs[lookup_url_kwarg]}
59
+ if filter_kwargs.get("pk", None) == "new":
60
+ instance = self.new_object()
61
+ serializer = self.get_serializer(instance)
62
+ return Response(serializer.data)
63
+ else:
64
+ raise
65
+
66
+
67
+ class PutPostMixin(object):
68
+ """
69
+ Provides support for when there is no record id in URL when calling PUT
70
+ (First empty form is loaded. Than user loads existing data to this form and updates it... - Perform PUT action)
71
+
72
+ or
73
+
74
+ Provides support for when there is record id in URL when calling POST
75
+ (First form for some existing record is loaded. Than user wants to create new record for it.
76
+ - deletes redord ID and perform POST action)
77
+ """
78
+
79
+ # When there is no record id in URL when calling PUT, this function will be called
80
+ # noinspection PyUnresolvedReferences
81
+ def put(self: viewsets.ModelViewSet, request, *args, **kwargs):
82
+ self.kwargs["pk"] = request.data["id"]
83
+ return self.update(request, *args, **kwargs)
84
+
85
+ # When there is record id in URL when calling POST, this function will be called
86
+ # noinspection PyUnresolvedReferences
87
+ def post(self: viewsets.ModelViewSet, request, *args, **kwargs):
88
+ return self.create(request, *args, **kwargs)
89
+
90
+
91
+ class TemplateRendererMixin:
92
+ template_context = {}
93
+ """
94
+ template_context provides configuration to templates being rendered
95
+
96
+ Note that when adding data from database, it is advised to make this definition a callable so that it is evaluated
97
+ on each render of the ViewSet: that way you can ensure data is always loaded fresh from database.
98
+ This member can also be defined in the serializer class. If that is the case, it will be copied to ViewSet.
99
+
100
+ e.g.
101
+
102
+ .. code-block:: python
103
+
104
+ template_context = lambda self: dict(items=MyModel.objects.all())
105
+
106
+ or
107
+
108
+ .. code-block:: python
109
+
110
+ def template_context(self):
111
+ return dict(items=MyModel.objects.all())
112
+ """
113
+
114
+ template_name = DYNAMICFORMS.table_base_template #: template filename for listing multiple records (html renderer)
115
+
116
+ def __init__(self, *args, **kwds):
117
+ if not self.template_context and getattr(self, "serializer_class", None) is not None:
118
+ self.template_context = getattr(self.serializer_class, "template_context", {})
119
+ super().__init__(*args, **kwds)
120
+
121
+ # noinspection PyAttributeOutsideInit
122
+ def initialize_request(self, request, *args, **kwargs):
123
+ # Caution: just to be sure for any future debugging: the request parameter to this function is a WSGIRequest
124
+ # while the return Request is actually DRF Request
125
+ # As a consequence, form values don't get parsed until you actually call super().initialize_request
126
+ # There's no "request.data", etc. Just saying. So you don't debug for two hours next time. By "you" I mean me
127
+
128
+ # Force render using a given render path (full page, table, table rows, form, dialog with form)
129
+ self.render_type = request.META.get("HTTP_X_DF_RENDER_TYPE", request.GET.get("df_render_type", "page"))
130
+
131
+ if request.method.lower() == "post" and request.POST.get("data-dynamicforms-method", None):
132
+ # This is a hack because HTML forms can only do POST & GET. This way we also get PUT & PATCH
133
+ request.method = request.POST.get("data-dynamicforms-method")
134
+ # If we don't set this META, django won't recognise our CSRF token
135
+ request.META["HTTP_X_CSRFTOKEN"] = request.POST["csrfmiddlewaretoken"]
136
+ return super().initialize_request(request, *args, **kwargs)
137
+
138
+ def finalize_response(self, request, response, *args, **kwargs):
139
+ if not isinstance(response, Response):
140
+ return response
141
+
142
+ res = super().finalize_response(request, response, *args, **kwargs)
143
+
144
+ def get_query_params():
145
+ if request.query_params:
146
+ return "?" + "&".join(["%s=%s" % (key, value) for key, value in request.query_params.items()])
147
+ return ""
148
+
149
+ if isinstance(res.accepted_renderer, TemplateHTMLRenderer):
150
+ if status.is_success(res.status_code) or res.status_code == status.HTTP_400_BAD_REQUEST:
151
+ if (
152
+ isinstance(res.data, dict)
153
+ and "next" in res.data
154
+ and "results" in res.data
155
+ and isinstance(res.data["results"], (ReturnList, ReturnDict))
156
+ ):
157
+ serializer = res.data["results"].serializer
158
+ else:
159
+ try:
160
+ serializer = res.data.serializer
161
+ except AttributeError:
162
+ # This happens when there's a ValidationError on LIST command
163
+ res.accepted_renderer = JSONRenderer()
164
+ return res
165
+
166
+ if isinstance(serializer, ListSerializer):
167
+ serializer.child.render_type = self.render_type
168
+ else:
169
+ serializer.render_type = self.render_type
170
+
171
+ if self.render_type in ("table", "table rows"):
172
+ serializer.data_template = self.template_name
173
+ elif self.render_type == "dialog":
174
+ serializer.data_template = DYNAMICFORMS.modal_dialog_rest_template
175
+ res.template_name = DYNAMICFORMS.modal_dialog_rest_template
176
+ elif self.render_type == "form":
177
+ serializer.data_template = res.data.serializer.template_name
178
+ res.template_name = res.data.serializer.template_name
179
+ else:
180
+ if isinstance(serializer, ListSerializer):
181
+ serializer.child.render_type = "table"
182
+ serializer.child.data_template = self.template_name
183
+ else:
184
+ serializer.render_type = "form"
185
+ serializer.data_template = serializer.template_name
186
+ elif (
187
+ res.status_code in (status.HTTP_401_UNAUTHORIZED, status.HTTP_403_FORBIDDEN)
188
+ and self.render_type != "dialog"
189
+ ):
190
+ # TODO: We should show a message here that user is not authorized for this action (only for 403)
191
+ if not request.is_ajax():
192
+ res = redirect_to_login(request.path_info + get_query_params())
193
+ return res
194
+
195
+
196
+ class ModelViewSet(NewMixin, PutPostMixin, TemplateRendererMixin, viewsets.ModelViewSet):
197
+ """
198
+ In addition to all the functionality, provided by DRF, DynamicForms ViewSet has some extra features:
199
+
200
+ * Separate templates for rendering list or single record
201
+ * You can request a "new" record and even have it pre-populated with values
202
+ * To render viewset as API or JSON use the same method as in DRF: To render it in HTML just add ".html" to the URL.
203
+ * Standard DRF router URL patterns apply:
204
+
205
+ * To render a new record use pk=new.
206
+ * To render an existing record (for editing) use pk={record_id}.
207
+
208
+ """
209
+
210
+ def paginate_queryset(self, queryset):
211
+ """
212
+ Return a single page of results, or `None` if pagination is disabled.
213
+ """
214
+ if self.paginator is None:
215
+ return None
216
+ # determine request format and handle pagination for json format
217
+ if isinstance(self.request.accepted_renderer, JSONRenderer) and not BooleanField().to_internal_value(
218
+ self.request.META.get("HTTP_X_PAGINATION", self.request.GET.get("x_df_pagination", False))
219
+ ):
220
+ return None
221
+ return self.paginator.paginate_queryset(queryset, self.request, view=self)
222
+
223
+ def get_queryset(self):
224
+ """
225
+ Returns records from queryset with filters applied
226
+
227
+ :return: filtered records
228
+ """
229
+ return super().get_queryset()
230
+
231
+ def filter_queryset(self, queryset, query_params=None):
232
+ """
233
+ Applies filters for all fields
234
+
235
+ :param queryset: Queryset
236
+ :param query_params: Custom query_params if needed
237
+ :return: queryset with filters applied
238
+ """
239
+ res = super().filter_queryset(queryset)
240
+ if self.request:
241
+ if query_params is None:
242
+ query_params = self.request.query_params
243
+ for fld, val in query_params.items():
244
+ res = self.filter_queryset_field(res, fld, val)
245
+ for backend in self.filter_backends:
246
+ if hasattr(backend, "get_ordering"):
247
+ ordering = backend().get_ordering(self.request, queryset, self)
248
+ if ordering:
249
+ self.ordering = ordering
250
+ break
251
+ return res
252
+
253
+ # noinspection PyMethodMayBeStatic
254
+ def filter_queryset_field(self, queryset, field, value):
255
+ """
256
+ Applies filter to individual field
257
+
258
+ :param queryset: Queryset
259
+ :param field: Field name
260
+ :param value: Field value
261
+ :return: queryset with applied filter for the field
262
+ """
263
+ if value is None or value == "":
264
+ return queryset
265
+
266
+ model_meta = queryset.model._meta
267
+
268
+ if field not in (fld.name for fld in model_meta.get_fields()):
269
+ return queryset
270
+
271
+ # TODO: this would probably be better moved into the fields themselves
272
+ if isinstance(model_meta.get_field(field), (models.CharField, models.TextField)):
273
+ return queryset.filter(**{field + "__icontains": value})
274
+ if isinstance(model_meta.get_field(field), (models.DateField, models.DateTimeField)):
275
+ date_time = None
276
+ for date_time_fmt in [settings.DATETIME_FORMAT, "%Y-%m-%dT%H:%M:%S", settings.DATE_FORMAT, "%Y-%m-%d"]:
277
+ try:
278
+ date_time = datetime.strptime(value, date_time_fmt)
279
+ break
280
+ except:
281
+ pass
282
+ if date_time is None:
283
+ return queryset
284
+ date_time = pytz.timezone(settings.TIME_ZONE).localize(date_time).astimezone(pytz.utc)
285
+ if len(value) <= 10:
286
+ return queryset.filter(**{field + "__gte": date_time, field + "__lt": date_time + timedelta(days=1)})
287
+ return queryset.filter(**{field + "__gte": date_time, field + "__lt": date_time + timedelta(seconds=1)})
288
+ else:
289
+ if isinstance(model_meta.get_field(field), models.BooleanField):
290
+ value = value == "true"
291
+ return queryset.filter(**{field: value})
292
+
293
+ @staticmethod
294
+ def generate_paged_loader(page_size: int = 30, ordering: Union[str, List[str]] = "id"):
295
+ """
296
+ Generates a Pagination class that will handle dynamic data loading for ViewSets with a lot of data.
297
+ Use by declaring `pagination_class = ModelViewSet.generate_paged_loader()` in class variables
298
+
299
+ :param page_size: how many records should be fetched at a time
300
+ :param ordering: This should be a string, or list of strings, indicating the field against which the cursor
301
+ based pagination will be applied. For example: ordering = 'slug'
302
+ :return: a Pagination class
303
+ """
304
+ from dynamicforms_legacy.pagination import CursorPagination
305
+
306
+ ps = page_size
307
+ ordr = ordering
308
+
309
+ class MyCursorPagination(CursorPagination):
310
+ ordering = ordr
311
+ page_size = ps
312
+ df_request = None
313
+
314
+ def paginate_queryset(self, queryset, request, view=None):
315
+ self.df_request = request
316
+ return super().paginate_queryset(queryset, request, view)
317
+
318
+ def encode_cursor(self, cursor):
319
+ # Following code is needed when we have https proxy server that redirects requests to http servers.
320
+ # In that case original code generates cursor links that have http scheme.
321
+ # So here I check REFERER header to find out which scheme is originally declared.
322
+ # And use that one in cursor link.
323
+ request = getattr(self, "df_request", None)
324
+ cursor_url = super().encode_cursor(cursor).split(":", 1)
325
+ req_url = self.df_request.META.get("HTTP_REFERER", None)
326
+ if req_url:
327
+ req_url = req_url.split(":", 1)
328
+ if cursor_url[0] != req_url[0] and req_url[0].lower() in ("http", "https"):
329
+ cursor_url[0] = req_url[0]
330
+ cursor_url = ":".join(cursor_url)
331
+ if (
332
+ request
333
+ and isinstance(request.accepted_renderer, JSONRenderer)
334
+ and "x_df_pagination" not in cursor_url
335
+ ):
336
+ cursor_url += "&x_df_pagination=1"
337
+ return cursor_url
338
+
339
+ return MyCursorPagination
340
+
341
+ def handle_create_validation_exception(self, e, request, *args, **kwargs):
342
+ instance = self.new_object()
343
+ ser = self.get_serializer(instance, data=request.data, partial=False)
344
+ ser.is_valid(raise_exception=False)
345
+ e.detail.serializer = ser
346
+ raise e
347
+
348
+ def create(self, request, *args, **kwargs):
349
+ try:
350
+ return super().create(request, *args, **kwargs)
351
+ except ValidationError as e:
352
+ self.handle_create_validation_exception(e, request, *args, **kwargs)
353
+
354
+
355
+ class SingleRecordViewSet(NewMixin, TemplateRendererMixin, viewsets.GenericViewSet):
356
+ def new_object(self):
357
+ raise NotImplementedError()
358
+
359
+ def create(self, request, *args, **kwargs):
360
+ raise NotImplementedError()
361
+
362
+
363
+ # noinspection PyUnresolvedReferences
364
+ class GenericViewSet(NewMixin, PutPostMixin, TemplateRendererMixin, viewsets.GenericViewSet):
365
+ def __init__(self, *args, **kwargs):
366
+ super().__init__(*args, **kwargs)