Updated css and added detected changes to confirmation page

main
Thu Trang Pham 2020-11-01 01:21:51 -07:00
parent 3f8961478a
commit 47b1d6beee
6 changed files with 83 additions and 21 deletions

View File

@ -10,11 +10,21 @@ from django.utils.translation import gettext as _
class AdminConfirmMixin(object):
"""Generic AdminConfirm Mixin"""
change_needs_confirmation = False
confirm_change = None
confirmation_fields = None
# Custom templates (designed to be over-ridden in subclasses)
change_confirmation_template = None
def get_confirmation_fields(self, request, obj=None):
"""
Hook for specifying confirmation fields
"""
if self.confirmation_fields:
return self.confirmation_fields
return flatten_fieldsets(self.get_fieldsets(request, obj))
def render_change_confirmation(self, request, context):
opts = self.model._meta
app_label = opts.app_label
@ -38,20 +48,19 @@ class AdminConfirmMixin(object):
)
def change_view(self, request, object_id=None, form_url="", extra_context=None):
# self.message_user(request, f"{request.POST}")
if request.method == "POST" and request.POST.get("_change_needs_confirmation"):
if request.method == "POST" and request.POST.get("_confirm_change"):
return self._change_confirmation_view(
request, object_id, form_url, extra_context
)
extra_context = {
**(extra_context or {}),
'change_needs_confirmation': self.change_needs_confirmation
'confirm_change': self.confirm_change
}
return super().change_view(request, object_id, form_url, extra_context)
def _change_confirmation_view(self, request, object_id, form_url, extra_context):
# Do we need any of this code?
# This code is taken from __changeform_view
to_field = request.POST.get(
TO_FIELD_VAR, request.GET.get(TO_FIELD_VAR)
)
@ -78,7 +87,6 @@ class AdminConfirmMixin(object):
request, obj, change=not add, fields=flatten_fieldsets(fieldsets)
)
# Should we be validating the data here? Or just pass it to super?
form = ModelForm(request.POST, request.FILES, obj)
form_validated = form.is_valid()
if form_validated:
@ -86,10 +94,17 @@ class AdminConfirmMixin(object):
else:
new_object = form.instance
if add:
title = _("Add %s")
elif self.has_change_permission(request, obj):
title = _("Change %s")
# Parse the changed data - Note that using form.changed_data would not work as initial is not set
changed_data = {}
for name, field in form.fields.items():
initial_value = obj.__getattribute__(name)
new_value = new_object.__getattribute__(name)
if field.has_changed(initial_value, new_value):
changed_data[name] = [initial_value, new_value]
if not bool(set(self.get_confirmation_fields(request, obj)) & set(changed_data.keys())):
# No confirmation required for changed fields, continue to save
return super().change_view(request, object_id, form_url, extra_context)
# Parse the original save action from request
save_action = None
@ -103,22 +118,25 @@ class AdminConfirmMixin(object):
for key in request.POST:
if key.startswith("_") or key == 'csrfmiddlewaretoken':
continue
form_data[key] = request.POST.get(key)
if add:
title_action = _('adding')
else:
title_action = _('changing')
context = {
**self.admin_site.each_context(request),
"title": title % opts.verbose_name,
"preserved_filters": self.get_preserved_filters(request),
"title": f"{_('Confirm')} {title_action} {opts.verbose_name}",
"subtitle": str(obj),
"object_name": str(obj),
"object_id": object_id,
"original": obj,
"new_object": new_object,
"app_label": opts.app_label,
"model_name": opts.model_name,
"opts": opts,
"preserved_filters": self.get_preserved_filters(request),
"form_data": form_data,
"changed_data": changed_data,
"submit_name": save_action,
**(extra_context or {}),
}

View File

@ -0,0 +1,24 @@
.submit-row a.cancel-link {
display: block;
background: #ba2121;
border-radius: 4px;
padding: 10px 15px;
height: 15px;
line-height: 15px;
color: #fff;
}
.submit-row a.cancel-link:focus,
.submit-row a.cancel-link:hover,
.submit-row a.cancel-link:active {
background: #a41515;
}
.changed-data table {
width: 100%;
}
.changed-data th,
.changed-data td {
width: 30%;
white-space: nowrap;
}

View File

@ -7,7 +7,11 @@
<script src="{% static 'admin/js/cancel.js' %}" async></script>
{% endblock %}
{% block extrastyle %}{{ block.super }}<link rel="stylesheet" type="text/css" href="{% static "admin/css/forms.css" %}">{% endblock %}
{% block extrastyle %}
{{ block.super }}
<link rel="stylesheet" type="text/css" href="{% static "admin/css/forms.css" %}">
<link rel="stylesheet" type="text/css" href="{% static "admin/css/confirmation.css" %}">
{% endblock %}
{% block bodyclass %}{{ block.super }} app-{{ opts.app_label }} model-{{ opts.model_name }} change-confirmation{% endblock %}
@ -16,13 +20,24 @@
<a href="{% url 'admin:index' %}">{% trans 'Home' %}</a>
&rsaquo; <a href="{% url 'admin:app_list' app_label=opts.app_label %}">{{ opts.app_config.verbose_name }}</a>
&rsaquo; <a href="{% url opts|admin_urlname:'changelist' %}">{{ opts.verbose_name_plural|capfirst }}</a>
&rsaquo; <a href="{% url opts|admin_urlname:'change' object_id|admin_urlquote %}">{{ new_object|truncatewords:"18" }}</a>
&rsaquo; <a href="{% url opts|admin_urlname:'change' object_id|admin_urlquote %}">{{ object_name|truncatewords:"18" }}</a>
&rsaquo; {% trans 'Change Confirmation' %}
</div>
{% endblock %}
{% block content %}
<p>{% blocktrans with escaped_object=object %}Are you sure you want to change the {{ model_name }} "{{ object_name }}"?{% endblocktrans %}</p>
{% if changed_data %}
<div class="changed-data">
<p><b>Detected Changes:</b></p>
<table>
<tr><th>Field</th><th>Current Value</th><th>New Value</th></tr>
{% for field, values in changed_data.items %}
<tr><td>{{ field }}</td><td>{{ values.0 }}</td><td>{{ values.1 }}</td></tr>
{% endfor %}
</table>
</div>
{% endif %}
<form method="post" action="{% url opts|admin_urlname:'change' object_id|admin_urlquote %}">{% csrf_token %}
<div>
{% for key, value in form_data.items %}
@ -32,7 +47,9 @@
{% if to_field %}<input type="hidden" name="{{ to_field_var }}" value="{{ to_field }}">{% endif %}
<div class="submit-row">
<input type="submit" value="{% trans 'Yes, Im sure' %}" name="{{ submit_name }}">
<a href="#" class="button closelink">{% trans "No, continue to edit" %}</a>
<p class="deletelink-box">
<a href="#" class="button cancel-link">{% trans "No, continue to edit" %}</a>
</p>
</div>
</div>
</form>

View File

@ -2,6 +2,6 @@
{% load i18n admin_urls %}
{% block submit-row %}
<input hidden name="_change_needs_confirmation" value="{{ change_needs_confirmation }}" />
<input hidden name="_confirm_change" value="{{ confirm_change }}" />
{{ block.super }}
{% endblock %}

BIN
screenshot.png 100644

Binary file not shown.

After

Width:  |  Height:  |  Size: 107 KiB

View File

@ -7,11 +7,14 @@ from .models import Item, Inventory, Shop
class ItemAdmin(AdminConfirmMixin, admin.ModelAdmin):
list_display = ('name', 'price', 'currency')
change_needs_confirmation = True
require_change_confirmation = True
class InventoryAdmin(admin.ModelAdmin):
class InventoryAdmin(AdminConfirmMixin, admin.ModelAdmin):
list_display = ('shop', 'item', 'quantity')
requires_change_confirmation = {
'fields': ['shop']
}
class ShopAdmin(admin.ModelAdmin):