Updated css and added detected changes to confirmation page
parent
3f8961478a
commit
47b1d6beee
|
|
@ -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 {}),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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>
|
||||
› <a href="{% url 'admin:app_list' app_label=opts.app_label %}">{{ opts.app_config.verbose_name }}</a>
|
||||
› <a href="{% url opts|admin_urlname:'changelist' %}">{{ opts.verbose_name_plural|capfirst }}</a>
|
||||
› <a href="{% url opts|admin_urlname:'change' object_id|admin_urlquote %}">{{ new_object|truncatewords:"18" }}</a>
|
||||
› <a href="{% url opts|admin_urlname:'change' object_id|admin_urlquote %}">{{ object_name|truncatewords:"18" }}</a>
|
||||
› {% 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, I’m 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>
|
||||
|
|
|
|||
|
|
@ -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 %}
|
||||
|
|
|
|||
Binary file not shown.
|
After Width: | Height: | Size: 107 KiB |
|
|
@ -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):
|
||||
|
|
|
|||
Loading…
Reference in New Issue