django-forms-workflows 0.36.2__tar.gz → 0.36.4__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 (162) hide show
  1. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/CHANGELOG.md +19 -0
  2. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/PKG-INFO +1 -1
  3. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/data_sources/database_source.py +80 -0
  4. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/diff_views.py +4 -0
  5. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/forms.py +102 -9
  6. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/sync_api.py +9 -0
  7. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/pyproject.toml +1 -1
  8. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/LICENSE +0 -0
  9. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/README.md +0 -0
  10. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/__init__.py +0 -0
  11. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/admin.py +0 -0
  12. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/api_urls.py +0 -0
  13. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/api_views.py +0 -0
  14. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/apps.py +0 -0
  15. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/conditions.py +0 -0
  16. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/context_processors.py +0 -0
  17. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/data_sources/__init__.py +0 -0
  18. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/data_sources/base.py +0 -0
  19. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/data_sources/ldap_source.py +0 -0
  20. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/data_sources/user_source.py +0 -0
  21. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/email_backends/__init__.py +0 -0
  22. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/email_backends/gmail_api.py +0 -0
  23. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/form_builder_urls.py +0 -0
  24. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/form_builder_views.py +0 -0
  25. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/handlers/__init__.py +0 -0
  26. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/handlers/api_handler.py +0 -0
  27. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/handlers/base.py +0 -0
  28. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/handlers/database_handler.py +0 -0
  29. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/handlers/email_handler.py +0 -0
  30. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/handlers/executor.py +0 -0
  31. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/handlers/file_handler.py +0 -0
  32. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/handlers/ldap_handler.py +0 -0
  33. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/ldap_backend.py +0 -0
  34. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/management/commands/create_default_templates.py +0 -0
  35. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/management/commands/pull_forms.py +0 -0
  36. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/management/commands/push_forms.py +0 -0
  37. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/management/commands/seed_farm_demo.py +0 -0
  38. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/management/commands/seed_pcn_form.py +0 -0
  39. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/management/commands/seed_prefill_sources.py +0 -0
  40. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/management/commands/sync_ldap_profiles.py +0 -0
  41. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/management/commands/sync_ldap_users.py +0 -0
  42. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/management/commands/test_db_connection.py +0 -0
  43. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/migrations/0001_initial.py +0 -0
  44. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/migrations/0002_prefillsource_alter_formfield_prefill_source_and_more.py +0 -0
  45. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/migrations/0003_postsubmissionaction.py +0 -0
  46. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/migrations/0004_formtemplate.py +0 -0
  47. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/migrations/0005_advanced_conditional_logic.py +0 -0
  48. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/migrations/0006_workflowdefinition_visual_workflow_data_and_more.py +0 -0
  49. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/migrations/0007_add_userprofile_ldap_enhancements.py +0 -0
  50. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/migrations/0008_add_file_workflow_models.py +0 -0
  51. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/migrations/0009_add_formfield_readonly.py +0 -0
  52. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/migrations/0010_add_prefillsource_template_fields.py +0 -0
  53. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/migrations/0011_postsubmissionaction_email_body_template_and_more.py +0 -0
  54. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/migrations/0012_add_approval_step_fields.py +0 -0
  55. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/migrations/0013_add_database_query_key.py +0 -0
  56. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/migrations/0014_add_form_category.py +0 -0
  57. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/migrations/0015_add_workflowstage_staged_approvals.py +0 -0
  58. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/migrations/0016_add_pdf_generation.py +0 -0
  59. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/migrations/0017_add_notification_batching.py +0 -0
  60. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/migrations/0018_add_form_category_parent.py +0 -0
  61. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/migrations/0019_add_ldap_group_profile.py +0 -0
  62. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/migrations/0020_add_bulk_export_field.py +0 -0
  63. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/migrations/0021_alter_pendingnotification_scheduled_for_and_more.py +0 -0
  64. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/migrations/0022_add_bulk_pdf_export.py +0 -0
  65. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/migrations/0023_add_performance_indexes.py +0 -0
  66. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/migrations/0024_add_allow_resubmit.py +0 -0
  67. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/migrations/0025_workflowstage_approve_label.py +0 -0
  68. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/migrations/0026_alter_formfield_width.py +0 -0
  69. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/migrations/0027_formsubmission_form_data_gin.py +0 -0
  70. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/migrations/0028_workflowstagegroupconfig.py +0 -0
  71. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/migrations/0029_formfield_workflow_stage_fk_drop_groupconfig.py +0 -0
  72. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/migrations/0030_formfield_phone_type.py +0 -0
  73. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/migrations/0031_sub_workflows.py +0 -0
  74. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/migrations/0032_approved_pending_detached_sub_workflow.py +0 -0
  75. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/migrations/0033_add_reject_parent_to_subworkflowdefinition.py +0 -0
  76. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/migrations/0034_add_notificationlog.py +0 -0
  77. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/migrations/0035_migrate_prefill_source_strings.py +0 -0
  78. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/migrations/0036_add_workflowstage_auto_created.py +0 -0
  79. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/migrations/0037_migrate_flat_workflows_to_staged.py +0 -0
  80. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/migrations/0038_remove_legacy_prefill_source_and_approval_step.py +0 -0
  81. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/migrations/0039_update_help_text.py +0 -0
  82. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/migrations/0040_migrate_deprecated_features.py +0 -0
  83. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/migrations/0041_remove_deprecated_fields.py +0 -0
  84. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/migrations/0042_add_sub_workflow_section_label.py +0 -0
  85. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/migrations/0043_fix_form_data_decimal_encoding.py +0 -0
  86. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/migrations/0044_remove_subworkflowinstance_label.py +0 -0
  87. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/migrations/0045_stageapprovalgroup_workflow_name_label.py +0 -0
  88. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/migrations/0046_workflow_definition_one_to_many.py +0 -0
  89. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/migrations/0047_add_hide_approval_history.py +0 -0
  90. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/migrations/0048_workflowdefinition_trigger_conditions_and_more.py +0 -0
  91. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/migrations/0049_formfield_multifile_type.py +0 -0
  92. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/migrations/0050_workflowdefinition_collapse_parallel_stages.py +0 -0
  93. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/migrations/0051_formdefinition_is_listed.py +0 -0
  94. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/migrations/0052_dynamic_assignee_and_form_field_notifications.py +0 -0
  95. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/migrations/0053_stageformfieldnotification_static_emails.py +0 -0
  96. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/migrations/0054_rename_approved_pending_to_pending_approval.py +0 -0
  97. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/migrations/0055_add_send_back.py +0 -0
  98. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/migrations/0056_calculated_formula_spreadsheet.py +0 -0
  99. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/migrations/0057_add_currency_field_type.py +0 -0
  100. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/migrations/0058_rename_assignee_email_field_add_lookup_type.py +0 -0
  101. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/migrations/0059_add_multiselect_list_field_type.py +0 -0
  102. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/migrations/0060_alter_workflowstage_assignee_lookup_type_helptext.py +0 -0
  103. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/migrations/0061_add_country_us_state_field_types.py +0 -0
  104. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/migrations/0062_add_batch_import_to_formdefinition.py +0 -0
  105. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/migrations/0063_formdefinition_api_enabled_apitoken.py +0 -0
  106. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/migrations/__init__.py +0 -0
  107. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/models.py +0 -0
  108. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/signals.py +0 -0
  109. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/sso_backends.py +0 -0
  110. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/sso_urls.py +0 -0
  111. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/sso_views.py +0 -0
  112. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/static/django_forms_workflows/api/swagger-ui-bundle.js +0 -0
  113. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/static/django_forms_workflows/api/swagger-ui.css +0 -0
  114. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/static/django_forms_workflows/js/form-builder.js +0 -0
  115. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/static/django_forms_workflows/js/form-enhancements.js +0 -0
  116. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/static/django_forms_workflows/js/workflow-builder.js +0 -0
  117. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/sync_views.py +0 -0
  118. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/tasks.py +0 -0
  119. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/templates/admin/django_forms_workflows/_sync_diff.html +0 -0
  120. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/templates/admin/django_forms_workflows/diff_forms.html +0 -0
  121. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/templates/admin/django_forms_workflows/form_builder.html +0 -0
  122. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/templates/admin/django_forms_workflows/formdef_change_form.html +0 -0
  123. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/templates/admin/django_forms_workflows/formdefinition/change_list.html +0 -0
  124. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/templates/admin/django_forms_workflows/sync_import.html +0 -0
  125. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/templates/admin/django_forms_workflows/sync_pull.html +0 -0
  126. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/templates/admin/django_forms_workflows/sync_push.html +0 -0
  127. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/templates/admin/django_forms_workflows/workflow_builder.html +0 -0
  128. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/templates/django_forms_workflows/_category_node.html +0 -0
  129. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/templates/django_forms_workflows/api/docs.html +0 -0
  130. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/templates/django_forms_workflows/approval_inbox.html +0 -0
  131. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/templates/django_forms_workflows/approve.html +0 -0
  132. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/templates/django_forms_workflows/base.html +0 -0
  133. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/templates/django_forms_workflows/batch_import_result.html +0 -0
  134. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/templates/django_forms_workflows/completed_approvals.html +0 -0
  135. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/templates/django_forms_workflows/form_categories.html +0 -0
  136. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/templates/django_forms_workflows/form_list.html +0 -0
  137. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/templates/django_forms_workflows/form_submit.html +0 -0
  138. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/templates/django_forms_workflows/my_submissions.html +0 -0
  139. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/templates/django_forms_workflows/reassign_task.html +0 -0
  140. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/templates/django_forms_workflows/resubmit_confirm.html +0 -0
  141. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/templates/django_forms_workflows/sso/login.html +0 -0
  142. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/templates/django_forms_workflows/sub_workflow_detail.html +0 -0
  143. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/templates/django_forms_workflows/submission_bulk_pdf.html +0 -0
  144. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/templates/django_forms_workflows/submission_detail.html +0 -0
  145. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/templates/django_forms_workflows/submission_pdf.html +0 -0
  146. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/templates/django_forms_workflows/withdraw_confirm.html +0 -0
  147. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/templates/emails/approval_notification.html +0 -0
  148. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/templates/emails/approval_reminder.html +0 -0
  149. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/templates/emails/approval_request.html +0 -0
  150. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/templates/emails/email_styles.html +0 -0
  151. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/templates/emails/escalation_notification.html +0 -0
  152. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/templates/emails/notification_digest.html +0 -0
  153. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/templates/emails/rejection_notification.html +0 -0
  154. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/templates/emails/submission_notification.html +0 -0
  155. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/templates/registration/login.html +0 -0
  156. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/templatetags/__init__.py +0 -0
  157. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/templatetags/forms_workflows_tags.py +0 -0
  158. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/urls.py +0 -0
  159. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/utils.py +0 -0
  160. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/views.py +0 -0
  161. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/workflow_builder_views.py +0 -0
  162. {django_forms_workflows-0.36.2 → django_forms_workflows-0.36.4}/django_forms_workflows/workflow_engine.py +0 -0
@@ -7,6 +7,25 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.36.4] - 2026-03-26
11
+
12
+ ### Added
13
+ - **Dynamic dropdown choices from database** — select, multiselect, multiselect_list, radio, and checkboxes fields can now have their options populated live from any SQL query defined in `FORMS_WORKFLOWS_DATABASE_QUERIES`. Mark a query with `"return_choices": True` (and no user parameter) to return multiple rows; each row's first column becomes the option value and the second column (if present) becomes the display label. Wire it up by pointing the field's PrefillSource at the query key — the stored `choices` JSON is used as a fallback if the DB is unavailable.
14
+ - `DatabaseDataSource.execute_choices_query(query_key)` — new method that executes a choices query without a user parameter and returns `[(value, label), ...]`.
15
+ - `_get_choices_from_prefill_source(field_def)` — new helper on both form classes that detects `return_choices` queries and calls `execute_choices_query`; returns `None` when not applicable so callers fall back to stored choices.
16
+ - `execute_custom_query` now warns and returns `None` if called on a `return_choices` query, preventing accidental single-value use.
17
+
18
+ ## [0.36.3] - 2026-03-26
19
+
20
+ ### Fixed
21
+ - **Cross-instance sync missing newer fields** — `sync_api.serialize_form` and `_serialize_field` were not including several fields added after the serializer was first written, meaning push/pull/diff silently dropped their values on the receiving instance:
22
+ - `FormDefinition.allow_batch_import` (spreadsheet/Excel batch upload toggle, migration 0062)
23
+ - `FormDefinition.is_listed` (hide-from-list-page flag, migration 0051)
24
+ - `FormDefinition.allow_resubmit` (re-submission from rejected/withdrawn, migration 0024)
25
+ - `FormDefinition.api_enabled` (REST API exposure flag, migration 0063)
26
+ - `FormField.formula` (formula expression for Calculated field types, migration 0056)
27
+ All five fields are now serialized on export and restored on import. The diff summary in `diff_views._build_summary` is also updated to detect changes to all four FormDefinition flags.
28
+
10
29
  ## [0.33.1] - 2026-03-23
11
30
 
12
31
  ### Fixed
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: django-forms-workflows
3
- Version: 0.36.2
3
+ Version: 0.36.4
4
4
  Summary: Enterprise-grade, database-driven form builder with approval workflows and external data integration
5
5
  License: LGPL-3.0-only
6
6
  License-File: LICENSE
@@ -428,6 +428,16 @@ class DatabaseDataSource(DataSource):
428
428
  )
429
429
  return None
430
430
 
431
+ # Choices queries (return_choices=True) return multiple rows for
432
+ # populating dropdown options and require no user parameter.
433
+ # Use execute_choices_query() for those instead.
434
+ if query_config.get("return_choices"):
435
+ logger.warning(
436
+ f"Database query '{query_key}' has return_choices=True. "
437
+ "Use execute_choices_query() to get dropdown options."
438
+ )
439
+ return None
440
+
431
441
  # Get user's lookup value
432
442
  user_id = self._get_user_id(user, user_field)
433
443
  if not user_id:
@@ -461,6 +471,76 @@ class DatabaseDataSource(DataSource):
461
471
  logger.error(f"Error executing custom query '{query_key}': {e}")
462
472
  return None
463
473
 
474
+ def execute_choices_query(self, query_key: str) -> list[tuple] | None:
475
+ """
476
+ Execute a reference-data query and return all rows as (value, label) tuples
477
+ for populating dropdown / select / radio field options.
478
+
479
+ Unlike execute_custom_query(), this method requires no user parameter and
480
+ always fetches all rows. The query config must have ``return_choices: True``.
481
+
482
+ If the query returns two columns, the first is used as the option value and
483
+ the second as the display label. If only one column is returned, both value
484
+ and label are set to that column's value.
485
+
486
+ Args:
487
+ query_key: Key from FORMS_WORKFLOWS_DATABASE_QUERIES setting.
488
+
489
+ Returns:
490
+ List of (value, label) tuples, or None on configuration/query error.
491
+ """
492
+ try:
493
+ queries = getattr(settings, "FORMS_WORKFLOWS_DATABASE_QUERIES", {})
494
+ if query_key not in queries:
495
+ logger.error(
496
+ f"Database query key '{query_key}' not found in "
497
+ "FORMS_WORKFLOWS_DATABASE_QUERIES setting"
498
+ )
499
+ return None
500
+
501
+ query_config = queries[query_key]
502
+
503
+ if not query_config.get("return_choices"):
504
+ logger.error(
505
+ f"Database query '{query_key}' does not have return_choices=True. "
506
+ "Use execute_custom_query() for single-value prefill queries."
507
+ )
508
+ return None
509
+
510
+ query_text = query_config.get("query")
511
+ db_alias = query_config.get("db_alias")
512
+
513
+ if not query_text or not db_alias:
514
+ logger.error(
515
+ f"Database choices query '{query_key}' missing 'query' or 'db_alias'"
516
+ )
517
+ return None
518
+
519
+ databases = getattr(settings, "DATABASES", {})
520
+ if db_alias not in databases:
521
+ logger.error(f"Database alias '{db_alias}' not configured")
522
+ return None
523
+
524
+ with connections[db_alias].cursor() as cursor:
525
+ cursor.execute(query_text)
526
+ rows = cursor.fetchall()
527
+
528
+ results = []
529
+ for row in rows:
530
+ if len(row) >= 2:
531
+ value = str(row[0] or "").strip()
532
+ label = str(row[1] or "").strip()
533
+ else:
534
+ value = label = str(row[0] or "").strip()
535
+ if value:
536
+ results.append((value, label))
537
+
538
+ return results
539
+
540
+ except Exception as e:
541
+ logger.error(f"Error executing choices query '{query_key}': {e}")
542
+ return None
543
+
464
544
  def is_available(self) -> bool:
465
545
  """
466
546
  Check if database source is configured.
@@ -150,13 +150,17 @@ def _build_summary(forms_data):
150
150
  "description",
151
151
  "instructions",
152
152
  "is_active",
153
+ "is_listed",
153
154
  "allow_save_draft",
154
155
  "allow_withdrawal",
156
+ "allow_resubmit",
157
+ "allow_batch_import",
155
158
  "requires_login",
156
159
  "enable_multi_step",
157
160
  "enable_auto_save",
158
161
  "auto_save_interval",
159
162
  "pdf_generation",
163
+ "api_enabled",
160
164
  ]
161
165
  for key in meta_keys:
162
166
  if b_form.get(key) != o_form.get(key):
@@ -276,6 +276,31 @@ class DynamicForm(forms.Form):
276
276
 
277
277
  return []
278
278
 
279
+ def _get_choices_from_prefill_source(self, field_def):
280
+ """
281
+ Return a list of (value, label) tuples from a database choices query when the
282
+ field's PrefillSource points to a query with ``return_choices=True``.
283
+
284
+ Returns None if the field has no such source (so the caller can fall back to
285
+ the stored ``field_def.choices``). Returns [] if the query ran but was empty.
286
+ """
287
+ prefill_key = field_def.get_prefill_source_key()
288
+ if not prefill_key or not prefill_key.startswith("dbquery."):
289
+ return None
290
+
291
+ query_key = prefill_key[len("dbquery.") :]
292
+
293
+ from django.conf import settings
294
+
295
+ queries = getattr(settings, "FORMS_WORKFLOWS_DATABASE_QUERIES", {})
296
+ if not queries.get(query_key, {}).get("return_choices"):
297
+ return None
298
+
299
+ from .data_sources import DatabaseDataSource
300
+
301
+ source = DatabaseDataSource()
302
+ return source.execute_choices_query(query_key)
303
+
279
304
  def add_field(self, field_def, initial_data):
280
305
  """Add a field to the form based on field definition"""
281
306
 
@@ -402,19 +427,34 @@ class DynamicForm(forms.Form):
402
427
  self.fields[field_def.field_name] = forms.URLField(**field_args)
403
428
 
404
429
  elif field_def.field_type == "select":
405
- choices = [("", "-- Select --")] + self._parse_choices(field_def.choices)
430
+ _db_choices = self._get_choices_from_prefill_source(field_def)
431
+ choices = [("", "-- Select --")] + (
432
+ _db_choices
433
+ if _db_choices is not None
434
+ else self._parse_choices(field_def.choices)
435
+ )
406
436
  self.fields[field_def.field_name] = forms.ChoiceField(
407
437
  choices=choices, **field_args
408
438
  )
409
439
 
410
440
  elif field_def.field_type == "multiselect":
411
- choices = self._parse_choices(field_def.choices)
441
+ _db_choices = self._get_choices_from_prefill_source(field_def)
442
+ choices = (
443
+ _db_choices
444
+ if _db_choices is not None
445
+ else self._parse_choices(field_def.choices)
446
+ )
412
447
  self.fields[field_def.field_name] = forms.MultipleChoiceField(
413
448
  choices=choices, widget=forms.CheckboxSelectMultiple, **field_args
414
449
  )
415
450
 
416
451
  elif field_def.field_type == "multiselect_list":
417
- choices = self._parse_choices(field_def.choices)
452
+ _db_choices = self._get_choices_from_prefill_source(field_def)
453
+ choices = (
454
+ _db_choices
455
+ if _db_choices is not None
456
+ else self._parse_choices(field_def.choices)
457
+ )
418
458
  self.fields[field_def.field_name] = forms.MultipleChoiceField(
419
459
  choices=choices,
420
460
  widget=forms.SelectMultiple(attrs={"class": "form-select"}),
@@ -422,7 +462,12 @@ class DynamicForm(forms.Form):
422
462
  )
423
463
 
424
464
  elif field_def.field_type == "radio":
425
- choices = self._parse_choices(field_def.choices)
465
+ _db_choices = self._get_choices_from_prefill_source(field_def)
466
+ choices = (
467
+ _db_choices
468
+ if _db_choices is not None
469
+ else self._parse_choices(field_def.choices)
470
+ )
426
471
  self.fields[field_def.field_name] = forms.ChoiceField(
427
472
  choices=choices, widget=forms.RadioSelect, **field_args
428
473
  )
@@ -436,7 +481,12 @@ class DynamicForm(forms.Form):
436
481
  )
437
482
 
438
483
  elif field_def.field_type == "checkboxes":
439
- choices = self._parse_choices(field_def.choices)
484
+ _db_choices = self._get_choices_from_prefill_source(field_def)
485
+ choices = (
486
+ _db_choices
487
+ if _db_choices is not None
488
+ else self._parse_choices(field_def.choices)
489
+ )
440
490
  self.fields[field_def.field_name] = forms.MultipleChoiceField(
441
491
  choices=choices,
442
492
  widget=forms.CheckboxSelectMultiple,
@@ -1057,7 +1107,12 @@ class ApprovalStepForm(forms.Form):
1057
1107
  self.fields[field_def.field_name] = forms.EmailField(**field_args)
1058
1108
 
1059
1109
  elif field_def.field_type == "select":
1060
- choices = [("", "-- Select --")] + self._parse_choices(field_def.choices)
1110
+ _db_choices = self._get_choices_from_prefill_source(field_def)
1111
+ choices = [("", "-- Select --")] + (
1112
+ _db_choices
1113
+ if _db_choices is not None
1114
+ else self._parse_choices(field_def.choices)
1115
+ )
1061
1116
  if widget_attrs:
1062
1117
  field_args["widget"] = forms.Select(attrs=widget_attrs)
1063
1118
  self.fields[field_def.field_name] = forms.ChoiceField(
@@ -1065,7 +1120,12 @@ class ApprovalStepForm(forms.Form):
1065
1120
  )
1066
1121
 
1067
1122
  elif field_def.field_type == "multiselect":
1068
- choices = self._parse_choices(field_def.choices)
1123
+ _db_choices = self._get_choices_from_prefill_source(field_def)
1124
+ choices = (
1125
+ _db_choices
1126
+ if _db_choices is not None
1127
+ else self._parse_choices(field_def.choices)
1128
+ )
1069
1129
  self.fields[field_def.field_name] = forms.MultipleChoiceField(
1070
1130
  choices=choices,
1071
1131
  widget=forms.CheckboxSelectMultiple,
@@ -1073,7 +1133,12 @@ class ApprovalStepForm(forms.Form):
1073
1133
  )
1074
1134
 
1075
1135
  elif field_def.field_type == "multiselect_list":
1076
- choices = self._parse_choices(field_def.choices)
1136
+ _db_choices = self._get_choices_from_prefill_source(field_def)
1137
+ choices = (
1138
+ _db_choices
1139
+ if _db_choices is not None
1140
+ else self._parse_choices(field_def.choices)
1141
+ )
1077
1142
  self.fields[field_def.field_name] = forms.MultipleChoiceField(
1078
1143
  choices=choices,
1079
1144
  widget=forms.SelectMultiple(attrs={"class": "form-select"}),
@@ -1081,7 +1146,12 @@ class ApprovalStepForm(forms.Form):
1081
1146
  )
1082
1147
 
1083
1148
  elif field_def.field_type == "radio":
1084
- choices = self._parse_choices(field_def.choices)
1149
+ _db_choices = self._get_choices_from_prefill_source(field_def)
1150
+ choices = (
1151
+ _db_choices
1152
+ if _db_choices is not None
1153
+ else self._parse_choices(field_def.choices)
1154
+ )
1085
1155
  self.fields[field_def.field_name] = forms.ChoiceField(
1086
1156
  choices=choices,
1087
1157
  widget=forms.RadioSelect(attrs=widget_attrs),
@@ -1195,6 +1265,29 @@ class ApprovalStepForm(forms.Form):
1195
1265
  return [(c.strip(), c.strip()) for c in choices.split(",") if c.strip()]
1196
1266
  return []
1197
1267
 
1268
+ def _get_choices_from_prefill_source(self, field_def):
1269
+ """
1270
+ Return (value, label) tuples from a database choices query when the field's
1271
+ PrefillSource points to a query with ``return_choices=True``, or None if the
1272
+ field has no such source (so the caller falls back to stored choices).
1273
+ """
1274
+ prefill_key = field_def.get_prefill_source_key()
1275
+ if not prefill_key or not prefill_key.startswith("dbquery."):
1276
+ return None
1277
+
1278
+ query_key = prefill_key[len("dbquery.") :]
1279
+
1280
+ from django.conf import settings
1281
+
1282
+ queries = getattr(settings, "FORMS_WORKFLOWS_DATABASE_QUERIES", {})
1283
+ if not queries.get(query_key, {}).get("return_choices"):
1284
+ return None
1285
+
1286
+ from .data_sources import DatabaseDataSource
1287
+
1288
+ source = DatabaseDataSource()
1289
+ return source.execute_choices_query(query_key)
1290
+
1198
1291
  def _build_layout_fields(self, field_defs):
1199
1292
  """Convert a list of field definitions into crispy layout elements,
1200
1293
  respecting half / third / fourth width settings."""
@@ -216,6 +216,7 @@ def _serialize_field(field):
216
216
  "choices": field.choices,
217
217
  "prefill_source_config": _serialize_prefill_source(field.prefill_source_config),
218
218
  "default_value": field.default_value,
219
+ "formula": field.formula,
219
220
  "conditional_rules": field.conditional_rules,
220
221
  "validation_rules": field.validation_rules,
221
222
  "field_dependencies": field.field_dependencies,
@@ -373,18 +374,22 @@ def serialize_form(form_definition):
373
374
  "description": form_definition.description,
374
375
  "instructions": form_definition.instructions,
375
376
  "is_active": form_definition.is_active,
377
+ "is_listed": form_definition.is_listed,
376
378
  "version": form_definition.version,
377
379
  "submit_groups": _group_names(form_definition.submit_groups),
378
380
  "view_groups": _group_names(form_definition.view_groups),
379
381
  "admin_groups": _group_names(form_definition.admin_groups),
380
382
  "allow_save_draft": form_definition.allow_save_draft,
381
383
  "allow_withdrawal": form_definition.allow_withdrawal,
384
+ "allow_resubmit": form_definition.allow_resubmit,
385
+ "allow_batch_import": form_definition.allow_batch_import,
382
386
  "requires_login": form_definition.requires_login,
383
387
  "enable_multi_step": form_definition.enable_multi_step,
384
388
  "form_steps": form_definition.form_steps,
385
389
  "enable_auto_save": form_definition.enable_auto_save,
386
390
  "auto_save_interval": form_definition.auto_save_interval,
387
391
  "pdf_generation": form_definition.pdf_generation,
392
+ "api_enabled": form_definition.api_enabled,
388
393
  },
389
394
  "fields": [
390
395
  _serialize_field(f) for f in form_definition.fields.all().order_by("order")
@@ -521,16 +526,20 @@ def import_form(form_data, conflict="update", category_cache=None):
521
526
  "description": fd.get("description", ""),
522
527
  "instructions": fd.get("instructions", ""),
523
528
  "is_active": fd.get("is_active", True),
529
+ "is_listed": fd.get("is_listed", True),
524
530
  "version": fd.get("version", 1),
525
531
  "category": category,
526
532
  "allow_save_draft": fd.get("allow_save_draft", False),
527
533
  "allow_withdrawal": fd.get("allow_withdrawal", False),
534
+ "allow_resubmit": fd.get("allow_resubmit", False),
535
+ "allow_batch_import": fd.get("allow_batch_import", False),
528
536
  "requires_login": fd.get("requires_login", True),
529
537
  "enable_multi_step": fd.get("enable_multi_step", False),
530
538
  "form_steps": fd.get("form_steps"),
531
539
  "enable_auto_save": fd.get("enable_auto_save", False),
532
540
  "auto_save_interval": fd.get("auto_save_interval", 30),
533
541
  "pdf_generation": fd.get("pdf_generation", False),
542
+ "api_enabled": fd.get("api_enabled", False),
534
543
  }
535
544
 
536
545
  form_obj, created = FormDefinition.objects.update_or_create(
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "django-forms-workflows"
3
- version = "0.36.2"
3
+ version = "0.36.4"
4
4
  description = "Enterprise-grade, database-driven form builder with approval workflows and external data integration"
5
5
  license = "LGPL-3.0-only"
6
6
  readme = "README.md"