mirror of
https://github.com/jazzband/django-auditlog.git
synced 2026-03-16 22:20:26 +00:00
Fix get_field_value field default value handling for Django 6.0 compatibility (#726)
* 'get_field_value' - improve default value handling * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Add Test cases --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
This commit is contained in:
parent
b640df67a3
commit
3a58e0a999
3 changed files with 54 additions and 14 deletions
|
|
@ -62,11 +62,31 @@ def get_field_value(obj, field, use_json_for_changes=False):
|
|||
:return: The value of the field as a string.
|
||||
:rtype: str
|
||||
"""
|
||||
|
||||
def get_default_value():
|
||||
"""
|
||||
Attempts to get the default value for a field from the model's field definition.
|
||||
|
||||
:return: The default value of the field or None
|
||||
"""
|
||||
try:
|
||||
model_field = obj._meta.get_field(field.name)
|
||||
default = model_field.default
|
||||
if default is NOT_PROVIDED:
|
||||
return None
|
||||
|
||||
if callable(default):
|
||||
return default()
|
||||
|
||||
return default
|
||||
except AttributeError:
|
||||
return None
|
||||
|
||||
try:
|
||||
if isinstance(field, DateTimeField):
|
||||
# DateTimeFields are timezone-aware, so we need to convert the field
|
||||
# to its naive form before we can accurately compare them for changes.
|
||||
value = getattr(obj, field.name, None)
|
||||
value = getattr(obj, field.name)
|
||||
try:
|
||||
value = field.to_python(value)
|
||||
except TypeError:
|
||||
|
|
@ -78,30 +98,22 @@ def get_field_value(obj, field, use_json_for_changes=False):
|
|||
):
|
||||
value = django_timezone.make_naive(value, timezone=timezone.utc)
|
||||
elif isinstance(field, JSONField):
|
||||
value = field.to_python(getattr(obj, field.name, None))
|
||||
value = field.to_python(getattr(obj, field.name))
|
||||
if not use_json_for_changes:
|
||||
try:
|
||||
value = json.dumps(value, sort_keys=True, cls=field.encoder)
|
||||
except TypeError:
|
||||
pass
|
||||
elif (field.one_to_one or field.many_to_one) and hasattr(field, "rel_class"):
|
||||
value = smart_str(
|
||||
getattr(obj, field.get_attname(), None), strings_only=True
|
||||
)
|
||||
value = smart_str(getattr(obj, field.get_attname()), strings_only=True)
|
||||
else:
|
||||
value = getattr(obj, field.name, None)
|
||||
|
||||
value = getattr(obj, field.name)
|
||||
if not use_json_for_changes:
|
||||
value = smart_str(value)
|
||||
if type(value).__name__ == "__proxy__":
|
||||
value = str(value)
|
||||
|
||||
except ObjectDoesNotExist:
|
||||
value = (
|
||||
field.default
|
||||
if getattr(field, "default", NOT_PROVIDED) is not NOT_PROVIDED
|
||||
else None
|
||||
)
|
||||
except (ObjectDoesNotExist, AttributeError):
|
||||
return get_default_value()
|
||||
|
||||
return value
|
||||
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ class SimpleModel(models.Model):
|
|||
boolean = models.BooleanField(default=False)
|
||||
integer = models.IntegerField(blank=True, null=True)
|
||||
datetime = models.DateTimeField(auto_now=True)
|
||||
char = models.CharField(null=True, max_length=100, default=lambda: "default value")
|
||||
|
||||
history = AuditlogHistoryField(delete_related=True)
|
||||
|
||||
|
|
|
|||
|
|
@ -2111,6 +2111,33 @@ class ModelInstanceDiffTest(TestCase):
|
|||
msg="ObjectDoesNotExist should be handled",
|
||||
)
|
||||
|
||||
def test_field_with_no_default_provided(self):
|
||||
"""Field with no default (NOT_PROVIDED) should return None."""
|
||||
first = SimpleModel(integer=1)
|
||||
second = SimpleModel()
|
||||
|
||||
delattr(second, "integer")
|
||||
|
||||
changes = model_instance_diff(first, second)
|
||||
self.assertEqual(
|
||||
changes,
|
||||
{"integer": ("1", "None")},
|
||||
msg="field with no default should return None",
|
||||
)
|
||||
|
||||
def test_field_with_callable_default(self):
|
||||
first = SimpleModel(char="value")
|
||||
second = SimpleModel()
|
||||
|
||||
delattr(second, "char")
|
||||
|
||||
changes = model_instance_diff(first, second)
|
||||
self.assertEqual(
|
||||
changes,
|
||||
{"char": ("value", "default value")},
|
||||
msg="callable default should be handled",
|
||||
)
|
||||
|
||||
def test_diff_models_with_json_fields(self):
|
||||
first = JSONModel.objects.create(
|
||||
json={
|
||||
|
|
|
|||
Loading…
Reference in a new issue