Skip to content

Commit 37c9859

Browse files
committed
feat: update django-admin-confirmation
* TrangPham/django-admin-confirm#32 is now released so our own modifications can be removed. Refs: LIIK-747
1 parent 1ac8766 commit 37c9859

File tree

5 files changed

+7
-155
lines changed

5 files changed

+7
-155
lines changed

poetry.lock

Lines changed: 4 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ social-auth-app-django = "^5.4.1"
4040
uWSGI = "^2.0.22"
4141
django-advanced-password-validation = "^1.2.0"
4242
django-axes = "^7.0.0"
43-
django-admin-confirm = "^1.0.0"
43+
django-admin-confirm = "^1.0.1"
4444

4545

4646
[tool.poetry.group.dev.dependencies]

traffic_control/admin/plan.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from copy import copy
22

3+
from admin_confirm import AdminConfirmMixin
34
from django.contrib.gis import admin
45
from django.http import HttpResponseForbidden, HttpResponseRedirect
56
from django.shortcuts import get_object_or_404, render
@@ -9,7 +10,6 @@
910
from traffic_control.admin.audit_log import AuditLogHistoryAdmin
1011
from traffic_control.forms import PlanModelForm, PlanRelationsForm
1112
from traffic_control.mixins import (
12-
CityInfraAdminConfirmMixin,
1313
EnumChoiceValueDisplayAdminMixin,
1414
Geometry3DFieldAdminMixin,
1515
SoftDeleteAdminMixin,
@@ -26,7 +26,7 @@ class PlanAdmin(
2626
SoftDeleteAdminMixin,
2727
UserStampedAdminMixin,
2828
Geometry3DFieldAdminMixin,
29-
CityInfraAdminConfirmMixin,
29+
AdminConfirmMixin,
3030
admin.GISModelAdmin,
3131
AuditLogHistoryAdmin,
3232
):

traffic_control/mixins/admin.py

Lines changed: 0 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,5 @@
1-
from typing import Dict
2-
3-
from admin_confirm import AdminConfirmMixin
41
from django.contrib.admin import SimpleListFilter
52
from django.contrib.gis.forms import OSMWidget
6-
from django.db.models import FileField, ImageField, ManyToManyField, Model
7-
from django.forms import ModelForm
83
from django.utils.translation import gettext_lazy as _
94

105
from traffic_control.models.plan import Plan
@@ -145,82 +140,3 @@ def delete_queryset(self, request, queryset):
145140
class DeviceTypeSearchAdminMixin:
146141
def get_search_fields(self, request):
147142
return self.search_fields + ("device_type__code", "device_type__legacy_code")
148-
149-
150-
class CityInfraAdminConfirmMixin(AdminConfirmMixin):
151-
"""Class for tweaking admin confirmation behaviour.
152-
Overwrite private _get_changed_data function to support fields only in admin form not in model itself.
153-
"""
154-
155-
only_form_fields = []
156-
157-
def _get_changed_data(self, form: ModelForm, model: Model, obj: object, add: bool) -> Dict:
158-
"""
159-
Given a form, detect the changes on the form from the default values (if add) or
160-
from the database values of the object (model instance)
161-
162-
form - Submitted form that is attempting to alter the obj
163-
model - the model class of the obj
164-
obj - instance of model which is being altered
165-
add - are we attempting to add the obj or does it already exist in the database
166-
167-
Returns a dictionary of the fields and their changed values if any
168-
"""
169-
170-
changed_data = {}
171-
if add:
172-
self._handle_add(form, model, changed_data)
173-
else:
174-
self._handle_change(form, model, changed_data, obj)
175-
176-
return changed_data
177-
178-
def _filtered_form_cleaned_data_items(self, form):
179-
return filter(lambda x: x[0] not in self.only_form_fields, form.cleaned_data.items())
180-
181-
@staticmethod
182-
def _display_for_changed_data(field, initial_value, new_value):
183-
if not (isinstance(field, FileField) or isinstance(field, ImageField)):
184-
return [initial_value, new_value]
185-
186-
if initial_value:
187-
if new_value is False:
188-
# Clear has been selected
189-
return [initial_value.name, None]
190-
elif new_value:
191-
return [initial_value.name, new_value.name]
192-
else:
193-
# No cover: Technically doesn't get called in current code because
194-
# This function is only called if there was a difference in the data
195-
return [initial_value.name, initial_value.name] # pragma: no cover
196-
197-
if new_value:
198-
return [None, new_value.name]
199-
200-
return [None, None]
201-
202-
def _handle_add(self, form, model, changed_data):
203-
for name, new_value in self._filtered_form_cleaned_data_items(form):
204-
# Don't consider default values as changed for adding
205-
field_object = model._meta.get_field(name)
206-
default_value = field_object.get_default()
207-
if new_value is not None and new_value != default_value:
208-
# Show what the default value is
209-
changed_data[name] = self._display_for_changed_data(field_object, default_value, new_value)
210-
211-
def _handle_change(self, form, model, changed_data, obj):
212-
for name, new_value in self._filtered_form_cleaned_data_items(form):
213-
# Ignore fields that are only in admin for and not in the model itself
214-
# Since the form considers initial as the value first shown in the form
215-
# It could be incorrect when user hits save, and then hits "No, go back to edit"
216-
obj.refresh_from_db()
217-
218-
field_object = model._meta.get_field(name)
219-
initial_value = getattr(obj, name)
220-
221-
# Note: getattr does not work on ManyToManyFields
222-
if isinstance(field_object, ManyToManyField):
223-
initial_value = field_object.value_from_object(obj)
224-
225-
if initial_value != new_value:
226-
changed_data[name] = self._display_for_changed_data(field_object, initial_value, new_value)

traffic_control/tests/test_plan_admin.py

Lines changed: 0 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,16 @@
1-
from unittest.mock import patch
2-
31
import pytest
42
from auditlog.models import LogEntry
53
from django.conf import settings
6-
from django.contrib.admin import site
74
from django.contrib.auth import get_user_model
85
from django.contrib.auth.models import Permission
96
from django.contrib.contenttypes.models import ContentType
107
from django.contrib.gis.geos import MultiPolygon
11-
from django.db.models import FileField
128
from django.test import override_settings
139
from django.urls import reverse
1410

1511
from city_furniture.tests.factories import get_furniture_signpost_plan
16-
from traffic_control.admin.plan import PlanAdmin
1712
from traffic_control.forms import PlanModelForm
1813
from traffic_control.geometry_utils import get_z_for_polygon
19-
from traffic_control.mixins.admin import CityInfraAdminConfirmMixin
2014
from traffic_control.models import Plan
2115
from traffic_control.tests.factories import (
2216
AdditionalSignPlanFactory,
@@ -34,7 +28,6 @@
3428
illegal_multipolygon,
3529
invalid_ewkt_str,
3630
test_multi_polygon,
37-
test_multi_polygon_2,
3831
test_point,
3932
test_point_2,
4033
test_polygon,
@@ -408,63 +401,5 @@ def test__plan_create_with_location_ewkt():
408401
assert plan.location.ewkt == test_multi_polygon.ewkt
409402

410403

411-
@pytest.mark.parametrize("derive_location", (False, True))
412-
@pytest.mark.django_db
413-
def test_plan_location_change_with_derive_location(admin_client, derive_location):
414-
"""Just test that confirmation dialog _handle_change is called when derive_location is on
415-
and not when it is off.
416-
NOTE: this test should be removed when/if support for non-model fields is supported in django-admin-confirm."""
417-
plan = PlanFactory(location=test_multi_polygon)
418-
post_data = {
419-
"derive_location": derive_location,
420-
"location": plan.location,
421-
"location_ewkt": test_multi_polygon_2.ewkt,
422-
"z_coord": 0,
423-
"decision_id": plan.decision_id,
424-
"name": plan.name,
425-
"_save": "Save",
426-
}
427-
url = reverse("admin:traffic_control_plan_change", kwargs={"object_id": plan.pk})
428-
pa = PlanAdmin(Plan, site)
429-
if derive_location:
430-
post_data["_confirm_change"] = "Confirm"
431-
with patch(
432-
"traffic_control.admin.plan.PlanAdmin._handle_change", side_effect=pa._handle_change
433-
) as mocked_function:
434-
admin_client.post(url, data=post_data)
435-
mocked_function.assert_called_once()
436-
else:
437-
with patch(
438-
"traffic_control.admin.plan.PlanAdmin._handle_change", side_effect=pa._handle_change
439-
) as mocked_function:
440-
admin_client.post(url, data=post_data)
441-
mocked_function.assert_not_called()
442-
443-
444-
def test_cityinfra_admin_confirm_mixin_display_for_changed_data():
445-
"""NOTE: this test should be removed when django-admin-confirm mixin has support for cityinfra features.
446-
This is here just to please sonaqube with new code coverage percentage.
447-
"""
448-
field = FileField()
449-
450-
class DummyValue:
451-
def __init__(self, name):
452-
self.name = name
453-
454-
test_initial_name = "testinitial"
455-
test_new_value = "testnewvalue"
456-
457-
ret = CityInfraAdminConfirmMixin._display_for_changed_data(field, DummyValue(test_initial_name), False)
458-
assert ret == [test_initial_name, None]
459-
460-
ret = CityInfraAdminConfirmMixin._display_for_changed_data(
461-
field, DummyValue(test_initial_name), DummyValue(test_new_value)
462-
)
463-
assert ret == [test_initial_name, test_new_value]
464-
465-
ret = CityInfraAdminConfirmMixin._display_for_changed_data(field, None, DummyValue(test_new_value))
466-
assert ret == [None, test_new_value]
467-
468-
469404
def _get_plan_mandatory_fields():
470405
return {"name": "testplan", "decision_id": "testid", "z_coord": 0}

0 commit comments

Comments
 (0)