django-unfold 0.25.0__tar.gz → 0.26.0__tar.gz

Sign up to get free protection for your applications and to get access to all the features.
Files changed (196) hide show
  1. {django_unfold-0.25.0 → django_unfold-0.26.0}/PKG-INFO +51 -6
  2. {django_unfold-0.25.0 → django_unfold-0.26.0}/README.md +50 -5
  3. {django_unfold-0.25.0 → django_unfold-0.26.0}/pyproject.toml +1 -1
  4. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/admin.py +11 -3
  5. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/contrib/import_export/forms.py +17 -0
  6. django_unfold-0.26.0/src/unfold/contrib/import_export/templates/admin/import_export/change_form.html +10 -0
  7. django_unfold-0.26.0/src/unfold/contrib/import_export/templates/admin/import_export/export.html +82 -0
  8. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/contrib/import_export/templates/admin/import_export/import_form.html +8 -12
  9. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/contrib/import_export/templates/admin/import_export/resource_fields_list.html +1 -1
  10. django_unfold-0.26.0/src/unfold/contrib/inlines/admin.py +141 -0
  11. django_unfold-0.26.0/src/unfold/contrib/inlines/apps.py +6 -0
  12. django_unfold-0.26.0/src/unfold/contrib/inlines/checks.py +18 -0
  13. django_unfold-0.26.0/src/unfold/contrib/inlines/forms.py +43 -0
  14. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/forms.py +6 -0
  15. django_unfold-0.26.0/src/unfold/static/unfold/css/simplebar.css +230 -0
  16. django_unfold-0.26.0/src/unfold/static/unfold/css/styles.css +1 -0
  17. django_unfold-0.26.0/src/unfold/static/unfold/js/simplebar.js +10 -0
  18. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/styles.css +9 -1
  19. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/templates/admin/app_list.html +1 -1
  20. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/templates/admin/change_form.html +11 -9
  21. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/templates/admin/change_list_results.html +2 -2
  22. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/templates/admin/edit_inline/stacked.html +6 -6
  23. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/templates/admin/edit_inline/tabular.html +3 -3
  24. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/templates/admin/includes/fieldset.html +1 -1
  25. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/templates/unfold/helpers/app_list.html +1 -1
  26. django_unfold-0.26.0/src/unfold/templates/unfold/helpers/display_header.html +23 -0
  27. django_unfold-0.26.0/src/unfold/templates/unfold/helpers/field.html +23 -0
  28. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/templates/unfold/helpers/fieldsets_tabs.html +4 -4
  29. django_unfold-0.26.0/src/unfold/templates/unfold/helpers/form_label.html +7 -0
  30. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/templates/unfold/layouts/skeleton.html +2 -0
  31. django_unfold-0.26.0/src/unfold/templates/unfold/widgets/foreign_key_raw_id.html +21 -0
  32. django_unfold-0.26.0/src/unfold/templates/unfold/widgets/textarea.html +1 -0
  33. django_unfold-0.26.0/src/unfold/templatetags/__init__.py +0 -0
  34. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/widgets.py +36 -3
  35. django_unfold-0.25.0/src/unfold/contrib/import_export/admin.py +0 -37
  36. django_unfold-0.25.0/src/unfold/contrib/import_export/templates/admin/import_export/export.html +0 -47
  37. django_unfold-0.25.0/src/unfold/static/unfold/css/styles.css +0 -1
  38. django_unfold-0.25.0/src/unfold/templates/unfold/helpers/display_header.html +0 -20
  39. django_unfold-0.25.0/src/unfold/templates/unfold/helpers/field.html +0 -9
  40. django_unfold-0.25.0/src/unfold/templates/unfold/helpers/form_label.html +0 -7
  41. {django_unfold-0.25.0 → django_unfold-0.26.0}/LICENSE.md +0 -0
  42. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/__init__.py +0 -0
  43. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/apps.py +0 -0
  44. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/checks.py +0 -0
  45. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/contrib/__init__.py +0 -0
  46. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/contrib/filters/__init__.py +0 -0
  47. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/contrib/filters/admin.py +0 -0
  48. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/contrib/filters/apps.py +0 -0
  49. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/contrib/filters/forms.py +0 -0
  50. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/contrib/filters/static/unfold/filters/css/nouislider.min.css +0 -0
  51. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/contrib/filters/static/unfold/filters/js/DateTimeShortcuts.js +0 -0
  52. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/contrib/filters/static/unfold/filters/js/admin-numeric-filter.js +0 -0
  53. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/contrib/filters/static/unfold/filters/js/nouislider.min.js +0 -0
  54. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/contrib/filters/static/unfold/filters/js/wNumb.min.js +0 -0
  55. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/contrib/filters/templates/unfold/filters/filters_date_range.html +0 -0
  56. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/contrib/filters/templates/unfold/filters/filters_datetime_range.html +0 -0
  57. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/contrib/filters/templates/unfold/filters/filters_field.html +0 -0
  58. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/contrib/filters/templates/unfold/filters/filters_numeric_range.html +0 -0
  59. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/contrib/filters/templates/unfold/filters/filters_numeric_single.html +0 -0
  60. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/contrib/filters/templates/unfold/filters/filters_numeric_slider.html +0 -0
  61. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/contrib/forms/__init__.py +0 -0
  62. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/contrib/forms/apps.py +0 -0
  63. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/contrib/forms/static/unfold/forms/css/trix.css +0 -0
  64. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/contrib/forms/static/unfold/forms/js/trix.config.js +0 -0
  65. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/contrib/forms/static/unfold/forms/js/trix.js +0 -0
  66. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/contrib/forms/templates/unfold/forms/helpers/toolbar.html +0 -0
  67. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/contrib/forms/templates/unfold/forms/wysiwyg.html +0 -0
  68. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/contrib/forms/widgets.py +0 -0
  69. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/contrib/guardian/__init__.py +0 -0
  70. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/contrib/guardian/apps.py +0 -0
  71. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/contrib/guardian/templates/admin/guardian/model/change_form.html +0 -0
  72. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/contrib/guardian/templates/admin/guardian/model/field.html +0 -0
  73. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/contrib/guardian/templates/admin/guardian/model/obj_perms_manage.html +0 -0
  74. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/contrib/guardian/templates/admin/guardian/model/obj_perms_manage_group.html +0 -0
  75. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/contrib/guardian/templates/admin/guardian/model/obj_perms_manage_user.html +0 -0
  76. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/contrib/guardian/templates/unfold/guardian/group_form.html +0 -0
  77. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/contrib/guardian/templates/unfold/guardian/user_form.html +0 -0
  78. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/contrib/import_export/__init__.py +0 -0
  79. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/contrib/import_export/apps.py +0 -0
  80. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/contrib/import_export/templates/admin/import_export/base.html +0 -0
  81. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/contrib/import_export/templates/admin/import_export/change_list_export_item.html +0 -0
  82. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/contrib/import_export/templates/admin/import_export/change_list_import_export.html +0 -0
  83. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/contrib/import_export/templates/admin/import_export/change_list_import_item.html +0 -0
  84. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/contrib/import_export/templates/admin/import_export/import.html +0 -0
  85. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/contrib/import_export/templates/admin/import_export/import_confirm.html +0 -0
  86. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/contrib/import_export/templates/admin/import_export/import_errors.html +0 -0
  87. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/contrib/import_export/templates/admin/import_export/import_preview.html +0 -0
  88. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/contrib/import_export/templates/admin/import_export/import_validation.html +0 -0
  89. {django_unfold-0.25.0/src/unfold/contrib/simple_history → django_unfold-0.26.0/src/unfold/contrib/inlines}/__init__.py +0 -0
  90. {django_unfold-0.25.0/src/unfold/templatetags → django_unfold-0.26.0/src/unfold/contrib/simple_history}/__init__.py +0 -0
  91. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/contrib/simple_history/apps.py +0 -0
  92. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/contrib/simple_history/templates/simple_history/_object_history_list.html +0 -0
  93. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/contrib/simple_history/templates/simple_history/object_history.html +0 -0
  94. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/contrib/simple_history/templates/simple_history/object_history_form.html +0 -0
  95. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/contrib/simple_history/templates/simple_history/submit_line.html +0 -0
  96. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/dataclasses.py +0 -0
  97. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/decorators.py +0 -0
  98. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/exceptions.py +0 -0
  99. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/settings.py +0 -0
  100. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/sites.py +0 -0
  101. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/static/unfold/fonts/inter/Inter-Bold.woff2 +0 -0
  102. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/static/unfold/fonts/inter/Inter-Medium.woff2 +0 -0
  103. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/static/unfold/fonts/inter/Inter-Regular.woff2 +0 -0
  104. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/static/unfold/fonts/inter/Inter-SemiBold.woff2 +0 -0
  105. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/static/unfold/fonts/inter/styles.css +0 -0
  106. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/static/unfold/fonts/material-symbols/Material-Symbols-Outlined.woff2 +0 -0
  107. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/static/unfold/fonts/material-symbols/styles.css +0 -0
  108. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/static/unfold/js/alpine.js +0 -0
  109. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/static/unfold/js/alpine.persist.js +0 -0
  110. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/static/unfold/js/app.js +0 -0
  111. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/static/unfold/js/chart.js +0 -0
  112. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/static/unfold/js/htmx.js +0 -0
  113. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/templates/admin/actions.html +0 -0
  114. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/templates/admin/app_index.html +0 -0
  115. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/templates/admin/auth/user/add_form.html +0 -0
  116. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/templates/admin/auth/user/change_password.html +0 -0
  117. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/templates/admin/base.html +0 -0
  118. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/templates/admin/base_site.html +0 -0
  119. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/templates/admin/change_form_object_tools.html +0 -0
  120. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/templates/admin/change_list.html +0 -0
  121. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/templates/admin/change_list_object_tools.html +0 -0
  122. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/templates/admin/date_hierarchy.html +0 -0
  123. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/templates/admin/delete_confirmation.html +0 -0
  124. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/templates/admin/delete_selected_confirmation.html +0 -0
  125. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/templates/admin/filter.html +0 -0
  126. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/templates/admin/includes/object_delete_summary.html +0 -0
  127. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/templates/admin/index.html +0 -0
  128. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/templates/admin/login.html +0 -0
  129. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/templates/admin/nav_sidebar.html +0 -0
  130. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/templates/admin/object_history.html +0 -0
  131. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/templates/admin/pagination.html +0 -0
  132. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/templates/admin/search_form.html +0 -0
  133. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/templates/admin/submit_line.html +0 -0
  134. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/templates/auth/widgets/read_only_password_hash.html +0 -0
  135. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/templates/registration/logged_out.html +0 -0
  136. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/templates/registration/password_change_done.html +0 -0
  137. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/templates/registration/password_change_form.html +0 -0
  138. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/templates/unfold/change_list_filter.html +0 -0
  139. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/templates/unfold/components/card.html +0 -0
  140. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/templates/unfold/components/chart/bar.html +0 -0
  141. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/templates/unfold/components/chart/line.html +0 -0
  142. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/templates/unfold/components/container.html +0 -0
  143. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/templates/unfold/components/flex.html +0 -0
  144. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/templates/unfold/components/navigation.html +0 -0
  145. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/templates/unfold/components/progress.html +0 -0
  146. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/templates/unfold/components/separator.html +0 -0
  147. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/templates/unfold/components/text.html +0 -0
  148. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/templates/unfold/components/title.html +0 -0
  149. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/templates/unfold/helpers/account_links.html +0 -0
  150. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/templates/unfold/helpers/actions_row.html +0 -0
  151. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/templates/unfold/helpers/add_link.html +0 -0
  152. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/templates/unfold/helpers/app_list_default.html +0 -0
  153. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/templates/unfold/helpers/boolean.html +0 -0
  154. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/templates/unfold/helpers/breadcrumb_item.html +0 -0
  155. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/templates/unfold/helpers/display_label.html +0 -0
  156. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/templates/unfold/helpers/field_readonly.html +0 -0
  157. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/templates/unfold/helpers/form_errors.html +0 -0
  158. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/templates/unfold/helpers/header.html +0 -0
  159. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/templates/unfold/helpers/help_text.html +0 -0
  160. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/templates/unfold/helpers/history.html +0 -0
  161. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/templates/unfold/helpers/label.html +0 -0
  162. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/templates/unfold/helpers/messages/error.html +0 -0
  163. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/templates/unfold/helpers/messages/errornote.html +0 -0
  164. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/templates/unfold/helpers/messages/info.html +0 -0
  165. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/templates/unfold/helpers/messages.html +0 -0
  166. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/templates/unfold/helpers/navigation.html +0 -0
  167. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/templates/unfold/helpers/pagination_current_item.html +0 -0
  168. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/templates/unfold/helpers/pagination_ellipsis.html +0 -0
  169. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/templates/unfold/helpers/search.html +0 -0
  170. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/templates/unfold/helpers/search_results.html +0 -0
  171. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/templates/unfold/helpers/site_icon.html +0 -0
  172. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/templates/unfold/helpers/site_logo.html +0 -0
  173. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/templates/unfold/helpers/submit.html +0 -0
  174. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/templates/unfold/helpers/tab_action.html +0 -0
  175. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/templates/unfold/helpers/tab_list.html +0 -0
  176. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/templates/unfold/helpers/theme_switch.html +0 -0
  177. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/templates/unfold/helpers/userlinks.html +0 -0
  178. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/templates/unfold/helpers/welcomemsg.html +0 -0
  179. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/templates/unfold/layouts/base_simple.html +0 -0
  180. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/templates/unfold/widgets/clearable_file_input.html +0 -0
  181. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/templates/unfold/widgets/clearable_file_input_small.html +0 -0
  182. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/templates/unfold/widgets/date.html +0 -0
  183. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/templates/unfold/widgets/radio.html +0 -0
  184. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/templates/unfold/widgets/radio_option.html +0 -0
  185. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/templates/unfold/widgets/range.html +0 -0
  186. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/templates/unfold/widgets/related_widget_wrapper.html +0 -0
  187. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/templates/unfold/widgets/split_datetime.html +0 -0
  188. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/templates/unfold/widgets/split_datetime_vertical.html +0 -0
  189. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/templates/unfold/widgets/split_money.html +0 -0
  190. /django_unfold-0.25.0/src/unfold/templates/unfold/widgets/textarea.html → /django_unfold-0.26.0/src/unfold/templates/unfold/widgets/textarea_expandable.html +0 -0
  191. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/templates/unfold/widgets/time.html +0 -0
  192. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/templatetags/unfold.py +0 -0
  193. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/templatetags/unfold_list.py +0 -0
  194. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/typing.py +0 -0
  195. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/utils.py +0 -0
  196. {django_unfold-0.25.0 → django_unfold-0.26.0}/src/unfold/views.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: django-unfold
3
- Version: 0.25.0
3
+ Version: 0.26.0
4
4
  Summary: Modern Django admin theme for seamless interface development
5
5
  Home-page: https://unfoldadmin.com
6
6
  License: MIT
@@ -30,7 +30,7 @@ Description-Content-Type: text/markdown
30
30
 
31
31
  [![Build](https://img.shields.io/github/actions/workflow/status/unfoldadmin/django-unfold/release.yml?style=for-the-badge)](https://github.com/unfoldadmin/django-unfold/actions?query=workflow%3Arelease)
32
32
  [![PyPI - Version](https://img.shields.io/pypi/v/django-unfold.svg?style=for-the-badge)](https://pypi.org/project/django-unfold/)
33
- ![Code Style - Black](https://img.shields.io/badge/code%20style-black-000000.svg?style=for-the-badge)
33
+ ![Code Style - Ruff](https://img.shields.io/badge/code%20style-ruff-30173D.svg?style=for-the-badge)
34
34
  ![Pre Commit](https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit&logoColor=white&style=for-the-badge)
35
35
 
36
36
  Unfold is theme for Django admin incorporating most common practises for building full-fledged admin areas. It is designed to work at the top of default administration provided by Django.
@@ -59,7 +59,8 @@ Did you decide to start using Unfold but you don't have time to make the switch
59
59
  - **Colors:** possibility to override default color scheme
60
60
  - **Third party packages:** default support for multiple popular applications
61
61
  - **Environment label**: distinguish between environments by displaying a label
62
- - **Parallel admin**: support for having default admin in parallel with Unfold. [Admin migration guide](https://unfoldadmin.com/blog/migrating-django-admin-unfold/)
62
+ - **Nonrelated inlines**: displays nonrelated model as inline in changeform
63
+ - **Parallel admin**: support for default admin in parallel with Unfold. [Admin migration guide](https://unfoldadmin.com/blog/migrating-django-admin-unfold/)
63
64
  - **VS Code**: project configuration and development container is included
64
65
 
65
66
  ## Table of contents <!-- omit from toc -->
@@ -78,6 +79,7 @@ Did you decide to start using Unfold but you don't have time to make the switch
78
79
  - [Dropdown filters](#dropdown-filters)
79
80
  - [Numeric filters](#numeric-filters)
80
81
  - [Date/time filters](#datetime-filters)
82
+ - [Nonrelated inlines](#nonrelated-inlines)
81
83
  - [Display decorator](#display-decorator)
82
84
  - [Change form tabs](#change-form-tabs)
83
85
  - [Third party packages](#third-party-packages)
@@ -114,6 +116,7 @@ INSTALLED_APPS = [
114
116
  "unfold", # before django.contrib.admin
115
117
  "unfold.contrib.filters", # optional, if special filters are needed
116
118
  "unfold.contrib.forms", # optional, if special form elements are needed
119
+ "unfold.contrib.inlines", # optional, if special inlines are needed
117
120
  "unfold.contrib.import_export", # optional, if django-import-export package is used
118
121
  "unfold.contrib.guardian", # optional, if django-guardian package is used
119
122
  "unfold.contrib.simple_history", # optional, if django-simple-history package is used
@@ -633,6 +636,41 @@ class YourModelAdmin(ModelAdmin):
633
636
  )
634
637
  ```
635
638
 
639
+ ## Nonrelated inlines
640
+
641
+ To display inlines which are not related (no foreign key pointing at the main model) to the model instance in changeform, you can use nonrelated inlines which are included in `unfold.contrib.inlines` module. Make sure this module is included in `INSTALLED_APPS` in settings.py.
642
+
643
+ ```python
644
+ from django.contrib.auth.models import User
645
+ from unfold.admin import ModelAdmin
646
+ from unfold.contrib.inlines.admin import NonrelatedTabularInline
647
+ from .models import OtherModel
648
+
649
+ class OtherNonrelatedInline(NonrelatedTabularInline): # NonrelatedStackedInline is available as well
650
+ model = OtherModel
651
+ fields = ["field1", "field2"] # Ignore property to display all fields
652
+
653
+ def get_form_queryset(self, obj):
654
+ """
655
+ Gets all nonrelated objects needed for inlines. Method must be implemented.
656
+ """
657
+ return self.model.objects.all()
658
+
659
+ def save_new_instance(self, parent, instance):
660
+ """
661
+ Extra save method which can for example update inline instances based on current
662
+ main model object. Method must be implemented.
663
+ """
664
+ pass
665
+
666
+
667
+ @admin.register(User)
668
+ class UserAdmin(ModelAdmin):
669
+ inlines = [OtherNonrelatedInline]
670
+ ```
671
+
672
+ **NOTE:** credit for this functionality goes to [django-nonrelated-inlines](https://github.com/bhomnick/django-nonrelated-inlines)
673
+
636
674
  ## Display decorator
637
675
 
638
676
  Unfold introduces it's own `unfold.decorators.display` decorator. By default it has exactly same behavior as native `django.contrib.admin.decorators.display` but it adds same customizations which helps to extends default logic.
@@ -697,12 +735,15 @@ class UserAdmin(ModelAdmin):
697
735
  """
698
736
  return [
699
737
  "First main heading",
700
- "Smaller additional description", # Use None in case you don't need it
701
- "AB", # Short text which will appear in front of
738
+ "Smaller additional description", # Use None in case you don't need it
739
+ "AB", # Short text which will appear in front of
702
740
  # Image instead of initials. Initials are ignored if image is available
703
741
  {
704
742
  "path": "some/path/picture.jpg,
705
743
  "squared": True, # Picture is displayed in square format, if empty circle
744
+ "borderless": True # Picture will be displayed without border
745
+ "width": 64, # Removes default width. Use together with height
746
+ "height": 48, # Removes default height. Use together with width
706
747
  }
707
748
  ]
708
749
  ```
@@ -822,15 +863,18 @@ Adding support for django-guardian is quote straightforward in Unfold, just add
822
863
 
823
864
  from unfold.admin import ModelAdmin
824
865
  from import_export.admin import ImportExportModelAdmin
825
- from unfold.contrib.import_export.forms import ExportForm, ImportForm
866
+ from unfold.contrib.import_export.forms import ExportForm, ImportForm, SelectableFieldsExportForm
826
867
 
827
868
  class ExampleAdmin(ModelAdmin, ImportExportModelAdmin):
828
869
  import_form_class = ImportForm
829
870
  export_form_class = ExportForm
871
+ # export_form_class = SelectableFieldsExportForm
830
872
  ```
831
873
 
832
874
  When implementing `import_export.admin.ExportActionModelAdmin` class in admin panel, import_export plugin adds its own implementation of action form which is not incorporating Unfold CSS classes. For this reason, `unfold.contrib.import_export.admin` contains class with the same name `ExportActionModelAdmin` which inherits behavior of parent form and adds appropriate CSS classes.
833
875
 
876
+ **Note:** This class has been removed and in new version (4.x) of django-import-export it is not needed.
877
+
834
878
  ```python
835
879
  admin.py
836
880
 
@@ -1135,6 +1179,7 @@ The container has already a node preinstalled so it is possible to compile a new
1135
1179
 
1136
1180
  ## Credits
1137
1181
 
1182
+ - [django-nonrelated-inlines](https://github.com/bhomnick/django-nonrelated-inlines) - Django admin inlines for unrelated models
1138
1183
  - [TailwindCSS](https://tailwindcss.com/) - CSS framework
1139
1184
  - [HTMX](https://htmx.org/) - AJAX communication with backend
1140
1185
  - [Material Icons](https://fonts.google.com/icons) - Icons from Google Fonts
@@ -6,7 +6,7 @@
6
6
 
7
7
  [![Build](https://img.shields.io/github/actions/workflow/status/unfoldadmin/django-unfold/release.yml?style=for-the-badge)](https://github.com/unfoldadmin/django-unfold/actions?query=workflow%3Arelease)
8
8
  [![PyPI - Version](https://img.shields.io/pypi/v/django-unfold.svg?style=for-the-badge)](https://pypi.org/project/django-unfold/)
9
- ![Code Style - Black](https://img.shields.io/badge/code%20style-black-000000.svg?style=for-the-badge)
9
+ ![Code Style - Ruff](https://img.shields.io/badge/code%20style-ruff-30173D.svg?style=for-the-badge)
10
10
  ![Pre Commit](https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit&logoColor=white&style=for-the-badge)
11
11
 
12
12
  Unfold is theme for Django admin incorporating most common practises for building full-fledged admin areas. It is designed to work at the top of default administration provided by Django.
@@ -35,7 +35,8 @@ Did you decide to start using Unfold but you don't have time to make the switch
35
35
  - **Colors:** possibility to override default color scheme
36
36
  - **Third party packages:** default support for multiple popular applications
37
37
  - **Environment label**: distinguish between environments by displaying a label
38
- - **Parallel admin**: support for having default admin in parallel with Unfold. [Admin migration guide](https://unfoldadmin.com/blog/migrating-django-admin-unfold/)
38
+ - **Nonrelated inlines**: displays nonrelated model as inline in changeform
39
+ - **Parallel admin**: support for default admin in parallel with Unfold. [Admin migration guide](https://unfoldadmin.com/blog/migrating-django-admin-unfold/)
39
40
  - **VS Code**: project configuration and development container is included
40
41
 
41
42
  ## Table of contents <!-- omit from toc -->
@@ -54,6 +55,7 @@ Did you decide to start using Unfold but you don't have time to make the switch
54
55
  - [Dropdown filters](#dropdown-filters)
55
56
  - [Numeric filters](#numeric-filters)
56
57
  - [Date/time filters](#datetime-filters)
58
+ - [Nonrelated inlines](#nonrelated-inlines)
57
59
  - [Display decorator](#display-decorator)
58
60
  - [Change form tabs](#change-form-tabs)
59
61
  - [Third party packages](#third-party-packages)
@@ -90,6 +92,7 @@ INSTALLED_APPS = [
90
92
  "unfold", # before django.contrib.admin
91
93
  "unfold.contrib.filters", # optional, if special filters are needed
92
94
  "unfold.contrib.forms", # optional, if special form elements are needed
95
+ "unfold.contrib.inlines", # optional, if special inlines are needed
93
96
  "unfold.contrib.import_export", # optional, if django-import-export package is used
94
97
  "unfold.contrib.guardian", # optional, if django-guardian package is used
95
98
  "unfold.contrib.simple_history", # optional, if django-simple-history package is used
@@ -609,6 +612,41 @@ class YourModelAdmin(ModelAdmin):
609
612
  )
610
613
  ```
611
614
 
615
+ ## Nonrelated inlines
616
+
617
+ To display inlines which are not related (no foreign key pointing at the main model) to the model instance in changeform, you can use nonrelated inlines which are included in `unfold.contrib.inlines` module. Make sure this module is included in `INSTALLED_APPS` in settings.py.
618
+
619
+ ```python
620
+ from django.contrib.auth.models import User
621
+ from unfold.admin import ModelAdmin
622
+ from unfold.contrib.inlines.admin import NonrelatedTabularInline
623
+ from .models import OtherModel
624
+
625
+ class OtherNonrelatedInline(NonrelatedTabularInline): # NonrelatedStackedInline is available as well
626
+ model = OtherModel
627
+ fields = ["field1", "field2"] # Ignore property to display all fields
628
+
629
+ def get_form_queryset(self, obj):
630
+ """
631
+ Gets all nonrelated objects needed for inlines. Method must be implemented.
632
+ """
633
+ return self.model.objects.all()
634
+
635
+ def save_new_instance(self, parent, instance):
636
+ """
637
+ Extra save method which can for example update inline instances based on current
638
+ main model object. Method must be implemented.
639
+ """
640
+ pass
641
+
642
+
643
+ @admin.register(User)
644
+ class UserAdmin(ModelAdmin):
645
+ inlines = [OtherNonrelatedInline]
646
+ ```
647
+
648
+ **NOTE:** credit for this functionality goes to [django-nonrelated-inlines](https://github.com/bhomnick/django-nonrelated-inlines)
649
+
612
650
  ## Display decorator
613
651
 
614
652
  Unfold introduces it's own `unfold.decorators.display` decorator. By default it has exactly same behavior as native `django.contrib.admin.decorators.display` but it adds same customizations which helps to extends default logic.
@@ -673,12 +711,15 @@ class UserAdmin(ModelAdmin):
673
711
  """
674
712
  return [
675
713
  "First main heading",
676
- "Smaller additional description", # Use None in case you don't need it
677
- "AB", # Short text which will appear in front of
714
+ "Smaller additional description", # Use None in case you don't need it
715
+ "AB", # Short text which will appear in front of
678
716
  # Image instead of initials. Initials are ignored if image is available
679
717
  {
680
718
  "path": "some/path/picture.jpg,
681
719
  "squared": True, # Picture is displayed in square format, if empty circle
720
+ "borderless": True # Picture will be displayed without border
721
+ "width": 64, # Removes default width. Use together with height
722
+ "height": 48, # Removes default height. Use together with width
682
723
  }
683
724
  ]
684
725
  ```
@@ -798,15 +839,18 @@ Adding support for django-guardian is quote straightforward in Unfold, just add
798
839
 
799
840
  from unfold.admin import ModelAdmin
800
841
  from import_export.admin import ImportExportModelAdmin
801
- from unfold.contrib.import_export.forms import ExportForm, ImportForm
842
+ from unfold.contrib.import_export.forms import ExportForm, ImportForm, SelectableFieldsExportForm
802
843
 
803
844
  class ExampleAdmin(ModelAdmin, ImportExportModelAdmin):
804
845
  import_form_class = ImportForm
805
846
  export_form_class = ExportForm
847
+ # export_form_class = SelectableFieldsExportForm
806
848
  ```
807
849
 
808
850
  When implementing `import_export.admin.ExportActionModelAdmin` class in admin panel, import_export plugin adds its own implementation of action form which is not incorporating Unfold CSS classes. For this reason, `unfold.contrib.import_export.admin` contains class with the same name `ExportActionModelAdmin` which inherits behavior of parent form and adds appropriate CSS classes.
809
851
 
852
+ **Note:** This class has been removed and in new version (4.x) of django-import-export it is not needed.
853
+
810
854
  ```python
811
855
  admin.py
812
856
 
@@ -1111,6 +1155,7 @@ The container has already a node preinstalled so it is possible to compile a new
1111
1155
 
1112
1156
  ## Credits
1113
1157
 
1158
+ - [django-nonrelated-inlines](https://github.com/bhomnick/django-nonrelated-inlines) - Django admin inlines for unrelated models
1114
1159
  - [TailwindCSS](https://tailwindcss.com/) - CSS framework
1115
1160
  - [HTMX](https://htmx.org/) - AJAX communication with backend
1116
1161
  - [Material Icons](https://fonts.google.com/icons) - Icons from Google Fonts
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "django-unfold"
3
- version = "0.25.0"
3
+ version = "0.26.0"
4
4
  description = "Modern Django admin theme for seamless interface development"
5
5
  license = "MIT"
6
6
  readme = "README.md"
@@ -55,6 +55,7 @@ from .widgets import (
55
55
  UnfoldAdminBigIntegerFieldWidget,
56
56
  UnfoldAdminDecimalFieldWidget,
57
57
  UnfoldAdminEmailInputWidget,
58
+ UnfoldAdminFileFieldWidget,
58
59
  UnfoldAdminImageFieldWidget,
59
60
  UnfoldAdminImageSmallFieldWidget,
60
61
  UnfoldAdminIntegerFieldWidget,
@@ -71,6 +72,7 @@ from .widgets import (
71
72
  UnfoldAdminUUIDInputWidget,
72
73
  UnfoldBooleanSwitchWidget,
73
74
  UnfoldBooleanWidget,
75
+ UnfoldForeignKeyRawIdWidget,
74
76
  )
75
77
 
76
78
  try:
@@ -109,6 +111,7 @@ FORMFIELD_OVERRIDES = {
109
111
  models.BigIntegerField: {"widget": UnfoldAdminBigIntegerFieldWidget},
110
112
  models.DecimalField: {"widget": UnfoldAdminDecimalFieldWidget},
111
113
  models.FloatField: {"widget": UnfoldAdminDecimalFieldWidget},
114
+ models.FileField: {"widget": UnfoldAdminFileFieldWidget},
112
115
  models.ImageField: {"widget": UnfoldAdminImageFieldWidget},
113
116
  models.JSONField: {"widget": UnfoldAdminTextareaWidget},
114
117
  models.DurationField: {"widget": UnfoldAdminTextInputWidget},
@@ -142,7 +145,6 @@ FORMFIELD_OVERRIDES_INLINE.update(
142
145
  class UnfoldAdminField(helpers.AdminField):
143
146
  def label_tag(self) -> SafeText:
144
147
  classes = []
145
-
146
148
  if not self.field.field.widget.__class__.__name__.startswith(
147
149
  "Unfold"
148
150
  ) and not self.field.field.widget.template_name.startswith("unfold"):
@@ -181,7 +183,9 @@ helpers.AdminField = UnfoldAdminField
181
183
 
182
184
  class UnfoldAdminReadonlyField(helpers.AdminReadonlyField):
183
185
  def label_tag(self) -> SafeText:
184
- if not isinstance(self.model_admin, ModelAdmin):
186
+ if not isinstance(self.model_admin, ModelAdmin) and not isinstance(
187
+ self.model_admin, ModelAdminMixin
188
+ ):
185
189
  return super().label_tag()
186
190
 
187
191
  attrs = {
@@ -305,10 +309,14 @@ class ModelAdminMixin:
305
309
  def formfield_for_foreignkey(
306
310
  self, db_field: ForeignKey, request: HttpRequest, **kwargs
307
311
  ) -> Optional[ModelChoiceField]:
312
+ db = kwargs.get("using")
313
+
308
314
  # Overrides widgets for all related fields
309
315
  if "widget" not in kwargs:
310
316
  if db_field.name in self.raw_id_fields:
311
- kwargs["widget"] = UnfoldAdminTextInputWidget()
317
+ kwargs["widget"] = UnfoldForeignKeyRawIdWidget(
318
+ db_field.remote_field, self.admin_site, using=db
319
+ )
312
320
  elif (
313
321
  db_field.name not in self.get_autocomplete_fields(request)
314
322
  and db_field.name not in self.radio_fields
@@ -1,8 +1,13 @@
1
+ from django.forms.fields import BooleanField
1
2
  from import_export.forms import ExportForm as BaseExportForm
2
3
  from import_export.forms import ImportForm as BaseImportForm
4
+ from import_export.forms import (
5
+ SelectableFieldsExportForm as BaseSelectableFieldsExportForm,
6
+ )
3
7
  from unfold.widgets import (
4
8
  SELECT_CLASSES,
5
9
  UnfoldAdminFileFieldWidget,
10
+ UnfoldBooleanWidget,
6
11
  )
7
12
 
8
13
 
@@ -18,4 +23,16 @@ class ImportForm(BaseImportForm):
18
23
  class ExportForm(BaseExportForm):
19
24
  def __init__(self, *args, **kwargs):
20
25
  super().__init__(*args, **kwargs)
26
+ self.fields["resource"].widget.attrs["class"] = " ".join(SELECT_CLASSES)
21
27
  self.fields["format"].widget.attrs["class"] = " ".join(SELECT_CLASSES)
28
+
29
+
30
+ class SelectableFieldsExportForm(BaseSelectableFieldsExportForm):
31
+ def __init__(self, formats, resources, **kwargs):
32
+ super().__init__(formats, resources, **kwargs)
33
+ self.fields["resource"].widget.attrs["class"] = " ".join(SELECT_CLASSES)
34
+ self.fields["format"].widget.attrs["class"] = " ".join(SELECT_CLASSES)
35
+
36
+ for _key, field in self.fields.items():
37
+ if isinstance(field, BooleanField):
38
+ field.widget = UnfoldBooleanWidget()
@@ -0,0 +1,10 @@
1
+ {% extends 'admin/change_form.html' %}
2
+ {% load i18n %}
3
+
4
+ {% block actions %}
5
+ {{ block.super }}
6
+
7
+ {% if show_change_form_export %}
8
+ <input type="submit" value="{% translate 'Export' %}" name="_export-item" class="bg-white text-gray-500 border cursor-pointer flex font-medium items-center px-3 py-2 mr-3 rounded-md shadow-sm text-sm dark:bg-gray-900 dark:border dark:border-gray-700 dark:text-gray-400">
9
+ {% endif %}
10
+ {% endblock %}
@@ -0,0 +1,82 @@
1
+ {% extends "admin/import_export/base.html" %}
2
+
3
+ {% load admin_urls i18n import_export_tags %}
4
+
5
+ {% block extrahead %}
6
+ {{ block.super }}
7
+ <script type="text/javascript" src="{% url 'admin:jsi18n' %}"></script>
8
+
9
+ {{ form.media }}
10
+ {% endblock %}
11
+
12
+ {% block breadcrumbs %}
13
+ <div class="px-4 lg:px-12">
14
+ <div class="container mb-6 mx-auto -my-3 lg:mb-12">
15
+ <ul class="flex">
16
+ {% url 'admin:index' as link %}
17
+ {% trans 'Home' as name %}
18
+ {% include 'unfold/helpers/breadcrumb_item.html' with link=link name=name %}
19
+
20
+ {% url 'admin:app_list' app_label=opts.app_label as link %}
21
+ {% include 'unfold/helpers/breadcrumb_item.html' with link=link name=opts.app_config.verbose_name %}
22
+
23
+ {% url opts|admin_urlname:'changelist' as link %}
24
+ {% include 'unfold/helpers/breadcrumb_item.html' with link=link name=opts.verbose_name_plural|capfirst %}
25
+
26
+ {% include 'unfold/helpers/breadcrumb_item.html' with link='' name=cl.opts.verbose_name_plural|capfirst %}
27
+
28
+ {% trans 'Export' as name %}
29
+ {% include 'unfold/helpers/breadcrumb_item.html' with link='' name=name %}
30
+ </ul>
31
+ </div>
32
+ </div>
33
+ {% endblock %}
34
+
35
+ {% block content %}
36
+ <form action="{{ export_url }}" method="POST">
37
+ {% csrf_token %}
38
+
39
+ {% if form.initial.export_items %}
40
+ <p class="bg-blue-50 mb-4 text-blue-500 px-3 py-3 rounded-md text-sm dark:bg-blue-500/20 dark:border-blue-500/10">
41
+ {% blocktranslate count len=form.initial.export_items|length %}
42
+ Export {{ len }} selected item.
43
+ {% plural %}
44
+ Export {{ len }} selected items.
45
+ {% endblocktranslate %}
46
+ </p>
47
+ {% endif %}
48
+
49
+ {% if not form.is_selectable_fields_form %}
50
+ {% include "admin/import_export/resource_fields_list.html" with import_or_export="export" %}
51
+ {% endif %}
52
+
53
+ {{ form.non_field_errors }}
54
+
55
+ <fieldset class="border border-gray-200 mb-4 rounded-md pt-3 px-3 shadow-sm dark:border-gray-800">
56
+ {% for field in form.visible_fields %}
57
+ <div {% if field.field.is_selectable_field %}class="selectable-field-export-row" resource-index="{{ field.field.resource_index }}"{% else %}class="form-row aligned"{% endif %}>
58
+ {% if field.field.initial_field %}
59
+ <p class="block font-medium mb-2 text-gray-900 text-sm dark:text-gray-200">
60
+ {% trans "This exporter will export the following fields" %}
61
+ </p>
62
+ {% endif %}
63
+
64
+ {% if field.field.widget.attrs.readonly %}
65
+ {% include "unfold/helpers/field_readonly.html" with title=field.label value=field.field.value %}
66
+ {{ field.as_hidden }}
67
+ {% else %}
68
+ {% include "unfold/helpers/field.html" with field=field %}
69
+ {% endif %}
70
+ </div>
71
+ {% endfor %}
72
+
73
+ {% for field in form.hidden_fields %}
74
+ {{ field }}
75
+ {% endfor %}
76
+ </fieldset>
77
+
78
+ <button type="submit" class="bg-primary-600 border border-transparent font-medium px-3 py-2 rounded-md text-sm text-white">
79
+ {% translate 'Submit' %}
80
+ </button>
81
+ </form>
82
+ {% endblock %}
@@ -7,20 +7,16 @@
7
7
  {% include "admin/import_export/resource_fields_list.html" with import_or_export="import" %}
8
8
 
9
9
  <fieldset class="border border-gray-200 mb-8 rounded-md pt-3 px-3 shadow-sm dark:border-gray-800">
10
- {% if form.resource.field.widget.attrs.readonly %}
11
- {% include "unfold/helpers/field_readonly.html" with title=form.resource.field.label value=form.resource.field.value %}
12
- {{ form.resource.as_hidden }}
13
- {% else %}
14
- {% include "unfold/helpers/field.html" with field=form.resource %}
15
- {% endif %}
16
-
17
-
18
- {% include "unfold/helpers/field.html" with field=form.import_file %}
19
-
20
- {% include "unfold/helpers/field.html" with field=form.format %}
10
+ {% for field in form %}
11
+ {% if field.field.widget.attrs.readonly %}
12
+ {% include "unfold/helpers/field_readonly.html" with title=field.label value=field.field.value %}
13
+ {{ field.as_hidden }}
14
+ {% else %}
15
+ {% include "unfold/helpers/field.html" with field=field %}
16
+ {% endif %}
17
+ {% endfor %}
21
18
  </fieldset>
22
19
 
23
-
24
20
  <button type="submit" class="bg-primary-600 border border-transparent font-medium px-3 py-2 rounded-md text-sm text-white">
25
21
  {% translate 'Submit' %}
26
22
  </button>
@@ -1,7 +1,7 @@
1
1
  {% load i18n %}
2
2
 
3
3
  {% block fields_help %}
4
- <div class="bg-blue-50 mb-8 text-blue-500 px-3 py-3 rounded-md text-sm dark:bg-blue-500/20 dark:border-blue-500/10">
4
+ <div class="bg-blue-50 mb-4 text-blue-500 px-3 py-3 rounded-md text-sm dark:bg-blue-500/20 dark:border-blue-500/10">
5
5
  {% if import_or_export == "export" %}
6
6
  {% trans "This exporter will export the following fields: " %}
7
7
  {% elif import_or_export == "import" %}
@@ -0,0 +1,141 @@
1
+ from functools import partial
2
+ from typing import Any, Optional
3
+
4
+ from django import forms
5
+ from django.contrib.admin.utils import NestedObjects, flatten_fieldsets
6
+ from django.core.exceptions import ValidationError
7
+ from django.db import router
8
+ from django.db.models import Model
9
+ from django.forms.formsets import DELETION_FIELD_NAME
10
+ from django.forms.models import modelform_defines_fields
11
+ from django.http import HttpRequest
12
+ from django.utils.text import get_text_list
13
+ from django.utils.translation import gettext_lazy as _
14
+ from unfold.admin import StackedInline, TabularInline
15
+
16
+ from .checks import NonrelatedModelAdminChecks
17
+ from .forms import NonrelatedInlineModelFormSet, nonrelated_inline_formset_factory
18
+
19
+
20
+ class NonrelatedInlineMixin:
21
+ checks_class = NonrelatedModelAdminChecks
22
+ formset = NonrelatedInlineModelFormSet
23
+
24
+ def get_formset(
25
+ self, request: HttpRequest, obj: Optional[Model] = None, **kwargs: Any
26
+ ):
27
+ defaults = self._get_formset_defaults(request, obj, **kwargs)
28
+
29
+ defaults["queryset"] = (
30
+ self.get_form_queryset(obj) if obj else self.model.objects.none()
31
+ )
32
+
33
+ return nonrelated_inline_formset_factory(
34
+ self.model, save_new_instance=self.save_new_instance, **defaults
35
+ )
36
+
37
+ def _get_formset_defaults(
38
+ self, request: HttpRequest, obj: Optional[Model] = None, **kwargs: Any
39
+ ):
40
+ """Return a BaseInlineFormSet class for use in admin add/change views."""
41
+ if "fields" in kwargs:
42
+ fields = kwargs.pop("fields")
43
+ else:
44
+ fields = flatten_fieldsets(self.get_fieldsets(request, obj))
45
+ excluded = self.get_exclude(request, obj)
46
+ exclude = [] if excluded is None else list(excluded)
47
+ exclude.extend(self.get_readonly_fields(request, obj))
48
+ if excluded is None and hasattr(self.form, "_meta") and self.form._meta.exclude:
49
+ # Take the custom ModelForm's Meta.exclude into account only if the
50
+ # InlineModelAdmin doesn't define its own.
51
+ exclude.extend(self.form._meta.exclude)
52
+ # If exclude is an empty list we use None, since that's the actual
53
+ # default.
54
+ exclude = exclude or None
55
+ can_delete = self.can_delete and self.has_delete_permission(request, obj)
56
+ defaults = {
57
+ "form": self.form,
58
+ "formset": self.formset,
59
+ # "fk_name": self.fk_name,
60
+ "fields": fields,
61
+ "exclude": exclude,
62
+ "formfield_callback": partial(self.formfield_for_dbfield, request=request),
63
+ "extra": self.get_extra(request, obj, **kwargs),
64
+ "min_num": self.get_min_num(request, obj, **kwargs),
65
+ "max_num": self.get_max_num(request, obj, **kwargs),
66
+ "can_delete": can_delete,
67
+ **kwargs,
68
+ }
69
+
70
+ base_model_form = defaults["form"]
71
+ can_change = self.has_change_permission(request, obj) if request else True
72
+ can_add = self.has_add_permission(request, obj) if request else True
73
+
74
+ class DeleteProtectedModelForm(base_model_form):
75
+ def hand_clean_DELETE(self):
76
+ """
77
+ We don't validate the 'DELETE' field itself because on
78
+ templates it's not rendered using the field information, but
79
+ just using a generic "deletion_field" of the InlineModelAdmin.
80
+ """
81
+ if self.cleaned_data.get(DELETION_FIELD_NAME, False):
82
+ using = router.db_for_write(self._meta.model)
83
+ collector = NestedObjects(using=using)
84
+ if self.instance._state.adding:
85
+ return
86
+ collector.collect([self.instance])
87
+ if collector.protected:
88
+ objs = []
89
+ for p in collector.protected:
90
+ objs.append(
91
+ # Translators: Model verbose name and instance representation,
92
+ # suitable to be an item in a list.
93
+ _("%(class_name)s %(instance)s")
94
+ % {
95
+ "class_name": p._meta.verbose_name,
96
+ "instance": p,
97
+ }
98
+ )
99
+ params = {
100
+ "class_name": self._meta.model._meta.verbose_name,
101
+ "instance": self.instance,
102
+ "related_objects": get_text_list(objs, _("and")),
103
+ }
104
+ msg = _(
105
+ "Deleting %(class_name)s %(instance)s would require "
106
+ "deleting the following protected related objects: "
107
+ "%(related_objects)s"
108
+ )
109
+ raise ValidationError(
110
+ msg, code="deleting_protected", params=params
111
+ )
112
+
113
+ def is_valid(self):
114
+ result = super().is_valid()
115
+ self.hand_clean_DELETE()
116
+ return result
117
+
118
+ def has_changed(self):
119
+ # Protect against unauthorized edits.
120
+ if not can_change and not self.instance._state.adding:
121
+ return False
122
+ if not can_add and self.instance._state.adding:
123
+ return False
124
+ return super().has_changed()
125
+
126
+ defaults["form"] = DeleteProtectedModelForm
127
+
128
+ if defaults["fields"] is None and not modelform_defines_fields(
129
+ defaults["form"]
130
+ ):
131
+ defaults["fields"] = forms.ALL_FIELDS
132
+
133
+ return defaults
134
+
135
+
136
+ class NonrelatedStackedInline(NonrelatedInlineMixin, StackedInline):
137
+ pass
138
+
139
+
140
+ class NonrelatedTabularInline(NonrelatedInlineMixin, TabularInline):
141
+ pass
@@ -0,0 +1,6 @@
1
+ from django.apps import AppConfig
2
+
3
+
4
+ class DefaultAppConfig(AppConfig):
5
+ name = "unfold.contrib.inlines"
6
+ label = "unfold_inlines"
@@ -0,0 +1,18 @@
1
+ from typing import List
2
+
3
+ from django.contrib.admin.checks import InlineModelAdminChecks
4
+ from django.contrib.admin.options import InlineModelAdmin
5
+ from django.core.checks import CheckMessage
6
+ from django.db.models import Model
7
+
8
+
9
+ class NonrelatedModelAdminChecks(InlineModelAdminChecks):
10
+ def _check_exclude_of_parent_model(
11
+ self, obj: InlineModelAdmin, parent_model: Model
12
+ ) -> List[CheckMessage]:
13
+ return []
14
+
15
+ def _check_relation(
16
+ self, obj: InlineModelAdmin, parent_model: Model
17
+ ) -> List[CheckMessage]:
18
+ return []