django-unfold 0.30.0__tar.gz → 0.32.0__tar.gz
Sign up to get free protection for your applications and to get access to all the features.
- {django_unfold-0.30.0 → django_unfold-0.32.0}/PKG-INFO +101 -31
- {django_unfold-0.30.0 → django_unfold-0.32.0}/README.md +100 -30
- {django_unfold-0.30.0 → django_unfold-0.32.0}/pyproject.toml +1 -1
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/admin.py +30 -11
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/contrib/filters/templates/unfold/filters/filters_numeric_slider.html +3 -3
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/contrib/forms/templates/unfold/forms/array.html +3 -1
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/contrib/forms/templates/unfold/forms/helpers/toolbar.html +6 -6
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/contrib/forms/templates/unfold/forms/wysiwyg.html +1 -1
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/contrib/forms/widgets.py +22 -11
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/contrib/guardian/templates/unfold/guardian/group_form.html +4 -4
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/contrib/guardian/templates/unfold/guardian/user_form.html +4 -4
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/contrib/import_export/templates/admin/import_export/change_form.html +1 -1
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/contrib/import_export/templates/admin/import_export/import_errors.html +1 -1
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/contrib/import_export/templates/admin/import_export/import_preview.html +3 -3
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/contrib/import_export/templates/admin/import_export/import_validation.html +4 -4
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/contrib/inlines/forms.py +1 -2
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/contrib/simple_history/templates/simple_history/object_history_list.html +9 -9
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/contrib/simple_history/templates/simple_history/submit_line.html +1 -1
- django_unfold-0.32.0/src/unfold/dataclasses.py +22 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/fields.py +1 -1
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/settings.py +1 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/sites.py +39 -15
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/static/unfold/css/styles.css +1 -1
- django_unfold-0.32.0/src/unfold/static/unfold/js/alpine.anchor.js +1 -0
- django_unfold-0.32.0/src/unfold/static/unfold/js/alpine.js +5 -0
- django_unfold-0.32.0/src/unfold/static/unfold/js/alpine.persist.js +1 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/static/unfold/js/app.js +26 -3
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/styles.css +10 -10
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/templates/admin/actions.html +1 -1
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/templates/admin/app_list.html +1 -1
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/templates/admin/base.html +4 -4
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/templates/admin/change_list.html +2 -2
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/templates/admin/change_list_results.html +2 -2
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/templates/admin/delete_confirmation.html +4 -4
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/templates/admin/delete_selected_confirmation.html +4 -4
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/templates/admin/edit_inline/stacked.html +2 -2
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/templates/admin/edit_inline/tabular.html +3 -3
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/templates/admin/filter.html +2 -2
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/templates/admin/includes/fieldset.html +1 -1
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/templates/admin/includes/object_delete_summary.html +1 -1
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/templates/admin/login.html +8 -8
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/templates/admin/object_history.html +4 -4
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/templates/admin/search_form.html +1 -1
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/templates/admin/submit_line.html +7 -5
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/templates/auth/widgets/read_only_password_hash.html +1 -1
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/templates/registration/logged_out.html +1 -1
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/templates/unfold/change_list_filter.html +9 -1
- django_unfold-0.32.0/src/unfold/templates/unfold/components/card.html +27 -0
- django_unfold-0.32.0/src/unfold/templates/unfold/components/icon.html +1 -0
- django_unfold-0.32.0/src/unfold/templates/unfold/components/separator.html +1 -0
- django_unfold-0.32.0/src/unfold/templates/unfold/components/table.html +31 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/templates/unfold/helpers/account_links.html +2 -2
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/templates/unfold/helpers/actions_row.html +4 -4
- django_unfold-0.32.0/src/unfold/templates/unfold/helpers/app_list.html +99 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/templates/unfold/helpers/app_list_default.html +4 -4
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/templates/unfold/helpers/breadcrumb_item.html +1 -1
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/templates/unfold/helpers/field_readonly_value.html +1 -1
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/templates/unfold/helpers/fieldset_row.html +6 -6
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/templates/unfold/helpers/fieldsets_tabs.html +2 -2
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/templates/unfold/helpers/header.html +1 -1
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/templates/unfold/helpers/help_text.html +1 -1
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/templates/unfold/helpers/history.html +1 -1
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/templates/unfold/helpers/label.html +2 -3
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/templates/unfold/helpers/search.html +7 -4
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/templates/unfold/helpers/search_results.html +2 -2
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/templates/unfold/helpers/tab_action.html +1 -1
- django_unfold-0.32.0/src/unfold/templates/unfold/helpers/tab_list.html +62 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/templates/unfold/helpers/theme_switch.html +2 -2
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/templates/unfold/layouts/skeleton.html +6 -1
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/templates/unfold/widgets/clearable_file_input.html +14 -6
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/templates/unfold/widgets/clearable_file_input_small.html +4 -4
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/templates/unfold/widgets/split_datetime.html +2 -2
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/templatetags/unfold.py +33 -12
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/templatetags/unfold_list.py +16 -6
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/widgets.py +2 -2
- django_unfold-0.30.0/src/unfold/dataclasses.py +0 -13
- django_unfold-0.30.0/src/unfold/static/unfold/js/alpine.js +0 -5
- django_unfold-0.30.0/src/unfold/static/unfold/js/alpine.persist.js +0 -1
- django_unfold-0.30.0/src/unfold/templates/unfold/components/card.html +0 -23
- django_unfold-0.30.0/src/unfold/templates/unfold/components/separator.html +0 -1
- django_unfold-0.30.0/src/unfold/templates/unfold/helpers/app_list.html +0 -89
- django_unfold-0.30.0/src/unfold/templates/unfold/helpers/tab_list.html +0 -40
- {django_unfold-0.30.0 → django_unfold-0.32.0}/LICENSE.md +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/__init__.py +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/apps.py +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/checks.py +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/contrib/__init__.py +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/contrib/filters/__init__.py +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/contrib/filters/admin.py +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/contrib/filters/apps.py +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/contrib/filters/forms.py +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/contrib/filters/static/unfold/filters/css/nouislider.min.css +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/contrib/filters/static/unfold/filters/js/DateTimeShortcuts.js +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/contrib/filters/static/unfold/filters/js/admin-numeric-filter.js +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/contrib/filters/static/unfold/filters/js/nouislider.min.js +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/contrib/filters/static/unfold/filters/js/wNumb.min.js +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/contrib/filters/templates/unfold/filters/filters_date_range.html +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/contrib/filters/templates/unfold/filters/filters_datetime_range.html +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/contrib/filters/templates/unfold/filters/filters_field.html +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/contrib/filters/templates/unfold/filters/filters_numeric_range.html +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/contrib/filters/templates/unfold/filters/filters_numeric_single.html +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/contrib/forms/__init__.py +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/contrib/forms/apps.py +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/contrib/forms/static/unfold/forms/css/trix.css +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/contrib/forms/static/unfold/forms/js/trix.config.js +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/contrib/forms/static/unfold/forms/js/trix.js +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/contrib/guardian/__init__.py +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/contrib/guardian/apps.py +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/contrib/guardian/templates/admin/guardian/model/change_form.html +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/contrib/guardian/templates/admin/guardian/model/field.html +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/contrib/guardian/templates/admin/guardian/model/obj_perms_manage.html +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/contrib/guardian/templates/admin/guardian/model/obj_perms_manage_group.html +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/contrib/guardian/templates/admin/guardian/model/obj_perms_manage_user.html +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/contrib/import_export/__init__.py +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/contrib/import_export/apps.py +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/contrib/import_export/forms.py +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/contrib/import_export/templates/admin/import_export/base.html +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/contrib/import_export/templates/admin/import_export/change_list_export.html +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/contrib/import_export/templates/admin/import_export/change_list_export_item.html +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/contrib/import_export/templates/admin/import_export/change_list_import_export.html +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/contrib/import_export/templates/admin/import_export/change_list_import_item.html +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/contrib/import_export/templates/admin/import_export/export.html +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/contrib/import_export/templates/admin/import_export/import.html +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/contrib/import_export/templates/admin/import_export/import_confirm.html +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/contrib/import_export/templates/admin/import_export/import_form.html +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/contrib/import_export/templates/admin/import_export/resource_fields_list.html +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/contrib/inlines/__init__.py +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/contrib/inlines/admin.py +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/contrib/inlines/apps.py +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/contrib/inlines/checks.py +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/contrib/simple_history/__init__.py +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/contrib/simple_history/apps.py +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/contrib/simple_history/templates/simple_history/object_history.html +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/contrib/simple_history/templates/simple_history/object_history_form.html +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/decorators.py +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/exceptions.py +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/forms.py +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/static/unfold/css/simplebar.css +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/static/unfold/fonts/inter/Inter-Bold.woff2 +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/static/unfold/fonts/inter/Inter-Medium.woff2 +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/static/unfold/fonts/inter/Inter-Regular.woff2 +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/static/unfold/fonts/inter/Inter-SemiBold.woff2 +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/static/unfold/fonts/inter/styles.css +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/static/unfold/fonts/material-symbols/Material-Symbols-Outlined.woff2 +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/static/unfold/fonts/material-symbols/styles.css +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/static/unfold/js/chart.js +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/static/unfold/js/htmx.js +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/static/unfold/js/simplebar.js +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/templates/admin/app_index.html +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/templates/admin/auth/user/add_form.html +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/templates/admin/auth/user/change_password.html +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/templates/admin/base_site.html +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/templates/admin/change_form.html +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/templates/admin/change_form_object_tools.html +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/templates/admin/change_list_object_tools.html +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/templates/admin/date_hierarchy.html +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/templates/admin/index.html +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/templates/admin/nav_sidebar.html +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/templates/admin/pagination.html +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/templates/registration/password_change_done.html +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/templates/registration/password_change_form.html +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/templates/unfold/components/button.html +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/templates/unfold/components/chart/bar.html +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/templates/unfold/components/chart/line.html +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/templates/unfold/components/container.html +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/templates/unfold/components/flex.html +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/templates/unfold/components/navigation.html +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/templates/unfold/components/progress.html +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/templates/unfold/components/text.html +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/templates/unfold/components/title.html +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/templates/unfold/helpers/add_link.html +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/templates/unfold/helpers/attrs.html +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/templates/unfold/helpers/boolean.html +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/templates/unfold/helpers/display_header.html +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/templates/unfold/helpers/display_label.html +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/templates/unfold/helpers/field.html +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/templates/unfold/helpers/field_readonly.html +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/templates/unfold/helpers/form_errors.html +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/templates/unfold/helpers/form_label.html +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/templates/unfold/helpers/messages/error.html +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/templates/unfold/helpers/messages/errornote.html +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/templates/unfold/helpers/messages/info.html +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/templates/unfold/helpers/messages.html +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/templates/unfold/helpers/navigation.html +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/templates/unfold/helpers/pagination_current_item.html +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/templates/unfold/helpers/pagination_ellipsis.html +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/templates/unfold/helpers/site_icon.html +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/templates/unfold/helpers/site_logo.html +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/templates/unfold/helpers/submit.html +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/templates/unfold/helpers/userlinks.html +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/templates/unfold/helpers/welcomemsg.html +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/templates/unfold/layouts/base.html +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/templates/unfold/layouts/base_simple.html +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/templates/unfold/widgets/date.html +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/templates/unfold/widgets/foreign_key_raw_id.html +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/templates/unfold/widgets/radio.html +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/templates/unfold/widgets/radio_option.html +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/templates/unfold/widgets/range.html +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/templates/unfold/widgets/related_widget_wrapper.html +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/templates/unfold/widgets/split_datetime_vertical.html +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/templates/unfold/widgets/split_money.html +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/templates/unfold/widgets/textarea.html +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/templates/unfold/widgets/textarea_expandable.html +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/templates/unfold/widgets/time.html +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/templatetags/__init__.py +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/typing.py +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.0}/src/unfold/utils.py +0 -0
- {django_unfold-0.30.0 → django_unfold-0.32.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.
|
3
|
+
Version: 0.32.0
|
4
4
|
Summary: Modern Django admin theme for seamless interface development
|
5
5
|
Home-page: https://unfoldadmin.com
|
6
6
|
License: MIT
|
@@ -33,7 +33,7 @@ Description-Content-Type: text/markdown
|
|
33
33
|

|
34
34
|

|
35
35
|
|
36
|
-
Unfold is theme for Django admin incorporating most common
|
36
|
+
Unfold is a theme for Django admin incorporating most common practices for building full-fledged admin areas. It is designed to work on top of default administration provided by Django.
|
37
37
|
|
38
38
|
- **Unfold:** demo site is available at [unfoldadmin.com](https://unfoldadmin.com?utm_medium=github&utm_source=unfold)
|
39
39
|
- **Formula:** repository with demo implementation at [github.com/unfoldadmin/formula](https://github.com/unfoldadmin/formula)
|
@@ -45,7 +45,7 @@ Did you decide to start using Unfold but you don't have time to make the switch
|
|
45
45
|
|
46
46
|
## Features <!-- omit from toc -->
|
47
47
|
|
48
|
-
- **Visual**: provides new user interface based on Tailwind CSS framework
|
48
|
+
- **Visual**: provides a new user interface based on Tailwind CSS framework
|
49
49
|
- **Sidebar:** simplifies definition of custom sidebar navigation with icons
|
50
50
|
- **Dark mode:** supports both light and dark mode versions
|
51
51
|
- **Configuration:** most of the basic options can be changed in settings.py
|
@@ -55,14 +55,16 @@ Did you decide to start using Unfold but you don't have time to make the switch
|
|
55
55
|
- **Array widget:** built-in widget for `django.contrib.postgres.fields.ArrayField`
|
56
56
|
- **Filters:** custom dropdown, numeric, datetime, and text fields
|
57
57
|
- **Dashboard:** custom components for rapid dashboard development
|
58
|
+
- **Inline tabs:** group inlines into tab navigation in the change form
|
58
59
|
- **Model tabs:** define custom tab navigations for models
|
59
|
-
- **Fieldset tabs:** merge several
|
60
|
-
- **Colors:** possibility to override default color scheme
|
61
|
-
- **Changeform modes:** display fields in
|
60
|
+
- **Fieldset tabs:** merge several fieldsets into tabs in the change form
|
61
|
+
- **Colors:** possibility to override the default color scheme
|
62
|
+
- **Changeform modes:** display fields in the change form in compressed mode
|
62
63
|
- **Third party packages:** default support for multiple popular applications
|
63
64
|
- **Environment label**: distinguish between environments by displaying a label
|
64
65
|
- **Nonrelated inlines**: displays nonrelated model as inline in changeform
|
65
66
|
- **Parallel admin**: support for default admin in parallel with Unfold. [Admin migration guide](https://unfoldadmin.com/blog/migrating-django-admin-unfold/?utm_medium=github&utm_source=unfold)
|
67
|
+
- **Favicons**: built-in support for configuring various site favicons
|
66
68
|
- **VS Code**: project configuration and development container is included
|
67
69
|
|
68
70
|
## Table of contents <!-- omit from toc -->
|
@@ -100,6 +102,7 @@ Did you decide to start using Unfold but you don't have time to make the switch
|
|
100
102
|
- [Overriding template](#overriding-template)
|
101
103
|
- [Custom variables](#custom-variables)
|
102
104
|
- [Unfold components](#unfold-components)
|
105
|
+
- [Table component example](#table-component-example)
|
103
106
|
- [Unfold development](#unfold-development)
|
104
107
|
- [Pre-commit](#pre-commit)
|
105
108
|
- [Poetry configuration](#poetry-configuration)
|
@@ -111,7 +114,7 @@ Did you decide to start using Unfold but you don't have time to make the switch
|
|
111
114
|
|
112
115
|
## Installation
|
113
116
|
|
114
|
-
The installation process is minimal. Everything
|
117
|
+
The installation process is minimal. Everything that is needed after installation is to put new application at the beginning of **INSTALLED_APPS**. The default admin configuration in urls.py can stay as it is, and no changes are required.
|
115
118
|
|
116
119
|
```python
|
117
120
|
# settings.py
|
@@ -170,17 +173,24 @@ class CustomAdminClass(ModelAdmin):
|
|
170
173
|
|
171
174
|
from django.contrib import admin
|
172
175
|
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
|
176
|
+
from django.contrib.auth.admin import GroupAdmin as BaseGroupAdmin
|
173
177
|
from django.contrib.auth.models import User
|
174
178
|
|
175
179
|
from unfold.admin import ModelAdmin
|
176
180
|
|
177
181
|
|
178
182
|
admin.site.unregister(User)
|
183
|
+
admin.site.unregister(Group)
|
179
184
|
|
180
185
|
|
181
186
|
@admin.register(User)
|
182
187
|
class UserAdmin(BaseUserAdmin, ModelAdmin):
|
183
188
|
pass
|
189
|
+
|
190
|
+
|
191
|
+
@admin.register(Group)
|
192
|
+
class GroupAdmin(BaseGroupAdmin, ModelAdmin):
|
193
|
+
pass
|
184
194
|
```
|
185
195
|
|
186
196
|
## Configuration
|
@@ -209,6 +219,14 @@ UNFOLD = {
|
|
209
219
|
"dark": lambda request: static("logo-dark.svg"), # dark mode
|
210
220
|
},
|
211
221
|
"SITE_SYMBOL": "speed", # symbol from icon set
|
222
|
+
"SITE_FAVICONS": [
|
223
|
+
{
|
224
|
+
"rel": "icon",
|
225
|
+
"sizes": "32x32",
|
226
|
+
"type": "image/svg+xml",
|
227
|
+
"href": lambda request: static("favicon.svg"),
|
228
|
+
},
|
229
|
+
],
|
212
230
|
"SHOW_HISTORY": True, # show/hide "History" button, default: True
|
213
231
|
"SHOW_VIEW_ON_SITE": True, # show/hide "View on site" button, default: True
|
214
232
|
"ENVIRONMENT": "sample_app.environment_callback",
|
@@ -255,6 +273,7 @@ UNFOLD = {
|
|
255
273
|
{
|
256
274
|
"title": _("Navigation"),
|
257
275
|
"separator": True, # Top border
|
276
|
+
"collapsible": True, # Collapsible group of links
|
258
277
|
"items": [
|
259
278
|
{
|
260
279
|
"title": _("Dashboard"),
|
@@ -345,6 +364,9 @@ class CustomAdminClass(ModelAdmin):
|
|
345
364
|
# Display submit button in filters
|
346
365
|
list_filter_submit = False
|
347
366
|
|
367
|
+
# Display changelist in fullwidth
|
368
|
+
list_fullwidth = False
|
369
|
+
|
348
370
|
# Position horizontal scrollbar in changelist at the top
|
349
371
|
list_horizontal_scrollbar_top = False
|
350
372
|
|
@@ -441,7 +463,7 @@ class UserAdmin(ModelAdmin):
|
|
441
463
|
actions_detail = ["change_detail_action_block"]
|
442
464
|
actions_submit_line = ["submit_line_action_activate"]
|
443
465
|
|
444
|
-
@action(description=_("Save & Activate"))
|
466
|
+
@action(description=_("Save & Activate"), permissions=["submit_line_action_activate"])
|
445
467
|
def submit_line_action_activate(self, request: HttpRequest, obj: User):
|
446
468
|
"""
|
447
469
|
If instance is modified in any way, it also needs to be saved,
|
@@ -453,6 +475,9 @@ class UserAdmin(ModelAdmin):
|
|
453
475
|
obj.is_active = True
|
454
476
|
obj.save()
|
455
477
|
|
478
|
+
def has_submit_line_action_activate_permission(self, request: HttpRequest, object_id: Union[str, int]):
|
479
|
+
pass
|
480
|
+
|
456
481
|
@action(description=_("Import"), url_path="import")
|
457
482
|
def changelist_global_action_import(self, request: HttpRequest):
|
458
483
|
"""
|
@@ -477,7 +502,7 @@ class UserAdmin(ModelAdmin):
|
|
477
502
|
"""
|
478
503
|
return redirect(f"https://example.com/{object_id}")
|
479
504
|
|
480
|
-
@action(description=_("Detail"), url_path="detail-action", attrs={"target": "_blank"})
|
505
|
+
@action(description=_("Detail"), url_path="detail-action", attrs={"target": "_blank"}, permissions=["change_detail_action_block"])
|
481
506
|
def change_detail_action_block(self, request: HttpRequest, object_id: int):
|
482
507
|
"""
|
483
508
|
Handler for detail action.
|
@@ -492,6 +517,10 @@ class UserAdmin(ModelAdmin):
|
|
492
517
|
return redirect(
|
493
518
|
reverse_lazy("admin:users_user_change", args=(object_id,))
|
494
519
|
)
|
520
|
+
|
521
|
+
|
522
|
+
def has_change_detail_action_block_permission(self, request: HttpRequest, object_id: Union[str, int]):
|
523
|
+
pass
|
495
524
|
```
|
496
525
|
|
497
526
|
### Action with form example
|
@@ -563,7 +592,7 @@ Text input field which allows filtering by the free string submitted by the user
|
|
563
592
|
|
564
593
|
`FieldTextFilter` requires just a model field name and the filter will make `__icontains` search on this field. There are no other things to configure so the integration in `list_filter` will be just one new row looking like `("model_field_name", FieldTextFilter)`.
|
565
594
|
|
566
|
-
In the case of the `TextFilter`, it is needed
|
595
|
+
In the case of the `TextFilter`, it is needed to write a whole new class inheriting from `TextFilter` with a custom implementation of the `queryset` method and the `parameter_name` attribute. This attribute will be a representation of the search query parameter name in URI. The benefit of the `TextFilter` is the possibility of writing complex queries.
|
567
596
|
|
568
597
|
```python
|
569
598
|
from django.contrib import admin
|
@@ -598,7 +627,7 @@ class MyAdmin(ModelAdmin):
|
|
598
627
|
|
599
628
|
Dropdown filters will display a select field with a list of options. Unfold contains two types of dropdowns: `ChoicesDropdownFilter` and `RelatedDropdownFilter`.
|
600
629
|
|
601
|
-
The difference between them is that `ChoicesDropdownFilter` will collect a list of options based on the `choices` attribute of the model field so most commonly it will be used in combination with `CharField` with specified `choices`. On the other
|
630
|
+
The difference between them is that `ChoicesDropdownFilter` will collect a list of options based on the `choices` attribute of the model field so most commonly it will be used in combination with `CharField` with specified `choices`. On the other hand, `RelatedDropdownFilter` needs a one-to-many or many-to-many foreign key to display options.
|
602
631
|
|
603
632
|
**Note:** At the moment Unfold does not implement a dropdown with an autocomplete functionality, so it is important not to use dropdowns displaying large datasets.
|
604
633
|
|
@@ -907,6 +936,19 @@ class MyModelAdmin(ModelAdmin):
|
|
907
936
|
)
|
908
937
|
```
|
909
938
|
|
939
|
+
Inlines can be grouped into tab navigation by specifying `tab` attribute in the inline class.
|
940
|
+
|
941
|
+
```python
|
942
|
+
# admin.py
|
943
|
+
|
944
|
+
from unfold.admin import TabularInline
|
945
|
+
|
946
|
+
|
947
|
+
class MyInline(TabularInline):
|
948
|
+
model = User
|
949
|
+
tab = True
|
950
|
+
```
|
951
|
+
|
910
952
|
## Third party packages
|
911
953
|
|
912
954
|
### django-celery-beat
|
@@ -976,11 +1018,11 @@ class ClockedScheduleAdmin(BaseClockedScheduleAdmin, ModelAdmin):
|
|
976
1018
|
|
977
1019
|
### django-guardian
|
978
1020
|
|
979
|
-
Adding support for django-guardian is
|
1021
|
+
Adding support for django-guardian is quite straightforward in Unfold, just add `unfold.contrib.guardian` to `INSTALLED_APPS` at the beginning of the file. This action will override all templates coming from the django-guardian. Please note that **Object permissions** link is available in top right dropdown navigation.
|
980
1022
|
|
981
1023
|
### django-import-export
|
982
1024
|
|
983
|
-
1. Add `unfold.contrib.import_export` to `INSTALLED_APPS` at the
|
1025
|
+
1. Add `unfold.contrib.import_export` to `INSTALLED_APPS` at the beginning of the file. This action will override all templates coming from the application.
|
984
1026
|
2. Change `import_form_class` and `export_form_class` in ModelAdmin which is inheriting from `ImportExportModelAdmin`. This chunk of code is responsible for adding proper styling to form elements.
|
985
1027
|
|
986
1028
|
```python
|
@@ -1052,7 +1094,7 @@ This application is supported in Unfold by default. It is not needed to add any
|
|
1052
1094
|
|
1053
1095
|
### django-simple-history
|
1054
1096
|
|
1055
|
-
To make this application work, add `unfold.contrib.simple_history` into `settings.py` in `INSTALLED_APPS` variable before right after `unfold`. This app should ensure that templates coming from django-simple-history are
|
1097
|
+
To make this application work, add `unfold.contrib.simple_history` into `settings.py` in `INSTALLED_APPS` variable before right after `unfold`. This app should ensure that templates coming from django-simple-history are overridden by Unfold.
|
1056
1098
|
|
1057
1099
|
## User Admin Form
|
1058
1100
|
|
@@ -1133,7 +1175,7 @@ npx tailwindcss -o your_project/static/css/styles.css --watch --minify
|
|
1133
1175
|
|
1134
1176
|
### Overriding template
|
1135
1177
|
|
1136
|
-
Create `templates/admin/index.html` in your project and paste the base template below into it. By default, all your custom styles here are not compiled because CSS classes are located in your specific project. Here it is needed to set up the Tailwind for your project and all
|
1178
|
+
Create `templates/admin/index.html` in your project and paste the base template below into it. By default, all your custom styles here are not compiled because CSS classes are located in your specific project. Here it is needed to set up the Tailwind for your project and all required instructions are located in [Project Level Tailwind Stylesheet](#project-level-tailwind-stylesheet) chapter.
|
1137
1179
|
|
1138
1180
|
```html+django
|
1139
1181
|
{% extends 'unfold/layouts/base_simple.html' %}
|
@@ -1237,25 +1279,53 @@ Below you can find a more complex example which is using multiple components and
|
|
1237
1279
|
|
1238
1280
|
#### List of available components <!-- omit from toc -->
|
1239
1281
|
|
1240
|
-
| Component | Description | Arguments
|
1241
|
-
| --------------------------------- | ------------------------------ |
|
1242
|
-
| unfold/components/
|
1243
|
-
| unfold/components/
|
1244
|
-
| unfold/components/
|
1245
|
-
| unfold/components/
|
1246
|
-
| unfold/components/
|
1247
|
-
| unfold/components/
|
1248
|
-
| unfold/components/
|
1249
|
-
| unfold/components/
|
1250
|
-
| unfold/components/
|
1251
|
-
| unfold/components/
|
1252
|
-
| unfold/components/
|
1282
|
+
| Component | Description | Arguments |
|
1283
|
+
| --------------------------------- | ------------------------------ | ------------------------------------ |
|
1284
|
+
| unfold/components/button.html | Basic button element | submit |
|
1285
|
+
| unfold/components/card.html | Card component | class, title, footer, label, icon |
|
1286
|
+
| unfold/components/chart/bar.html | Bar chart implementation | class, data, height, width |
|
1287
|
+
| unfold/components/chart/line.html | Line chart implementation | class, data, height, width |
|
1288
|
+
| unfold/components/container.html | Wrapper for settings max width | class |
|
1289
|
+
| unfold/components/flex.html | Flex items | class, col |
|
1290
|
+
| unfold/components/icon.html | Icon element | class |
|
1291
|
+
| unfold/components/navigation.html | List of navigation links | class, items |
|
1292
|
+
| unfold/components/progress.html | Percentual progress bar | class, value, title, description |
|
1293
|
+
| unfold/components/separator.html | Separator, horizontal rule | class |
|
1294
|
+
| unfold/components/table.html | Table | table, card_included, striped |
|
1295
|
+
| unfold/components/text.html | Paragraph of text | class |
|
1296
|
+
| unfold/components/title.html | Basic heading element | class |
|
1297
|
+
|
1298
|
+
|
1299
|
+
#### Table component example
|
1300
|
+
|
1301
|
+
```python
|
1302
|
+
from typing import Dict
|
1303
|
+
from django.http import HttpRequest
|
1304
|
+
|
1305
|
+
|
1306
|
+
def dashboard_callback(request: HttpRequest) -> Dict:
|
1307
|
+
return {
|
1308
|
+
"table_data": {
|
1309
|
+
"headers": ["col 1", "col 2"],
|
1310
|
+
"rows": [
|
1311
|
+
["a", "b"],
|
1312
|
+
["c", "d"],
|
1313
|
+
]
|
1314
|
+
}
|
1315
|
+
}
|
1316
|
+
```
|
1317
|
+
|
1318
|
+
```django-html
|
1319
|
+
{% component "unfold/components/card" with title="Card title" %}
|
1320
|
+
{% component "unfold/components/table.html" with table=table_data card_included=1 striped=1 %}{% encomponent %}
|
1321
|
+
{% endcomponent %}
|
1322
|
+
```
|
1253
1323
|
|
1254
1324
|
## Unfold development
|
1255
1325
|
|
1256
1326
|
### Pre-commit
|
1257
1327
|
|
1258
|
-
Before adding any source code, it is recommended to have pre-commit installed on your local computer to check for all potential issues when
|
1328
|
+
Before adding any source code, it is recommended to have pre-commit installed on your local computer to check for all potential issues when committing the code.
|
1259
1329
|
|
1260
1330
|
```bash
|
1261
1331
|
pip install pre-commit
|
@@ -1275,7 +1345,7 @@ To add a new feature or fix the easiest approach is to use django-unfold in comb
|
|
1275
1345
|
|
1276
1346
|
### Compiling Tailwind
|
1277
1347
|
|
1278
|
-
At the moment project contains package.json with all dependencies required to compile new CSS file. Tailwind configuration file is set to check all html, js and py files for Tailwind's
|
1348
|
+
At the moment project contains package.json with all dependencies required to compile new CSS file. Tailwind configuration file is set to check all html, js and py files for Tailwind's classes occurrences.
|
1279
1349
|
|
1280
1350
|
```bash
|
1281
1351
|
npm install
|
@@ -1285,7 +1355,7 @@ npm run tailwind:watch # run after each change in code
|
|
1285
1355
|
npm run tailwind:build # run once
|
1286
1356
|
```
|
1287
1357
|
|
1288
|
-
Some components like datepickers, calendars or selectors in admin was not possible to style by overriding html templates so their default styles are
|
1358
|
+
Some components like datepickers, calendars or selectors in admin was not possible to style by overriding html templates so their default styles are overridden in **styles.css**.
|
1289
1359
|
|
1290
1360
|
**Note:** most of the custom styles located in style.css are created via `@apply some-tailwind-class;` as is not possible to manually add CSS class to element which are for example created via jQuery.
|
1291
1361
|
|
@@ -9,7 +9,7 @@
|
|
9
9
|

|
10
10
|

|
11
11
|
|
12
|
-
Unfold is theme for Django admin incorporating most common
|
12
|
+
Unfold is a theme for Django admin incorporating most common practices for building full-fledged admin areas. It is designed to work on top of default administration provided by Django.
|
13
13
|
|
14
14
|
- **Unfold:** demo site is available at [unfoldadmin.com](https://unfoldadmin.com?utm_medium=github&utm_source=unfold)
|
15
15
|
- **Formula:** repository with demo implementation at [github.com/unfoldadmin/formula](https://github.com/unfoldadmin/formula)
|
@@ -21,7 +21,7 @@ Did you decide to start using Unfold but you don't have time to make the switch
|
|
21
21
|
|
22
22
|
## Features <!-- omit from toc -->
|
23
23
|
|
24
|
-
- **Visual**: provides new user interface based on Tailwind CSS framework
|
24
|
+
- **Visual**: provides a new user interface based on Tailwind CSS framework
|
25
25
|
- **Sidebar:** simplifies definition of custom sidebar navigation with icons
|
26
26
|
- **Dark mode:** supports both light and dark mode versions
|
27
27
|
- **Configuration:** most of the basic options can be changed in settings.py
|
@@ -31,14 +31,16 @@ Did you decide to start using Unfold but you don't have time to make the switch
|
|
31
31
|
- **Array widget:** built-in widget for `django.contrib.postgres.fields.ArrayField`
|
32
32
|
- **Filters:** custom dropdown, numeric, datetime, and text fields
|
33
33
|
- **Dashboard:** custom components for rapid dashboard development
|
34
|
+
- **Inline tabs:** group inlines into tab navigation in the change form
|
34
35
|
- **Model tabs:** define custom tab navigations for models
|
35
|
-
- **Fieldset tabs:** merge several
|
36
|
-
- **Colors:** possibility to override default color scheme
|
37
|
-
- **Changeform modes:** display fields in
|
36
|
+
- **Fieldset tabs:** merge several fieldsets into tabs in the change form
|
37
|
+
- **Colors:** possibility to override the default color scheme
|
38
|
+
- **Changeform modes:** display fields in the change form in compressed mode
|
38
39
|
- **Third party packages:** default support for multiple popular applications
|
39
40
|
- **Environment label**: distinguish between environments by displaying a label
|
40
41
|
- **Nonrelated inlines**: displays nonrelated model as inline in changeform
|
41
42
|
- **Parallel admin**: support for default admin in parallel with Unfold. [Admin migration guide](https://unfoldadmin.com/blog/migrating-django-admin-unfold/?utm_medium=github&utm_source=unfold)
|
43
|
+
- **Favicons**: built-in support for configuring various site favicons
|
42
44
|
- **VS Code**: project configuration and development container is included
|
43
45
|
|
44
46
|
## Table of contents <!-- omit from toc -->
|
@@ -76,6 +78,7 @@ Did you decide to start using Unfold but you don't have time to make the switch
|
|
76
78
|
- [Overriding template](#overriding-template)
|
77
79
|
- [Custom variables](#custom-variables)
|
78
80
|
- [Unfold components](#unfold-components)
|
81
|
+
- [Table component example](#table-component-example)
|
79
82
|
- [Unfold development](#unfold-development)
|
80
83
|
- [Pre-commit](#pre-commit)
|
81
84
|
- [Poetry configuration](#poetry-configuration)
|
@@ -87,7 +90,7 @@ Did you decide to start using Unfold but you don't have time to make the switch
|
|
87
90
|
|
88
91
|
## Installation
|
89
92
|
|
90
|
-
The installation process is minimal. Everything
|
93
|
+
The installation process is minimal. Everything that is needed after installation is to put new application at the beginning of **INSTALLED_APPS**. The default admin configuration in urls.py can stay as it is, and no changes are required.
|
91
94
|
|
92
95
|
```python
|
93
96
|
# settings.py
|
@@ -146,17 +149,24 @@ class CustomAdminClass(ModelAdmin):
|
|
146
149
|
|
147
150
|
from django.contrib import admin
|
148
151
|
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
|
152
|
+
from django.contrib.auth.admin import GroupAdmin as BaseGroupAdmin
|
149
153
|
from django.contrib.auth.models import User
|
150
154
|
|
151
155
|
from unfold.admin import ModelAdmin
|
152
156
|
|
153
157
|
|
154
158
|
admin.site.unregister(User)
|
159
|
+
admin.site.unregister(Group)
|
155
160
|
|
156
161
|
|
157
162
|
@admin.register(User)
|
158
163
|
class UserAdmin(BaseUserAdmin, ModelAdmin):
|
159
164
|
pass
|
165
|
+
|
166
|
+
|
167
|
+
@admin.register(Group)
|
168
|
+
class GroupAdmin(BaseGroupAdmin, ModelAdmin):
|
169
|
+
pass
|
160
170
|
```
|
161
171
|
|
162
172
|
## Configuration
|
@@ -185,6 +195,14 @@ UNFOLD = {
|
|
185
195
|
"dark": lambda request: static("logo-dark.svg"), # dark mode
|
186
196
|
},
|
187
197
|
"SITE_SYMBOL": "speed", # symbol from icon set
|
198
|
+
"SITE_FAVICONS": [
|
199
|
+
{
|
200
|
+
"rel": "icon",
|
201
|
+
"sizes": "32x32",
|
202
|
+
"type": "image/svg+xml",
|
203
|
+
"href": lambda request: static("favicon.svg"),
|
204
|
+
},
|
205
|
+
],
|
188
206
|
"SHOW_HISTORY": True, # show/hide "History" button, default: True
|
189
207
|
"SHOW_VIEW_ON_SITE": True, # show/hide "View on site" button, default: True
|
190
208
|
"ENVIRONMENT": "sample_app.environment_callback",
|
@@ -231,6 +249,7 @@ UNFOLD = {
|
|
231
249
|
{
|
232
250
|
"title": _("Navigation"),
|
233
251
|
"separator": True, # Top border
|
252
|
+
"collapsible": True, # Collapsible group of links
|
234
253
|
"items": [
|
235
254
|
{
|
236
255
|
"title": _("Dashboard"),
|
@@ -321,6 +340,9 @@ class CustomAdminClass(ModelAdmin):
|
|
321
340
|
# Display submit button in filters
|
322
341
|
list_filter_submit = False
|
323
342
|
|
343
|
+
# Display changelist in fullwidth
|
344
|
+
list_fullwidth = False
|
345
|
+
|
324
346
|
# Position horizontal scrollbar in changelist at the top
|
325
347
|
list_horizontal_scrollbar_top = False
|
326
348
|
|
@@ -417,7 +439,7 @@ class UserAdmin(ModelAdmin):
|
|
417
439
|
actions_detail = ["change_detail_action_block"]
|
418
440
|
actions_submit_line = ["submit_line_action_activate"]
|
419
441
|
|
420
|
-
@action(description=_("Save & Activate"))
|
442
|
+
@action(description=_("Save & Activate"), permissions=["submit_line_action_activate"])
|
421
443
|
def submit_line_action_activate(self, request: HttpRequest, obj: User):
|
422
444
|
"""
|
423
445
|
If instance is modified in any way, it also needs to be saved,
|
@@ -429,6 +451,9 @@ class UserAdmin(ModelAdmin):
|
|
429
451
|
obj.is_active = True
|
430
452
|
obj.save()
|
431
453
|
|
454
|
+
def has_submit_line_action_activate_permission(self, request: HttpRequest, object_id: Union[str, int]):
|
455
|
+
pass
|
456
|
+
|
432
457
|
@action(description=_("Import"), url_path="import")
|
433
458
|
def changelist_global_action_import(self, request: HttpRequest):
|
434
459
|
"""
|
@@ -453,7 +478,7 @@ class UserAdmin(ModelAdmin):
|
|
453
478
|
"""
|
454
479
|
return redirect(f"https://example.com/{object_id}")
|
455
480
|
|
456
|
-
@action(description=_("Detail"), url_path="detail-action", attrs={"target": "_blank"})
|
481
|
+
@action(description=_("Detail"), url_path="detail-action", attrs={"target": "_blank"}, permissions=["change_detail_action_block"])
|
457
482
|
def change_detail_action_block(self, request: HttpRequest, object_id: int):
|
458
483
|
"""
|
459
484
|
Handler for detail action.
|
@@ -468,6 +493,10 @@ class UserAdmin(ModelAdmin):
|
|
468
493
|
return redirect(
|
469
494
|
reverse_lazy("admin:users_user_change", args=(object_id,))
|
470
495
|
)
|
496
|
+
|
497
|
+
|
498
|
+
def has_change_detail_action_block_permission(self, request: HttpRequest, object_id: Union[str, int]):
|
499
|
+
pass
|
471
500
|
```
|
472
501
|
|
473
502
|
### Action with form example
|
@@ -539,7 +568,7 @@ Text input field which allows filtering by the free string submitted by the user
|
|
539
568
|
|
540
569
|
`FieldTextFilter` requires just a model field name and the filter will make `__icontains` search on this field. There are no other things to configure so the integration in `list_filter` will be just one new row looking like `("model_field_name", FieldTextFilter)`.
|
541
570
|
|
542
|
-
In the case of the `TextFilter`, it is needed
|
571
|
+
In the case of the `TextFilter`, it is needed to write a whole new class inheriting from `TextFilter` with a custom implementation of the `queryset` method and the `parameter_name` attribute. This attribute will be a representation of the search query parameter name in URI. The benefit of the `TextFilter` is the possibility of writing complex queries.
|
543
572
|
|
544
573
|
```python
|
545
574
|
from django.contrib import admin
|
@@ -574,7 +603,7 @@ class MyAdmin(ModelAdmin):
|
|
574
603
|
|
575
604
|
Dropdown filters will display a select field with a list of options. Unfold contains two types of dropdowns: `ChoicesDropdownFilter` and `RelatedDropdownFilter`.
|
576
605
|
|
577
|
-
The difference between them is that `ChoicesDropdownFilter` will collect a list of options based on the `choices` attribute of the model field so most commonly it will be used in combination with `CharField` with specified `choices`. On the other
|
606
|
+
The difference between them is that `ChoicesDropdownFilter` will collect a list of options based on the `choices` attribute of the model field so most commonly it will be used in combination with `CharField` with specified `choices`. On the other hand, `RelatedDropdownFilter` needs a one-to-many or many-to-many foreign key to display options.
|
578
607
|
|
579
608
|
**Note:** At the moment Unfold does not implement a dropdown with an autocomplete functionality, so it is important not to use dropdowns displaying large datasets.
|
580
609
|
|
@@ -883,6 +912,19 @@ class MyModelAdmin(ModelAdmin):
|
|
883
912
|
)
|
884
913
|
```
|
885
914
|
|
915
|
+
Inlines can be grouped into tab navigation by specifying `tab` attribute in the inline class.
|
916
|
+
|
917
|
+
```python
|
918
|
+
# admin.py
|
919
|
+
|
920
|
+
from unfold.admin import TabularInline
|
921
|
+
|
922
|
+
|
923
|
+
class MyInline(TabularInline):
|
924
|
+
model = User
|
925
|
+
tab = True
|
926
|
+
```
|
927
|
+
|
886
928
|
## Third party packages
|
887
929
|
|
888
930
|
### django-celery-beat
|
@@ -952,11 +994,11 @@ class ClockedScheduleAdmin(BaseClockedScheduleAdmin, ModelAdmin):
|
|
952
994
|
|
953
995
|
### django-guardian
|
954
996
|
|
955
|
-
Adding support for django-guardian is
|
997
|
+
Adding support for django-guardian is quite straightforward in Unfold, just add `unfold.contrib.guardian` to `INSTALLED_APPS` at the beginning of the file. This action will override all templates coming from the django-guardian. Please note that **Object permissions** link is available in top right dropdown navigation.
|
956
998
|
|
957
999
|
### django-import-export
|
958
1000
|
|
959
|
-
1. Add `unfold.contrib.import_export` to `INSTALLED_APPS` at the
|
1001
|
+
1. Add `unfold.contrib.import_export` to `INSTALLED_APPS` at the beginning of the file. This action will override all templates coming from the application.
|
960
1002
|
2. Change `import_form_class` and `export_form_class` in ModelAdmin which is inheriting from `ImportExportModelAdmin`. This chunk of code is responsible for adding proper styling to form elements.
|
961
1003
|
|
962
1004
|
```python
|
@@ -1028,7 +1070,7 @@ This application is supported in Unfold by default. It is not needed to add any
|
|
1028
1070
|
|
1029
1071
|
### django-simple-history
|
1030
1072
|
|
1031
|
-
To make this application work, add `unfold.contrib.simple_history` into `settings.py` in `INSTALLED_APPS` variable before right after `unfold`. This app should ensure that templates coming from django-simple-history are
|
1073
|
+
To make this application work, add `unfold.contrib.simple_history` into `settings.py` in `INSTALLED_APPS` variable before right after `unfold`. This app should ensure that templates coming from django-simple-history are overridden by Unfold.
|
1032
1074
|
|
1033
1075
|
## User Admin Form
|
1034
1076
|
|
@@ -1109,7 +1151,7 @@ npx tailwindcss -o your_project/static/css/styles.css --watch --minify
|
|
1109
1151
|
|
1110
1152
|
### Overriding template
|
1111
1153
|
|
1112
|
-
Create `templates/admin/index.html` in your project and paste the base template below into it. By default, all your custom styles here are not compiled because CSS classes are located in your specific project. Here it is needed to set up the Tailwind for your project and all
|
1154
|
+
Create `templates/admin/index.html` in your project and paste the base template below into it. By default, all your custom styles here are not compiled because CSS classes are located in your specific project. Here it is needed to set up the Tailwind for your project and all required instructions are located in [Project Level Tailwind Stylesheet](#project-level-tailwind-stylesheet) chapter.
|
1113
1155
|
|
1114
1156
|
```html+django
|
1115
1157
|
{% extends 'unfold/layouts/base_simple.html' %}
|
@@ -1213,25 +1255,53 @@ Below you can find a more complex example which is using multiple components and
|
|
1213
1255
|
|
1214
1256
|
#### List of available components <!-- omit from toc -->
|
1215
1257
|
|
1216
|
-
| Component | Description | Arguments
|
1217
|
-
| --------------------------------- | ------------------------------ |
|
1218
|
-
| unfold/components/
|
1219
|
-
| unfold/components/
|
1220
|
-
| unfold/components/
|
1221
|
-
| unfold/components/
|
1222
|
-
| unfold/components/
|
1223
|
-
| unfold/components/
|
1224
|
-
| unfold/components/
|
1225
|
-
| unfold/components/
|
1226
|
-
| unfold/components/
|
1227
|
-
| unfold/components/
|
1228
|
-
| unfold/components/
|
1258
|
+
| Component | Description | Arguments |
|
1259
|
+
| --------------------------------- | ------------------------------ | ------------------------------------ |
|
1260
|
+
| unfold/components/button.html | Basic button element | submit |
|
1261
|
+
| unfold/components/card.html | Card component | class, title, footer, label, icon |
|
1262
|
+
| unfold/components/chart/bar.html | Bar chart implementation | class, data, height, width |
|
1263
|
+
| unfold/components/chart/line.html | Line chart implementation | class, data, height, width |
|
1264
|
+
| unfold/components/container.html | Wrapper for settings max width | class |
|
1265
|
+
| unfold/components/flex.html | Flex items | class, col |
|
1266
|
+
| unfold/components/icon.html | Icon element | class |
|
1267
|
+
| unfold/components/navigation.html | List of navigation links | class, items |
|
1268
|
+
| unfold/components/progress.html | Percentual progress bar | class, value, title, description |
|
1269
|
+
| unfold/components/separator.html | Separator, horizontal rule | class |
|
1270
|
+
| unfold/components/table.html | Table | table, card_included, striped |
|
1271
|
+
| unfold/components/text.html | Paragraph of text | class |
|
1272
|
+
| unfold/components/title.html | Basic heading element | class |
|
1273
|
+
|
1274
|
+
|
1275
|
+
#### Table component example
|
1276
|
+
|
1277
|
+
```python
|
1278
|
+
from typing import Dict
|
1279
|
+
from django.http import HttpRequest
|
1280
|
+
|
1281
|
+
|
1282
|
+
def dashboard_callback(request: HttpRequest) -> Dict:
|
1283
|
+
return {
|
1284
|
+
"table_data": {
|
1285
|
+
"headers": ["col 1", "col 2"],
|
1286
|
+
"rows": [
|
1287
|
+
["a", "b"],
|
1288
|
+
["c", "d"],
|
1289
|
+
]
|
1290
|
+
}
|
1291
|
+
}
|
1292
|
+
```
|
1293
|
+
|
1294
|
+
```django-html
|
1295
|
+
{% component "unfold/components/card" with title="Card title" %}
|
1296
|
+
{% component "unfold/components/table.html" with table=table_data card_included=1 striped=1 %}{% encomponent %}
|
1297
|
+
{% endcomponent %}
|
1298
|
+
```
|
1229
1299
|
|
1230
1300
|
## Unfold development
|
1231
1301
|
|
1232
1302
|
### Pre-commit
|
1233
1303
|
|
1234
|
-
Before adding any source code, it is recommended to have pre-commit installed on your local computer to check for all potential issues when
|
1304
|
+
Before adding any source code, it is recommended to have pre-commit installed on your local computer to check for all potential issues when committing the code.
|
1235
1305
|
|
1236
1306
|
```bash
|
1237
1307
|
pip install pre-commit
|
@@ -1251,7 +1321,7 @@ To add a new feature or fix the easiest approach is to use django-unfold in comb
|
|
1251
1321
|
|
1252
1322
|
### Compiling Tailwind
|
1253
1323
|
|
1254
|
-
At the moment project contains package.json with all dependencies required to compile new CSS file. Tailwind configuration file is set to check all html, js and py files for Tailwind's
|
1324
|
+
At the moment project contains package.json with all dependencies required to compile new CSS file. Tailwind configuration file is set to check all html, js and py files for Tailwind's classes occurrences.
|
1255
1325
|
|
1256
1326
|
```bash
|
1257
1327
|
npm install
|
@@ -1261,7 +1331,7 @@ npm run tailwind:watch # run after each change in code
|
|
1261
1331
|
npm run tailwind:build # run once
|
1262
1332
|
```
|
1263
1333
|
|
1264
|
-
Some components like datepickers, calendars or selectors in admin was not possible to style by overriding html templates so their default styles are
|
1334
|
+
Some components like datepickers, calendars or selectors in admin was not possible to style by overriding html templates so their default styles are overridden in **styles.css**.
|
1265
1335
|
|
1266
1336
|
**Note:** most of the custom styles located in style.css are created via `@apply some-tailwind-class;` as is not possible to manually add CSS class to element which are for example created via jQuery.
|
1267
1337
|
|