From f61b3d07f9f0cb3e6ca69272bdbd3a81803a99a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Krej=C4=8D=C3=AD?= Date: Thu, 3 Jun 2021 17:22:59 +0200 Subject: [PATCH 1/7] Add PoC tabular.html --- adminlte3_theme/templates/admin/tabular.html | 114 +++++++++++++++++++ 1 file changed, 114 insertions(+) create mode 100644 adminlte3_theme/templates/admin/tabular.html diff --git a/adminlte3_theme/templates/admin/tabular.html b/adminlte3_theme/templates/admin/tabular.html new file mode 100644 index 0000000..e703f50 --- /dev/null +++ b/adminlte3_theme/templates/admin/tabular.html @@ -0,0 +1,114 @@ +{% load i18n admin_urls static admin_modify %} +
+ {{ inline_admin_formset.formset.management_form }} +
+
+ {% if inline_admin_formset.formset.max_num == 1 %} + {{ inline_admin_formset.opts.verbose_name|capfirst }} + {% else %} + {{ inline_admin_formset.opts.verbose_name_plural|capfirst }} + {% endif %} +
+
+ +
+
+
+
+ {{ inline_admin_formset.formset.non_form_errors }} + + + + + {% for field in inline_admin_formset.fields %} + {% if not field.widget.is_hidden %} + + {% endif %} + {% endfor %} + {% if inline_admin_formset.formset.can_delete and inline_admin_formset.has_delete_permission %} + + {% endif %} + + + + {% for inline_admin_form in inline_admin_formset %} + {% if inline_admin_form.form.non_field_errors %} + + + + {% endif %} + + + {% for fieldset in inline_admin_form %} + {% for line in fieldset %} + {% for field in line %} + {% if field.is_readonly or not field.field.is_hidden %} + + {% endif %} + {% endfor %} + {% endfor %} + {% endfor %} + {% if inline_admin_formset.formset.can_delete and inline_admin_formset.has_delete_permission %} + + {% endif %} + + {% endfor %} + +
+ {{ field.label|capfirst }} + {% if field.help_text %} + ({{ field.help_text|striptags }}) + {% endif %} + {% translate "Delete?" %}
{{ inline_admin_form.form.non_field_errors }} +
+ {% if inline_admin_form.original or inline_admin_form.show_url %} +

+ {% if inline_admin_form.original %} + {{ inline_admin_form.original }} + {% if inline_admin_form.model_admin.show_change_link and inline_admin_form.model_admin.has_registered_model %} + + {% if inline_admin_formset.has_change_permission %} + {% translate "Change" %} + {% else %} + {% translate "View" %} + {% endif %} + + {% endif %} + {% endif %} + {% if inline_admin_form.show_url %} + {% translate "View on site" %} + {% endif %} +

+ {% endif %} + {% if inline_admin_form.needs_explicit_pk_field %} + {{ inline_admin_form.pk_field.field }} + {% endif %} + {% if inline_admin_form.fk_field %} + {{ inline_admin_form.fk_field.field }} + {% endif %} + {% spaceless %} + {% for fieldset in inline_admin_form %} + {% for line in fieldset %} + {% for field in line %} + {% if not field.is_readonly and field.field.is_hidden %} + {{ field.field }} + {% endif %} + {% endfor %} + {% endfor %} + {% endfor %} + {% endspaceless %} +
+ {% if field.is_readonly %} +

{{ field.contents }}

+ {% else %} + {{ field.field.errors.as_ul }} + {{ field.field }} + {% endif %} +
+ {% if inline_admin_form.original %} + {{ inline_admin_form.deletion_field.field }} + {% endif %} +
+
+
+
From 06d26da017981be63f94cabfbb46bbb9ff244bcf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Krej=C4=8D=C3=AD?= Date: Thu, 3 Jun 2021 17:30:24 +0200 Subject: [PATCH 2/7] Move tabular.html to correct folder --- adminlte3_theme/templates/admin/{ => edit_inline}/tabular.html | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename adminlte3_theme/templates/admin/{ => edit_inline}/tabular.html (100%) diff --git a/adminlte3_theme/templates/admin/tabular.html b/adminlte3_theme/templates/admin/edit_inline/tabular.html similarity index 100% rename from adminlte3_theme/templates/admin/tabular.html rename to adminlte3_theme/templates/admin/edit_inline/tabular.html From 8700c59ddeb8bb75fee2be0574aee56c4f5dfe6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Krej=C4=8D=C3=AD?= Date: Thu, 3 Jun 2021 19:29:04 +0200 Subject: [PATCH 3/7] Create bootstrap_input template filter This filter adds needed Bootstrap CSS classes to input fields. --- .../templatetags/bootstrap_forms.py | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 adminlte3_theme/templatetags/bootstrap_forms.py diff --git a/adminlte3_theme/templatetags/bootstrap_forms.py b/adminlte3_theme/templatetags/bootstrap_forms.py new file mode 100644 index 0000000..bf9f9d9 --- /dev/null +++ b/adminlte3_theme/templatetags/bootstrap_forms.py @@ -0,0 +1,35 @@ +from django.contrib.admin.widgets import RelatedFieldWidgetWrapper +from django.template import Library +from django.utils.safestring import mark_safe + +register = Library() + + +@register.filter(is_safe=True) +def bootstrap_input(value): + """Adds appropriate bootstrap CSS classes to widgets so that they are rendered bootstrap-ish""" + current_classes = value.field.widget.attrs.get("class", "").strip().split(" ") + field_type = value.field.widget.attrs.get("type", "text") + + if field_type == "range": + bootstrap_class = "form-control-range" + elif field_type == "checkbox" or field_type == "radio": + bootstrap_class = "form-check-input" + elif isinstance(value.field.widget, RelatedFieldWidgetWrapper): + bootstrap_class = "custom-select" # For wrapped widgets (those with edit, add and delete icons) + else: + bootstrap_class = "form-control" + + # We always have a list. This checks if first item contains something (list is not [''], meaning the attribute + # contained something) and then adds the bootstrap_class if it is not already there. If the list is "empty" then we create + # a new one that contains only the bootstrap_class we want. + if current_classes[0] and bootstrap_class not in current_classes: + current_classes.append(bootstrap_class) + else: + current_classes = [bootstrap_class] + + # Also add the is-invalid class to render the field with a red border if there are any errors. + if value.errors: + current_classes.append("is-invalid") + + return value.as_widget(attrs={"class": " ".join(current_classes)}) From f6b064d058b50866b9f3f9d87459f536a863e491 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Krej=C4=8D=C3=AD?= Date: Thu, 3 Jun 2021 19:55:41 +0200 Subject: [PATCH 4/7] Exclude AdminSplitDateTime widget This widget is complicated and controlled by JS, it is not trivial to bootstrapify. Now the decorator will leave it alone and just spit it back unharmed. --- adminlte3_theme/templatetags/bootstrap_forms.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/adminlte3_theme/templatetags/bootstrap_forms.py b/adminlte3_theme/templatetags/bootstrap_forms.py index bf9f9d9..0c9c6f5 100644 --- a/adminlte3_theme/templatetags/bootstrap_forms.py +++ b/adminlte3_theme/templatetags/bootstrap_forms.py @@ -1,4 +1,4 @@ -from django.contrib.admin.widgets import RelatedFieldWidgetWrapper +from django.contrib.admin.widgets import RelatedFieldWidgetWrapper, AdminSplitDateTime from django.template import Library from django.utils.safestring import mark_safe @@ -17,6 +17,8 @@ def bootstrap_input(value): bootstrap_class = "form-check-input" elif isinstance(value.field.widget, RelatedFieldWidgetWrapper): bootstrap_class = "custom-select" # For wrapped widgets (those with edit, add and delete icons) + elif isinstance(value.field.widget, AdminSplitDateTime): + return value # We don't want to style the date time field (for now) else: bootstrap_class = "form-control" From 5a502c7f2ea93f71fba5e5555920e0f90e248ae8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Krej=C4=8D=C3=AD?= Date: Thu, 3 Jun 2021 19:58:44 +0200 Subject: [PATCH 5/7] Apply new template filter to all fields in tabular inline Also to match the style all fields in basic admin form are bootstrapified too. --- .../templates/admin/edit_inline/tabular.html | 188 +++++++++--------- .../templates/admin/includes/fieldset.html | 7 +- .../admin/widgets/related_widget_wrapper.html | 31 +++ 3 files changed, 131 insertions(+), 95 deletions(-) create mode 100644 adminlte3_theme/templates/admin/widgets/related_widget_wrapper.html diff --git a/adminlte3_theme/templates/admin/edit_inline/tabular.html b/adminlte3_theme/templates/admin/edit_inline/tabular.html index e703f50..e81047e 100644 --- a/adminlte3_theme/templates/admin/edit_inline/tabular.html +++ b/adminlte3_theme/templates/admin/edit_inline/tabular.html @@ -1,114 +1,118 @@ -{% load i18n admin_urls static admin_modify %} +{% load i18n admin_urls static admin_modify bootstrap_forms %}
{{ inline_admin_formset.formset.management_form }}
-
+

{% if inline_admin_formset.formset.max_num == 1 %} {{ inline_admin_formset.opts.verbose_name|capfirst }} {% else %} {{ inline_admin_formset.opts.verbose_name_plural|capfirst }} {% endif %} -

+
-
-
- {{ inline_admin_formset.formset.non_form_errors }} - - - - - {% for field in inline_admin_formset.fields %} - {% if not field.widget.is_hidden %} - - {% endif %} - {% endfor %} - {% if inline_admin_formset.formset.can_delete and inline_admin_formset.has_delete_permission %} - - {% endif %} - - - - {% for inline_admin_form in inline_admin_formset %} - {% if inline_admin_form.form.non_field_errors %} - - - - {% endif %} - - + {% endif %} + + {% endfor %} + +
- {{ field.label|capfirst }} - {% if field.help_text %} - ({{ field.help_text|striptags }}) - {% endif %} - {% translate "Delete?" %}
{{ inline_admin_form.form.non_field_errors }} -
- {% if inline_admin_form.original or inline_admin_form.show_url %} -

- {% if inline_admin_form.original %} - {{ inline_admin_form.original }} - {% if inline_admin_form.model_admin.show_change_link and inline_admin_form.model_admin.has_registered_model %} - - {% if inline_admin_formset.has_change_permission %} - {% translate "Change" %} - {% else %} - {% translate "View" %} - {% endif %} - - {% endif %} - {% endif %} - {% if inline_admin_form.show_url %} - {% translate "View on site" %} - {% endif %} -

+
+ {{ inline_admin_formset.formset.non_form_errors }} + + + + + {% for field in inline_admin_formset.fields %} + {% if not field.widget.is_hidden %} + + {% endif %} + {% endfor %} + {% if inline_admin_formset.formset.can_delete and inline_admin_formset.has_delete_permission %} + + {% endif %} + + + + {% for inline_admin_form in inline_admin_formset %} + {% if inline_admin_form.form.non_field_errors %} + + - {% for fieldset in inline_admin_form %} - {% for line in fieldset %} - {% for field in line %} - {% if field.is_readonly or not field.field.is_hidden %} - + {% endif %} + + + {% endif %} + {% endif %} + {% if inline_admin_form.show_url %} + {% translate "View on site" %} + {% endif %} +

+ {% endif %} + {% if inline_admin_form.needs_explicit_pk_field %} + {{ inline_admin_form.pk_field.field }} + {% endif %} + {% if inline_admin_form.fk_field %} + {{ inline_admin_form.fk_field.field }} + {% endif %} + {% spaceless %} + {% for fieldset in inline_admin_form %} + {% for line in fieldset %} + {% for field in line %} + {% if not field.is_readonly and field.field.is_hidden %} + {{ field.field }} + {% endif %} + {% endfor %} {% endfor %} {% endfor %} - {% endfor %} - {% if inline_admin_formset.formset.can_delete and inline_admin_formset.has_delete_permission %} - + {% for fieldset in inline_admin_form %} + {% for line in fieldset %} + {% for field in line %} + {% if field.is_readonly or not field.field.is_hidden %} + {% endif %} - - {% endif %} - - {% endfor %} - -
+ {{ field.label|capfirst }} + {% if field.help_text %} + ({{ field.help_text|striptags }}) {% endif %} - {% if inline_admin_form.needs_explicit_pk_field %} - {{ inline_admin_form.pk_field.field }} - {% endif %} - {% if inline_admin_form.fk_field %} - {{ inline_admin_form.fk_field.field }} - {% endif %} - {% spaceless %} - {% for fieldset in inline_admin_form %} - {% for line in fieldset %} - {% for field in line %} - {% if not field.is_readonly and field.field.is_hidden %} - {{ field.field }} - {% endif %} - {% endfor %} - {% endfor %} - {% endfor %} - {% endspaceless %} + {% translate "Delete?" %}
{{ inline_admin_form.form.non_field_errors }} - {% if field.is_readonly %} -

{{ field.contents }}

+
+ {% if inline_admin_form.original or inline_admin_form.show_url %} +

+ {% if inline_admin_form.original %} + {{ inline_admin_form.original }} + {% if inline_admin_form.model_admin.show_change_link and inline_admin_form.model_admin.has_registered_model %} + + {% if inline_admin_formset.has_change_permission %} + {% translate "Change" %} {% else %} - {{ field.field.errors.as_ul }} - {{ field.field }} + {% translate "View" %} {% endif %} -

- {% if inline_admin_form.original %} - {{ inline_admin_form.deletion_field.field }} + {% endspaceless %} + + {% if field.is_readonly %} +

{{ field.contents }}

+ {% else %} +
+ {{ field.field|bootstrap_input }} + {% if field.field.errors %} +
+ {{ field.field.errors.as_ul }} +
+ {% endif %} +
+ {% endif %} +
- + {% endfor %} + {% endfor %} + {% endfor %} + {% if inline_admin_formset.formset.can_delete and inline_admin_formset.has_delete_permission %} +
+ {% if inline_admin_form.original %} + {{ inline_admin_form.deletion_field.field }} + {% endif %} +
diff --git a/adminlte3_theme/templates/admin/includes/fieldset.html b/adminlte3_theme/templates/admin/includes/fieldset.html index b9b7ed1..c32e61a 100644 --- a/adminlte3_theme/templates/admin/includes/fieldset.html +++ b/adminlte3_theme/templates/admin/includes/fieldset.html @@ -1,3 +1,4 @@ +{% load bootstrap_forms %}

{% if fieldset.name %}{{ fieldset.name }}{% endif %}

@@ -18,13 +19,13 @@

{% if fieldset.name %}{{ fieldset.name }}{% endif %}

{% if field.is_checkbox %} - {{ field.field }} + {{ field.field|bootstrap_input }} {% else %} {% if field.is_readonly %}
{{ field.contents }}
{% else %} - {{ field.field }} + {{ field.field|bootstrap_input }} {% endif %} {% endif %} {% if field.field.help_text %} @@ -37,4 +38,4 @@

{% if fieldset.name %}{{ fieldset.name }}{% endif %}

{% endfor %}
-
\ No newline at end of file + diff --git a/adminlte3_theme/templates/admin/widgets/related_widget_wrapper.html b/adminlte3_theme/templates/admin/widgets/related_widget_wrapper.html new file mode 100644 index 0000000..135237e --- /dev/null +++ b/adminlte3_theme/templates/admin/widgets/related_widget_wrapper.html @@ -0,0 +1,31 @@ +{% load i18n static %} +
+ {{ rendered_widget }} + {% block links %} + {% spaceless %} + {% if not is_hidden %} + {% if can_change_related %} +
+ + + +
+ {% endif %} + {% if can_add_related %} +
+ + + +
+ {% endif %} + {% if can_delete_related %} +
+ + + +
+ {% endif %} + {% endif %} + {% endspaceless %} + {% endblock %} +
From 3f64e1e5fd45c6aaf3edc81638e05411fd985386 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Krej=C4=8D=C3=AD?= Date: Thu, 3 Jun 2021 20:11:55 +0200 Subject: [PATCH 6/7] Bootstrapify a few more fields, add table stripes --- .../templates/admin/edit_inline/tabular.html | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/adminlte3_theme/templates/admin/edit_inline/tabular.html b/adminlte3_theme/templates/admin/edit_inline/tabular.html index e81047e..d305254 100644 --- a/adminlte3_theme/templates/admin/edit_inline/tabular.html +++ b/adminlte3_theme/templates/admin/edit_inline/tabular.html @@ -15,7 +15,7 @@

{{ inline_admin_formset.formset.non_form_errors }} - +
@@ -64,10 +64,10 @@

{% endif %} {% if inline_admin_form.needs_explicit_pk_field %} - {{ inline_admin_form.pk_field.field }} + {{ inline_admin_form.pk_field.field|bootstrap_input }} {% endif %} {% if inline_admin_form.fk_field %} - {{ inline_admin_form.fk_field.field }} + {{ inline_admin_form.fk_field.field|bootstrap_input }} {% endif %} {% spaceless %} {% for fieldset in inline_admin_form %} @@ -104,9 +104,11 @@

{% endfor %} {% endfor %} {% if inline_admin_formset.formset.can_delete and inline_admin_formset.has_delete_permission %} -

{% endif %} From f0042633d7d7b35dc0d1210be806f161d1cd6296 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Krej=C4=8D=C3=AD?= Date: Sat, 5 Jun 2021 22:07:22 +0200 Subject: [PATCH 7/7] Add formatting for file fields --- adminlte3_theme/static/admin/css/forms.css | 4 ++++ .../admin/widgets/clearable_file_input.html | 12 ++++++++++++ adminlte3_theme/templatetags/bootstrap_forms.py | 8 +++++++- 3 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 adminlte3_theme/templates/admin/widgets/clearable_file_input.html diff --git a/adminlte3_theme/static/admin/css/forms.css b/adminlte3_theme/static/admin/css/forms.css index 03b1e11..39a2815 100644 --- a/adminlte3_theme/static/admin/css/forms.css +++ b/adminlte3_theme/static/admin/css/forms.css @@ -39,6 +39,10 @@ label { color: #333; } +.custom-file label { + font-size: 16px; +} + /* RADIO BUTTONS */ form ul.radiolist li { diff --git a/adminlte3_theme/templates/admin/widgets/clearable_file_input.html b/adminlte3_theme/templates/admin/widgets/clearable_file_input.html new file mode 100644 index 0000000..fa73971 --- /dev/null +++ b/adminlte3_theme/templates/admin/widgets/clearable_file_input.html @@ -0,0 +1,12 @@ +{% if widget.is_initial %}

{{ widget.initial_text }}: {{ widget.value }}{% if not widget.required %} + + +{% endif %}
+{{ widget.input_text }}:{% endif %} +

+
+ + +
+
+{% if widget.is_initial %}

{% endif %} diff --git a/adminlte3_theme/templatetags/bootstrap_forms.py b/adminlte3_theme/templatetags/bootstrap_forms.py index 0c9c6f5..abb7c6a 100644 --- a/adminlte3_theme/templatetags/bootstrap_forms.py +++ b/adminlte3_theme/templatetags/bootstrap_forms.py @@ -1,4 +1,4 @@ -from django.contrib.admin.widgets import RelatedFieldWidgetWrapper, AdminSplitDateTime +from django.contrib.admin.widgets import RelatedFieldWidgetWrapper, AdminSplitDateTime, AdminFileWidget from django.template import Library from django.utils.safestring import mark_safe @@ -11,12 +11,18 @@ def bootstrap_input(value): current_classes = value.field.widget.attrs.get("class", "").strip().split(" ") field_type = value.field.widget.attrs.get("type", "text") + print(type(value.field.widget)) + if field_type == "range": bootstrap_class = "form-control-range" elif field_type == "checkbox" or field_type == "radio": bootstrap_class = "form-check-input" + elif field_type == "file": + bootstrap_class = "custom-file-input" elif isinstance(value.field.widget, RelatedFieldWidgetWrapper): bootstrap_class = "custom-select" # For wrapped widgets (those with edit, add and delete icons) + elif isinstance(value.field.widget, AdminFileWidget): + bootstrap_class = "custom-file-input" elif isinstance(value.field.widget, AdminSplitDateTime): return value # We don't want to style the date time field (for now) else:
+ {% if inline_admin_form.original %} - {{ inline_admin_form.deletion_field.field }} +
+ {{ inline_admin_form.deletion_field.field|bootstrap_input }} +
{% endif %}