django-unfold 0.24.0__py3-none-any.whl → 0.26.0__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 (37) hide show
  1. {django_unfold-0.24.0.dist-info → django_unfold-0.26.0.dist-info}/METADATA +51 -6
  2. {django_unfold-0.24.0.dist-info → django_unfold-0.26.0.dist-info}/RECORD +36 -26
  3. unfold/admin.py +11 -3
  4. unfold/contrib/import_export/forms.py +28 -5
  5. unfold/contrib/import_export/templates/admin/import_export/change_form.html +10 -0
  6. unfold/contrib/import_export/templates/admin/import_export/export.html +38 -3
  7. unfold/contrib/import_export/templates/admin/import_export/import_form.html +9 -20
  8. unfold/contrib/import_export/templates/admin/import_export/resource_fields_list.html +24 -0
  9. unfold/contrib/inlines/__init__.py +0 -0
  10. unfold/contrib/inlines/admin.py +141 -0
  11. unfold/contrib/inlines/apps.py +6 -0
  12. unfold/contrib/inlines/checks.py +18 -0
  13. unfold/contrib/inlines/forms.py +43 -0
  14. unfold/forms.py +6 -0
  15. unfold/static/unfold/css/simplebar.css +230 -0
  16. unfold/static/unfold/css/styles.css +1 -1
  17. unfold/static/unfold/js/simplebar.js +10 -0
  18. unfold/styles.css +10 -2
  19. unfold/templates/admin/app_list.html +1 -1
  20. unfold/templates/admin/change_form.html +11 -9
  21. unfold/templates/admin/change_list_results.html +67 -65
  22. unfold/templates/admin/edit_inline/stacked.html +7 -7
  23. unfold/templates/admin/edit_inline/tabular.html +111 -109
  24. unfold/templates/admin/includes/fieldset.html +1 -1
  25. unfold/templates/unfold/helpers/app_list.html +1 -1
  26. unfold/templates/unfold/helpers/display_header.html +11 -8
  27. unfold/templates/unfold/helpers/field.html +20 -6
  28. unfold/templates/unfold/helpers/fieldsets_tabs.html +4 -4
  29. unfold/templates/unfold/helpers/form_label.html +1 -1
  30. unfold/templates/unfold/layouts/skeleton.html +2 -0
  31. unfold/templates/unfold/widgets/foreign_key_raw_id.html +21 -0
  32. unfold/templates/unfold/widgets/textarea.html +1 -7
  33. unfold/templates/unfold/widgets/textarea_expandable.html +7 -0
  34. unfold/widgets.py +36 -3
  35. unfold/contrib/import_export/admin.py +0 -37
  36. {django_unfold-0.24.0.dist-info → django_unfold-0.26.0.dist-info}/LICENSE.md +0 -0
  37. {django_unfold-0.24.0.dist-info → django_unfold-0.26.0.dist-info}/WHEEL +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: django-unfold
3
- Version: 0.24.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
@@ -1,5 +1,5 @@
1
1
  unfold/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- unfold/admin.py,sha256=iNlDiZy_kl4lk2We4VDKOK5lMam4GeNMOA-bo67ykqU,23810
2
+ unfold/admin.py,sha256=ATDHEq87eC1zgtoObwqTCpRKqJbl0yrS0rf6AAHZTxM,24133
3
3
  unfold/apps.py,sha256=SlBXPYrUd2uXn67qFbRvbXSUk3XFWrF4-5WELgDCvho,381
4
4
  unfold/checks.py,sha256=Smgji9w19hnYjJElJ_FJnnyTEAE-E-OUB6otHu7lasY,1670
5
5
  unfold/contrib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -36,20 +36,26 @@ unfold/contrib/guardian/templates/admin/guardian/model/obj_perms_manage_user.htm
36
36
  unfold/contrib/guardian/templates/unfold/guardian/group_form.html,sha256=P8WMC5EejUHV5AxEiIQ2LOGzefLHk5J5UHiNq9wnBgY,4145
37
37
  unfold/contrib/guardian/templates/unfold/guardian/user_form.html,sha256=ci7FRrhTEKbFKKxsJ-07_dWXBYz4mqXPoqu5HfqYLaM,4132
38
38
  unfold/contrib/import_export/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
39
- unfold/contrib/import_export/admin.py,sha256=h6CKRuvloEdxcVScycTSAShXEfzEAsL75uMj2ullhOM,1151
40
39
  unfold/contrib/import_export/apps.py,sha256=SdJu6Qh90VqGWY19FSDhhpUqhTbaIYsJKny3zX5baHI,149
41
- unfold/contrib/import_export/forms.py,sha256=DCTjCqeWT0jyPAMZgDDad0LoWtKRGu1Q5TohNpnpMAA,637
40
+ unfold/contrib/import_export/forms.py,sha256=cmUUiULJo771rbxf-uCarrbRNwvzCIketbP_7eFnvGc,1496
42
41
  unfold/contrib/import_export/templates/admin/import_export/base.html,sha256=loL2qcV-f8aAzkHss_I4IkwfgemVW2CjOu_aiBxdwX0,357
42
+ unfold/contrib/import_export/templates/admin/import_export/change_form.html,sha256=_YorgltKO0CRSaLBAp67XnGMUBWEP_XewsUff0hlrE4,446
43
43
  unfold/contrib/import_export/templates/admin/import_export/change_list_export_item.html,sha256=pTDeqPKOlCPKH2dxMIfPnWuc2wVDzB7AzL73WbxSnRY,257
44
44
  unfold/contrib/import_export/templates/admin/import_export/change_list_import_export.html,sha256=JdKd6P2Ot9Ou4yg4CywTauuE1UiTz_mRvDwlx3vj3LI,229
45
45
  unfold/contrib/import_export/templates/admin/import_export/change_list_import_item.html,sha256=XUuRxnsx9YQbKvW-E_JGl_ha7kpTSGSoRefOTTizuX0,233
46
- unfold/contrib/import_export/templates/admin/import_export/export.html,sha256=W-ZId8LJCzA3Kuzxun7v-RNzqo7q8cxRk-vmd8xaC0s,1786
46
+ unfold/contrib/import_export/templates/admin/import_export/export.html,sha256=a0gL1YvlFTYQEpJuab-Ue_YL86UO5VkfREqy5CepZUg,3481
47
47
  unfold/contrib/import_export/templates/admin/import_export/import.html,sha256=P54_f3s96PV87Bo-FCZfmsn9DkRXLOB36r7HYF6y7GM,2075
48
48
  unfold/contrib/import_export/templates/admin/import_export/import_confirm.html,sha256=M-acK4XSLHuPFD_NJashGYvPPeJrJsC-3LMvHs3lRis,867
49
49
  unfold/contrib/import_export/templates/admin/import_export/import_errors.html,sha256=0DmJvZs31u-E2Y53yySci86cTnG9aUnOzvfYrOo0lYA,1422
50
- unfold/contrib/import_export/templates/admin/import_export/import_form.html,sha256=F0cLh5AAyVpgxPClKcIXSt1bLRR1lESTdaSMU0Z_6G4,1303
50
+ unfold/contrib/import_export/templates/admin/import_export/import_form.html,sha256=mMuMTAbgMbJ1IyCQPBkzmob4m5lJmZ69_QSo3GvvSiY,990
51
51
  unfold/contrib/import_export/templates/admin/import_export/import_preview.html,sha256=pNuLDW6zc5yOF1jurL2EgR0j05RL9ZVJLZiV4R21GJc,2413
52
52
  unfold/contrib/import_export/templates/admin/import_export/import_validation.html,sha256=1wQOiXN_Ga9VO6GGyl__KEiuJlCh4gTqzZdzIbmKxG0,4880
53
+ unfold/contrib/import_export/templates/admin/import_export/resource_fields_list.html,sha256=7LzgBiT73c4GHVZx3-ap_cuMz57EnIJ1ESGA5xR31mM,871
54
+ unfold/contrib/inlines/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
55
+ unfold/contrib/inlines/admin.py,sha256=p55cNAFOwEFToyFdXUtGl6Vt6j89s9i42V4kHYSZ5Ws,5928
56
+ unfold/contrib/inlines/apps.py,sha256=Z9JBnzywq-DanZbD56fG0ndBfLXbojzkjVBleqoOBSU,136
57
+ unfold/contrib/inlines/checks.py,sha256=8sdyBcxw0erqQvp9sHlpGgy0rXfum-cd2eQE0rXFKQ0,559
58
+ unfold/contrib/inlines/forms.py,sha256=R9OJvrbqNLlKvTxw97JjElCY4CQ3IyRIkjIJUN0gJ9k,1323
53
59
  unfold/contrib/simple_history/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
54
60
  unfold/contrib/simple_history/apps.py,sha256=eF_KVYb60CAnGgWk2Z1YKYGfgA3TJBMr229qI7e2pgU,153
55
61
  unfold/contrib/simple_history/templates/simple_history/_object_history_list.html,sha256=aXOQ1zwsRBlFmzODsZApvMtb8t1IPXim6i4plXUR5XE,5112
@@ -59,10 +65,11 @@ unfold/contrib/simple_history/templates/simple_history/submit_line.html,sha256=n
59
65
  unfold/dataclasses.py,sha256=JJdGYzQ8MpeOe2FQPJqrMn_UJcxUz1VJgHCuCtkZCA8,199
60
66
  unfold/decorators.py,sha256=BVDlxhZxB4ND3f5-5oiENRTv_W_Q_Eu-gZlsrYKOxiU,3272
61
67
  unfold/exceptions.py,sha256=gcCj1ox61E137bk_0Cqy4YC3SttdPgB-fiJUqpmyHSE,43
62
- unfold/forms.py,sha256=SzdyBC5wqE5IcoZWS2oXObycmfmICHsqlS3X03mw4QA,3468
68
+ unfold/forms.py,sha256=GXEm3CFwglyuEbGdVyEMJTB45Gs-_RvGGlXJEkPy2kw,3688
63
69
  unfold/settings.py,sha256=--TdTSWdOA8TQGW4-vjJkjy_zEyd_kZwBr3BIuQ8hzI,1208
64
70
  unfold/sites.py,sha256=Gy_i43j2nizW2g8-mas5icvtk-beKism_CznATW6Ia8,12586
65
- unfold/static/unfold/css/styles.css,sha256=DjRQV4lwg81SmOyR1YRs1QWHNA0FdV7XYRiYP33lTig,91399
71
+ unfold/static/unfold/css/simplebar.css,sha256=5LLaEM11pKi6JFCOLt4XKuZxTpT9rpdq_tNlaQytFlU,4647
72
+ unfold/static/unfold/css/styles.css,sha256=hlPYMtAEeIPl7yIFpqMR4DqJwz9K2RLhpbI4aSNq6mU,91675
66
73
  unfold/static/unfold/fonts/inter/Inter-Bold.woff2,sha256=O88EyjAeRPE_QEyKBKpK5wf2epUOEu8wwjj5bnhCZqE,46552
67
74
  unfold/static/unfold/fonts/inter/Inter-Medium.woff2,sha256=O88EyjAeRPE_QEyKBKpK5wf2epUOEu8wwjj5bnhCZqE,46552
68
75
  unfold/static/unfold/fonts/inter/Inter-Regular.woff2,sha256=O88EyjAeRPE_QEyKBKpK5wf2epUOEu8wwjj5bnhCZqE,46552
@@ -75,26 +82,27 @@ unfold/static/unfold/js/alpine.persist.js,sha256=84PZYnPi25AFm7wIWRe1gzA74c5Rv2V
75
82
  unfold/static/unfold/js/app.js,sha256=CIitJoFqpeZYPw8icGVXYX9tVRUgqFxcPZ2WjWS8Ylk,5288
76
83
  unfold/static/unfold/js/chart.js,sha256=22W6cFERR-CElMOKRgMMicueMVP0Vf7FBEBYH8Z8tCk,200633
77
84
  unfold/static/unfold/js/htmx.js,sha256=XOLqvnZiyEx46EW9vaJTBUaaWg8CGVVfXJkVsUmJbpI,42820
78
- unfold/styles.css,sha256=dlTJBzFvZEfH9xSs2AJ9nfzYTnxf8muCMa8COifqmzU,17598
85
+ unfold/static/unfold/js/simplebar.js,sha256=t-uG1FAD6ZoiMeN--wac0XRS7SxoDVG6zvRnGuEp7X8,27176
86
+ unfold/styles.css,sha256=JA2ybI-pzRM4ZOKshI187oJ5Z3gMNWHQAuEfwq5Xb_E,17854
79
87
  unfold/templates/admin/actions.html,sha256=1tVlUpLoM72K2Ew4vQGcRwPjHuAtO5Jm4QdDsDLOq0I,2625
80
88
  unfold/templates/admin/app_index.html,sha256=lVjMIFsspHQ09LGHKfdfg7TlqlL39AX5LbwoeoZjFhk,1335
81
- unfold/templates/admin/app_list.html,sha256=7u2Ex0ArdC0CJNCTDnTEZpAXI_xbNQ1nrzAH4BuInNA,3009
89
+ unfold/templates/admin/app_list.html,sha256=krDzw2EXqqvIi8bJtPhJsNran9H7hwdhM6ZW_IRlDwQ,3038
82
90
  unfold/templates/admin/auth/user/add_form.html,sha256=iLig-vd2YExXsj0xGBwYhZ4kGUihwYtLtNVhzObgSzg,478
83
91
  unfold/templates/admin/auth/user/change_password.html,sha256=-Wa9ml3yss-kDz0YQxCiwoxs91KQD8eetCt5l6xekWM,2892
84
92
  unfold/templates/admin/base.html,sha256=MGqtCcydXZPnp6dasaWktyd9D6rdUYX01rFGAv7Zkm4,2226
85
93
  unfold/templates/admin/base_site.html,sha256=3ckWrcAdd7Pw1hk6Zwyknab_Qb-rteV9-mXhMnfo6VI,361
86
- unfold/templates/admin/change_form.html,sha256=-X_fQOGaa6k0WVbMO7he9bZIdIY3oj8PyRSV4dnt6qA,5320
94
+ unfold/templates/admin/change_form.html,sha256=OvegZJTH4eGHXf5RJOHfy9tXKCtyml_Yl8pENb9kNq8,5431
87
95
  unfold/templates/admin/change_form_object_tools.html,sha256=eyeH-i2HgEM0Yi-OJA2D1VnKJyC19A_my1IDGxxoP8Y,593
88
96
  unfold/templates/admin/change_list.html,sha256=18GDZswc1c0xtw2BcKti9SX95Ar9e1BX_HSY0K79g_8,5102
89
97
  unfold/templates/admin/change_list_object_tools.html,sha256=cmMiT2nT20Ph5yfpj9aHPr76Z-JP4aSXp0o-Rnad28s,147
90
- unfold/templates/admin/change_list_results.html,sha256=32zSgJ6W5uQlfzI-0N1FmCFagw2VYaXuiUZyZbxUIag,5004
98
+ unfold/templates/admin/change_list_results.html,sha256=Ie2NGfIiU0HHy1a5wJ-YJV1doZkibVRCmR3DRZdoV2I,5395
91
99
  unfold/templates/admin/date_hierarchy.html,sha256=BfUPbsLpHZVa40BHBahz1H9RSVuz36Jc3yrlobOiIpw,1306
92
100
  unfold/templates/admin/delete_confirmation.html,sha256=hpa2E14oZEXBBs6W1qdNQuF650TIO2Rhr52Q6UfwVeQ,5166
93
101
  unfold/templates/admin/delete_selected_confirmation.html,sha256=Foka2yvwAMEZre-Kh1KNadRzrCotdKM2U4e6AJQYZu8,4941
94
- unfold/templates/admin/edit_inline/stacked.html,sha256=U6O_r9-5Hp7mT0l1EgTeBB8tc9nEAAi0etL2aCU2pBM,4415
95
- unfold/templates/admin/edit_inline/tabular.html,sha256=YOrCgAQ9apLZf8VtFmUhK-WFoQomPtlilT9ktkEFBQA,12315
102
+ unfold/templates/admin/edit_inline/stacked.html,sha256=HG-Dj42gcKNofHRVjg0ltIER2oJGYUd9GN_B7lDv7rQ,4580
103
+ unfold/templates/admin/edit_inline/tabular.html,sha256=mVlQ5aJr6-GdHM2zaWVUKaa6gok3Vv3MAMQj0sIX-lQ,12976
96
104
  unfold/templates/admin/filter.html,sha256=dkrFkei-EAlldIU8DrgvSChzWQuUOu6-LS_qlZxdfFw,1708
97
- unfold/templates/admin/includes/fieldset.html,sha256=r4XjcZAOkWxHQExHZBWoCGtO3LYL0Iwkw1C55oR5V6M,2898
105
+ unfold/templates/admin/includes/fieldset.html,sha256=qVxXy7KRI8GC4bIBPO9hjQlMtDg83vhEZbmVXqdfrgg,2929
98
106
  unfold/templates/admin/includes/object_delete_summary.html,sha256=Nv69SCzyJHFX14iJFfodxKM0IIpQegKZH0fvKB15QJI,468
99
107
  unfold/templates/admin/index.html,sha256=pkGdKWdD3zzOvkRdELvdb15sleSpfl4eHPA14PAh7z0,684
100
108
  unfold/templates/admin/login.html,sha256=WdOfFLofwBWj9VKCq1U22uLY19J2YQY6vRaE4OOSKfQ,3681
@@ -121,17 +129,17 @@ unfold/templates/unfold/components/title.html,sha256=PSiNK-s8jUJfu6f9zCcGOOyLiKx
121
129
  unfold/templates/unfold/helpers/account_links.html,sha256=Kc1FobAVN3B34x9vcMoEXyuQ45d5SjfjaJSo3UErL3Q,1934
122
130
  unfold/templates/unfold/helpers/actions_row.html,sha256=1xd39zx38NOoKuDuxAG7PHeu5x2OTIraQGFkm15Erqg,1681
123
131
  unfold/templates/unfold/helpers/add_link.html,sha256=mIgpKrwqBO1oJ4cwPQWSX1oUHBwHJmy5-2TxUHf-1bo,808
124
- unfold/templates/unfold/helpers/app_list.html,sha256=FvL-cEOVxwckP5TqzLEYL34EMlYiCd6gRy0oguBaRMw,4691
132
+ unfold/templates/unfold/helpers/app_list.html,sha256=lFnW8p9DcZbI9t3_ee9JX9ERHA0NRL2V88zpzuG4jq8,4720
125
133
  unfold/templates/unfold/helpers/app_list_default.html,sha256=vZkw1F7oHOKReNkdHRYjhuNdA1nNdvSD4wbDmf0bnsM,4102
126
134
  unfold/templates/unfold/helpers/boolean.html,sha256=p_WOlytoXvDwta76WgcV4JSWKpBgKf4amhqmHF798F8,564
127
135
  unfold/templates/unfold/helpers/breadcrumb_item.html,sha256=k_1j57UV0WtzFFlMKaewj4NLbR_DhXI6RzCHThblZLw,234
128
- unfold/templates/unfold/helpers/display_header.html,sha256=J49ReIVl8Z29714HMIH-zFfaQdraMRS32VL1Ewg4W9M,808
136
+ unfold/templates/unfold/helpers/display_header.html,sha256=RR3HexzdO3YazPSJYfF9UfujCDiJ_EDrmnfxDFNLd7U,1160
129
137
  unfold/templates/unfold/helpers/display_label.html,sha256=LS9DWzYjHkYLV27sZDwyXlg2sLJ0AlId9FbjnXpsbfg,317
130
- unfold/templates/unfold/helpers/field.html,sha256=oEhGUrLZi2hiuLaC96R2zdwD8DNZqX2_sJIxTpPTJDM,340
138
+ unfold/templates/unfold/helpers/field.html,sha256=Ds-zUHkdyxamfUCVNhxvtM0XoJg9OCA0QcsLbLWv4oo,882
131
139
  unfold/templates/unfold/helpers/field_readonly.html,sha256=v7-2oSSDgOsuYpP70y8DqdBqbRybubAfSDzstveoBuw,382
132
- unfold/templates/unfold/helpers/fieldsets_tabs.html,sha256=-l8ni5jeJQPNxucAn4ujbts08Bp2WuGlQGnHpBMk5Os,1316
140
+ unfold/templates/unfold/helpers/fieldsets_tabs.html,sha256=V3bgW75eozaBDty-xfciGafhCWq_Ba5HfQkk92yRc9A,1445
133
141
  unfold/templates/unfold/helpers/form_errors.html,sha256=EwerIJptSCWXvtAJ1IZKfEn98qlShBIGavsTThbklAs,266
134
- unfold/templates/unfold/helpers/form_label.html,sha256=5wKKBXVPwziV5v5fbYatpRvnvSJBDJf_7znNdE6V8IM,237
142
+ unfold/templates/unfold/helpers/form_label.html,sha256=SR4U6iK9w4oels6iGY_Da-yN4BbXQVN9zCDlBGGXcw8,310
135
143
  unfold/templates/unfold/helpers/header.html,sha256=jklASqVEJRa22jxdXq_X2UZb2uYn_ywaZbI2N4nBv20,998
136
144
  unfold/templates/unfold/helpers/help_text.html,sha256=iBXw0LWfoYT5PoPLJek9ixv4SuK7hfVkjPgmv2ODW-s,146
137
145
  unfold/templates/unfold/helpers/history.html,sha256=0_Imm7Fc1PqjjXEmHh8QEQg_qIqBZWx2BeK5o3axfvY,2017
@@ -154,10 +162,11 @@ unfold/templates/unfold/helpers/theme_switch.html,sha256=skkl6fYUnYLM7fAPivHxWjn
154
162
  unfold/templates/unfold/helpers/userlinks.html,sha256=qWjtBt9Q_tU8a874ii0Qqg8t_d-SSYBTB_3QZfNlx9g,634
155
163
  unfold/templates/unfold/helpers/welcomemsg.html,sha256=noRysgSENef4_53pXaTiBCy2or6lQm1ZtmCQVODAB1c,1120
156
164
  unfold/templates/unfold/layouts/base_simple.html,sha256=rki7n7QagHFAaCEn488pTOj9dpNL9AwwzKps8Ipiubk,993
157
- unfold/templates/unfold/layouts/skeleton.html,sha256=D35u-G6-h5SwTMzIZaEURedsPObSjoB198lLsJwmZWs,3278
165
+ unfold/templates/unfold/layouts/skeleton.html,sha256=iXrUiggVp36vmBIia5p32c-9Ruy0PxkFFQogDpvENbk,3419
158
166
  unfold/templates/unfold/widgets/clearable_file_input.html,sha256=vXsyP0-YD-z3z6VL4vXW9pJH9_-ZU9u-3AnmZkni-R4,1994
159
167
  unfold/templates/unfold/widgets/clearable_file_input_small.html,sha256=rqUnHF4jwL8_RySUuq2aXgj-0P_usgo1HeVT_IcfyFY,2531
160
168
  unfold/templates/unfold/widgets/date.html,sha256=WXo2LG1v_gBZBSg-zocj7oujMKI0MWLYCIFfB04HMLQ,122
169
+ unfold/templates/unfold/widgets/foreign_key_raw_id.html,sha256=26UGK04ojS-ZsvhWpPIbr6VE9b91Q2sEhB7FBkMY1NI,917
161
170
  unfold/templates/unfold/widgets/radio.html,sha256=3WcmclQNg7R_pRjEHL1dHkGjAzWlWNYnhHkAirC4nuA,646
162
171
  unfold/templates/unfold/widgets/radio_option.html,sha256=IZgPx-aWKJuxrSalJ3K50RFd1vwSpb9Qk0yZwfV78_A,368
163
172
  unfold/templates/unfold/widgets/range.html,sha256=28FBtSUgUcG82vpk_I27Lbs5oWZOV_oMzVhx4wj3-Ik,262
@@ -165,7 +174,8 @@ unfold/templates/unfold/widgets/related_widget_wrapper.html,sha256=0I6wSu8z_sJPq
165
174
  unfold/templates/unfold/widgets/split_datetime.html,sha256=eXLFZyCv84LCTFWAUhNO3xAIzWvGBvI1ZpYbB38_HOI,862
166
175
  unfold/templates/unfold/widgets/split_datetime_vertical.html,sha256=xinCH4kkQ-yKUqcSI7-m-_UEzOEKWqvLTjUa3i-e8EM,881
167
176
  unfold/templates/unfold/widgets/split_money.html,sha256=AFLUBmzGbY-RXgsfz7gaDxVRhplaIPhXjg_hWYo9xcY,352
168
- unfold/templates/unfold/widgets/textarea.html,sha256=4xIGWb20DuwiwumndByrAyh7xF-ReXKLulSpDImX_cs,459
177
+ unfold/templates/unfold/widgets/textarea.html,sha256=-ZLDGrtASero7L-J3VvTNq_KjPAZh_kLVw0Ow3awqXM,144
178
+ unfold/templates/unfold/widgets/textarea_expandable.html,sha256=4xIGWb20DuwiwumndByrAyh7xF-ReXKLulSpDImX_cs,459
169
179
  unfold/templates/unfold/widgets/time.html,sha256=WXo2LG1v_gBZBSg-zocj7oujMKI0MWLYCIFfB04HMLQ,122
170
180
  unfold/templatetags/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
171
181
  unfold/templatetags/unfold.py,sha256=HFe0GrTD4va0lLzsZhxqjEOONmehqOWdf5vulkxgfGU,6302
@@ -173,8 +183,8 @@ unfold/templatetags/unfold_list.py,sha256=5xAjQX0_JnVwDaj-wGkGqbjOAtp-a18koWIKj5
173
183
  unfold/typing.py,sha256=1P8PWM2oeaceUJtA5j071RbKEBpHYaux441u7Hd6wv4,643
174
184
  unfold/utils.py,sha256=5OIgDcwvIJQbwbnnqHx61cHh-2T1h184mTAuNq5WXLI,4088
175
185
  unfold/views.py,sha256=Ml3XlEoHLcbEWof59Dw8ihKBMcmp-gBAibThtBFj55A,708
176
- unfold/widgets.py,sha256=JfcWOWtPPxqosXMyP-BcfO6UK53eoEU3obRpMZijED4,14216
177
- django_unfold-0.24.0.dist-info/LICENSE.md,sha256=Ltk_quRyyvV3J5v3brtOqmibeZSw2Hrb8bY1W3ya0Ik,1077
178
- django_unfold-0.24.0.dist-info/METADATA,sha256=ph7g7IiHyDYbuoztj_K9eodilCfHAXFTjU_29nuGwHg,46669
179
- django_unfold-0.24.0.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
180
- django_unfold-0.24.0.dist-info/RECORD,,
186
+ unfold/widgets.py,sha256=iiI73XznYH34LgXBHu1oVtYb76lLO3HiOD9blmm89rY,15236
187
+ django_unfold-0.26.0.dist-info/LICENSE.md,sha256=Ltk_quRyyvV3J5v3brtOqmibeZSw2Hrb8bY1W3ya0Ik,1077
188
+ django_unfold-0.26.0.dist-info/METADATA,sha256=UUv_H7BwNNquFABkpQ1PObEBBKknsGFxkyDnkk3l5oU,48746
189
+ django_unfold-0.26.0.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
190
+ django_unfold-0.26.0.dist-info/RECORD,,
unfold/admin.py CHANGED
@@ -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,15 +1,38 @@
1
- from import_export.forms import ImportExportFormBase as BaseImportExportFormBase
2
- from unfold.widgets import SELECT_CLASSES, UnfoldAdminFileFieldWidget
1
+ from django.forms.fields import BooleanField
2
+ from import_export.forms import ExportForm as BaseExportForm
3
+ from import_export.forms import ImportForm as BaseImportForm
4
+ from import_export.forms import (
5
+ SelectableFieldsExportForm as BaseSelectableFieldsExportForm,
6
+ )
7
+ from unfold.widgets import (
8
+ SELECT_CLASSES,
9
+ UnfoldAdminFileFieldWidget,
10
+ UnfoldBooleanWidget,
11
+ )
3
12
 
4
13
 
5
- class ImportForm(BaseImportExportFormBase):
14
+ class ImportForm(BaseImportForm):
6
15
  def __init__(self, *args, **kwargs):
7
16
  super().__init__(*args, **kwargs)
8
- self.fields["resource"].widget = UnfoldAdminFileFieldWidget()
17
+
18
+ self.fields["resource"].widget.attrs["class"] = " ".join(SELECT_CLASSES)
19
+ self.fields["import_file"].widget = UnfoldAdminFileFieldWidget()
9
20
  self.fields["format"].widget.attrs["class"] = " ".join(SELECT_CLASSES)
10
21
 
11
22
 
12
- class ExportForm(BaseImportExportFormBase):
23
+ class ExportForm(BaseExportForm):
13
24
  def __init__(self, *args, **kwargs):
14
25
  super().__init__(*args, **kwargs)
26
+ self.fields["resource"].widget.attrs["class"] = " ".join(SELECT_CLASSES)
15
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 %}
@@ -33,11 +33,46 @@
33
33
  {% endblock %}
34
34
 
35
35
  {% block content %}
36
- <form action="" method="POST">
36
+ <form action="{{ export_url }}" method="POST">
37
37
  {% csrf_token %}
38
38
 
39
- <fieldset class="border border-gray-200 mb-8 rounded-md pt-3 px-3 shadow-sm dark:border-gray-800">
40
- {% include "unfold/helpers/field.html" with field=form.format %}
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 %}
41
76
  </fieldset>
42
77
 
43
78
  <button type="submit" class="bg-primary-600 border border-transparent font-medium px-3 py-2 rounded-md text-sm text-white">
@@ -4,30 +4,19 @@
4
4
  <form action="" method="post" enctype="multipart/form-data">
5
5
  {% csrf_token %}
6
6
 
7
- <p 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">
8
- {% trans "This importer will import the following fields: " %}
9
-
10
- {% if fields_list|length <= 1 %}
11
- <span class="font-medium">
12
- {{ fields_list.0.1|join:", " }}
13
- </code>
14
- {% else %}
15
- <dl>
16
- {% for resource, fields in fields_list %}
17
- <dt>{{ resource }}</dt>
18
- <dd><code>{{ fields|join:", " }}</code></dd>
19
- {% endfor %}
20
- </dl>
21
- {% endif %}
22
- </p>
7
+ {% include "admin/import_export/resource_fields_list.html" with import_or_export="import" %}
23
8
 
24
9
  <fieldset class="border border-gray-200 mb-8 rounded-md pt-3 px-3 shadow-sm dark:border-gray-800">
25
- {% include "unfold/helpers/field.html" with field=form.resource %}
26
-
27
- {% 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 %}
28
18
  </fieldset>
29
19
 
30
-
31
20
  <button type="submit" class="bg-primary-600 border border-transparent font-medium px-3 py-2 rounded-md text-sm text-white">
32
21
  {% translate 'Submit' %}
33
22
  </button>
@@ -0,0 +1,24 @@
1
+ {% load i18n %}
2
+
3
+ {% block fields_help %}
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
+ {% if import_or_export == "export" %}
6
+ {% trans "This exporter will export the following fields: " %}
7
+ {% elif import_or_export == "import" %}
8
+ {% trans "This importer will import the following fields: " %}
9
+ {% endif %}
10
+
11
+ {% if fields_list|length <= 1 %}
12
+ <code class="font-medium">
13
+ {{ fields_list.0.1|join:", " }}
14
+ </code>
15
+ {% else %}
16
+ <dl>
17
+ {% for resource, fields in fields_list %}
18
+ <dt>{{ resource }}</dt>
19
+ <dd><code>{{ fields|join:", " }}</code></dd>
20
+ {% endfor %}
21
+ </dl>
22
+ {% endif %}
23
+ </div>
24
+ {% endblock %}
File without changes