Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Question: Datatype casting in JSON changes column #675

Open
ulinja opened this issue Oct 16, 2024 · 1 comment
Open

Question: Datatype casting in JSON changes column #675

ulinja opened this issue Oct 16, 2024 · 1 comment

Comments

@ulinja
Copy link

ulinja commented Oct 16, 2024

When logging changes to model instances, the changes column casts all python data types into strings, rather than their JSON equivalents:

  • None -> "None" and not null
  • True -> "True" and not true
  • 1 -> "1" and not 1

and so on.

To illustrate this, consider the following model:

from django.db import models
from auditlog.registry import auditlog

class Person(models.Model):
    is_cool = models.BooleanField(default=False)
    age = models.IntegerField(
        null=True,
        default=None,
    )

auditlog.register(Person)

And with the following changes:

>>> from myapp.models import Person
>>> person = Person.objects.create()
>>> person.is_cool = True
>>> person.age = 42
>>> person.save()
>>> 
>>> from auditlog.models import LogEntry
>>> log_entry = LogEntry.objects.first()
>>> log_entry.changes
{'is_cool': ['False', 'True'], 'age': ['None', '42']}
>>> type(log_entry.changes['age'][0])
<class 'str'>
>>> type(log_entry.changes['age'][1])
<class 'str'>

The values in the changes object stored in the database just get turned into strings, such that all type information is lost.
Here is what the changes column looks like in the database:

{"is_cool": ["False", "True"], "age": ["None", "42"]}

Instead, I would expect the following:

>>> log_entry.changes
{'is_cool': [False, True], 'age': [None, 42]}
>>> type(log_entry.changes['age'][0])
<class 'NoneType'>
>>> type(log_entry.changes['age'][1])
<class 'int'>

and the following JSON in the DB:

{"is_cool": [false, true], "age": [null, 42]}

Am I doing something wrong or is this behavior intended?

@hramezani
Copy link
Member

Yes, it is a string. the model field's type is JSONField. but it seems the value type is string.

I think it can be json as the field type is JSONField. not sure how we can change it without introducing a breaking change.

Probably by introducing a config flag like STORE_JSON_CHANGES or something like that with the default value of False. then by enabling this flag the changes will be stored in json and we can remove the config in the next major release.

BTW, this is an initial idea and needs some more investigation. Unfortunately, I don't have time to investigate.

@aqeelat @aleh-rymasheuski do you have any idea here?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants