1
0
mirror of https://github.com/django/django.git synced 2025-01-18 14:24:39 +00:00

Refs #34462 -- Removed ModelAdmin.log_deletion() and LogEntryManager.log_action() per deprecation timeline.

This commit is contained in:
Sarah Boyce 2024-12-12 16:55:42 +01:00
parent 817bc5800b
commit 6c120508b6
6 changed files with 4 additions and 240 deletions

View File

@ -1,5 +1,4 @@
import json
import warnings
from django.conf import settings
from django.contrib.admin.utils import quote
@ -7,7 +6,6 @@ from django.contrib.contenttypes.models import ContentType
from django.db import models
from django.urls import NoReverseMatch, reverse
from django.utils import timezone
from django.utils.deprecation import RemovedInDjango60Warning
from django.utils.text import get_text_list
from django.utils.translation import gettext
from django.utils.translation import gettext_lazy as _
@ -26,56 +24,9 @@ ACTION_FLAG_CHOICES = [
class LogEntryManager(models.Manager):
use_in_migrations = True
def log_action(
self,
user_id,
content_type_id,
object_id,
object_repr,
action_flag,
change_message="",
):
warnings.warn(
"LogEntryManager.log_action() is deprecated. Use log_actions() instead.",
RemovedInDjango60Warning,
stacklevel=2,
)
if isinstance(change_message, list):
change_message = json.dumps(change_message)
return self.model.objects.create(
user_id=user_id,
content_type_id=content_type_id,
object_id=str(object_id),
object_repr=object_repr[:200],
action_flag=action_flag,
change_message=change_message,
)
def log_actions(
self, user_id, queryset, action_flag, change_message="", *, single_object=False
):
# RemovedInDjango60Warning.
if type(self).log_action != LogEntryManager.log_action:
warnings.warn(
"The usage of log_action() is deprecated. Implement log_actions() "
"instead.",
RemovedInDjango60Warning,
stacklevel=2,
)
return [
self.log_action(
user_id=user_id,
content_type_id=ContentType.objects.get_for_model(
obj, for_concrete_model=False
).id,
object_id=obj.pk,
object_repr=str(obj),
action_flag=action_flag,
change_message=change_message,
)
for obj in queryset
]
if isinstance(change_message, list):
change_message = json.dumps(change_message)

View File

@ -2,7 +2,6 @@ import copy
import enum
import json
import re
import warnings
from functools import partial, update_wrapper
from urllib.parse import parse_qsl
from urllib.parse import quote as urlquote
@ -56,7 +55,6 @@ from django.http.response import HttpResponseBase
from django.template.response import SimpleTemplateResponse, TemplateResponse
from django.urls import reverse
from django.utils.decorators import method_decorator
from django.utils.deprecation import RemovedInDjango60Warning
from django.utils.html import format_html
from django.utils.http import urlencode
from django.utils.safestring import mark_safe
@ -967,28 +965,6 @@ class ModelAdmin(BaseModelAdmin):
single_object=True,
)
def log_deletion(self, request, obj, object_repr):
"""
Log that an object will be deleted. Note that this method must be
called before the deletion.
The default implementation creates an admin LogEntry object.
"""
warnings.warn(
"ModelAdmin.log_deletion() is deprecated. Use log_deletions() instead.",
RemovedInDjango60Warning,
stacklevel=2,
)
from django.contrib.admin.models import DELETION, LogEntry
return LogEntry.objects.log_action(
user_id=request.user.pk,
content_type_id=get_content_type_for_model(obj).pk,
object_id=obj.pk,
object_repr=object_repr,
action_flag=DELETION,
)
def log_deletions(self, request, queryset):
"""
Log that objects will be deleted. Note that this method must be called
@ -998,16 +974,6 @@ class ModelAdmin(BaseModelAdmin):
"""
from django.contrib.admin.models import DELETION, LogEntry
# RemovedInDjango60Warning.
if type(self).log_deletion != ModelAdmin.log_deletion:
warnings.warn(
"The usage of log_deletion() is deprecated. Implement log_deletions() "
"instead.",
RemovedInDjango60Warning,
stacklevel=2,
)
return [self.log_deletion(request, obj, str(obj)) for obj in queryset]
return LogEntry.objects.log_actions(
user_id=request.user.pk,
queryset=queryset,

View File

@ -299,3 +299,6 @@ to remove usage of these features.
* ``django.urls.register_converter()`` no longer allows overriding existing
converters.
* The ``ModelAdmin.log_deletion()`` and ``LogEntryManager.log_action()``
methods are removed.

View File

@ -1,5 +1,4 @@
from django.contrib import admin
from django.contrib.admin.models import LogEntry, LogEntryManager
from django.db import models
from django.utils.translation import gettext_lazy as _
@ -87,26 +86,3 @@ class VehicleMixin(Vehicle):
class Car(VehicleMixin):
pass
class InheritedLogEntryManager(LogEntryManager):
model = LogEntry
def log_action(
self,
user_id,
content_type_id,
object_id,
object_repr,
action_flag,
change_message="",
):
return LogEntry.objects.create(
user_id=user_id,
content_type_id=content_type_id,
object_id=str(object_id),
# Changing actual repr to test repr
object_repr="Test Repr",
action_flag=action_flag,
change_message=change_message,
)

View File

@ -8,10 +8,9 @@ from django.contrib.contenttypes.models import ContentType
from django.test import TestCase, override_settings
from django.urls import reverse
from django.utils import translation
from django.utils.deprecation import RemovedInDjango60Warning
from django.utils.html import escape
from .models import Article, ArticleProxy, Car, InheritedLogEntryManager, Site
from .models import Article, ArticleProxy, Car, Site
@override_settings(ROOT_URLCONF="admin_utils.urls")
@ -236,22 +235,6 @@ class LogEntryTests(TestCase):
logentry = LogEntry.objects.first()
self.assertEqual(repr(logentry), str(logentry.action_time))
# RemovedInDjango60Warning.
def test_log_action(self):
msg = "LogEntryManager.log_action() is deprecated. Use log_actions() instead."
content_type_val = ContentType.objects.get_for_model(Article).pk
with self.assertWarnsMessage(RemovedInDjango60Warning, msg) as ctx:
log_entry = LogEntry.objects.log_action(
self.user.pk,
content_type_val,
self.a1.pk,
repr(self.a1),
CHANGE,
change_message="Changed something else",
)
self.assertEqual(log_entry, LogEntry.objects.latest("id"))
self.assertEqual(ctx.filename, __file__)
def test_log_actions(self):
queryset = Article.objects.all().order_by("-id")
msg = "Deleted Something"
@ -289,46 +272,6 @@ class LogEntryTests(TestCase):
]
self.assertSequenceEqual(logs, expected_log_values)
# RemovedInDjango60Warning.
def test_log_action_fallback(self):
LogEntry.objects2 = InheritedLogEntryManager()
queryset = Article.objects.all().order_by("-id")
content_type = ContentType.objects.get_for_model(self.a1)
self.assertEqual(len(queryset), 3)
msg = (
"The usage of log_action() is deprecated. Implement log_actions() instead."
)
with (
self.assertNumQueries(3),
self.assertWarnsMessage(RemovedInDjango60Warning, msg) as ctx,
):
LogEntry.objects2.log_actions(self.user.pk, queryset, DELETION)
self.assertEqual(ctx.filename, __file__)
log_values = (
LogEntry.objects.filter(action_flag=DELETION)
.order_by("id")
.values_list(
"user",
"content_type",
"object_id",
"object_repr",
"action_flag",
"change_message",
)
)
expected_log_values = [
(
self.user.pk,
content_type.id,
str(obj.pk),
"Test Repr",
DELETION,
"",
)
for obj in queryset
]
self.assertSequenceEqual(log_values, expected_log_values)
def test_recentactions_without_content_type(self):
"""
If a LogEntry is missing content_type it will not display it in span

View File

@ -21,7 +21,6 @@ from django.db import models
from django.forms.widgets import Select
from django.test import RequestFactory, SimpleTestCase, TestCase
from django.test.utils import isolate_apps
from django.utils.deprecation import RemovedInDjango60Warning
from .models import Band, Concert, Song
@ -891,80 +890,6 @@ class ModelAdminTests(TestCase):
]
self.assertSequenceEqual(logs, expected_log_values)
# RemovedInDjango60Warning.
def test_log_deletion(self):
ma = ModelAdmin(Band, self.site)
mock_request = MockRequest()
mock_request.user = User.objects.create(username="bill")
content_type = get_content_type_for_model(self.band)
msg = "ModelAdmin.log_deletion() is deprecated. Use log_deletions() instead."
with self.assertWarnsMessage(RemovedInDjango60Warning, msg) as ctx:
created = ma.log_deletion(mock_request, self.band, str(self.band))
self.assertEqual(ctx.filename, __file__)
fetched = LogEntry.objects.filter(action_flag=DELETION).latest("id")
self.assertEqual(created, fetched)
self.assertEqual(fetched.action_flag, DELETION)
self.assertEqual(fetched.content_type, content_type)
self.assertEqual(fetched.object_id, str(self.band.pk))
self.assertEqual(fetched.user, mock_request.user)
self.assertEqual(fetched.change_message, "")
self.assertEqual(fetched.object_repr, str(self.band))
# RemovedInDjango60Warning.
def test_log_deletion_fallback(self):
class InheritedModelAdmin(ModelAdmin):
def log_deletion(self, request, obj, object_repr):
return super().log_deletion(request, obj, object_repr)
ima = InheritedModelAdmin(Band, self.site)
mock_request = MockRequest()
mock_request.user = User.objects.create(username="akash")
content_type = get_content_type_for_model(self.band)
Band.objects.create(
name="The Beatles",
bio="A legendary rock band from Liverpool.",
sign_date=date(1962, 1, 1),
)
Band.objects.create(
name="Mohiner Ghoraguli",
bio="A progressive rock band from Calcutta.",
sign_date=date(1975, 1, 1),
)
queryset = Band.objects.all().order_by("-id")[:3]
self.assertEqual(len(queryset), 3)
msg = (
"The usage of log_deletion() is deprecated. Implement log_deletions() "
"instead."
)
with self.assertNumQueries(3):
with self.assertWarnsMessage(RemovedInDjango60Warning, msg) as ctx:
ima.log_deletions(mock_request, queryset)
self.assertEqual(ctx.filename, __file__)
logs = (
LogEntry.objects.filter(action_flag=DELETION)
.order_by("id")
.values_list(
"user_id",
"content_type",
"object_id",
"object_repr",
"action_flag",
"change_message",
)
)
expected_log_values = [
(
mock_request.user.id,
content_type.id,
str(obj.pk),
str(obj),
DELETION,
"",
)
for obj in queryset
]
self.assertSequenceEqual(logs, expected_log_values)
def test_get_autocomplete_fields(self):
class NameAdmin(ModelAdmin):
search_fields = ["name"]