Skip to content

Conversation

@kubajecminek
Copy link
Contributor

Hi, thank you for auditlog.

This pull request fixes bug number #664. It is naive implementation but it seems that it works as expected. Please let me know what you think so I can adjust the patch accordingly.

@codecov
Copy link

codecov bot commented Mar 18, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 95.54%. Comparing base (5289482) to head (04386bc).
Report is 41 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master     #707      +/-   ##
==========================================
+ Coverage   95.21%   95.54%   +0.32%     
==========================================
  Files          31       33       +2     
  Lines        1025     1101      +76     
==========================================
+ Hits          976     1052      +76     
  Misses         49       49              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Comment on lines +357 to +358
def test_create_duplicate_with_pk_none(self):
pass

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why does this test here do?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It disables test_create_duplicate_with_pk_none test for models which have another model as primary key (ModelPrimaryKeyModel).

obj = self.obj
obj.pk = None
obj.save()
self.assertEqual(LogEntry.objects.count(), initial_entries_count + 1)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The fix that you did prevent log entry creation in case of pk is None, why did the log entry count increased by one?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

New entry has been created because we duplicated obj which is expected behavior. auditlog currently thinks that we're updating the object which is why it crashes on IntegrityError.

@hramezani
Copy link
Member

Thanks @kubajecminek for the fix. I do not entirely understand the problem. could you please provide more information like error trace back?

Also, please add an entry to changelog file.

@kubajecminek
Copy link
Contributor Author

kubajecminek commented Mar 18, 2025

Thanks for the review.

Thanks @kubajecminek for the fix. I do not entirely understand the problem. could you please provide more information like error trace back?

Sure. You can copy/duplicate object in Django with this trick:

entry = LogEntry.objects.first()
entry.pk = None
entry.save() # New object will be created

However auditlog thinks that we're updating the object.

Here's sample backtrace from running the tests without the fix:

======================================================================
ERROR: test_create_duplicate_with_pk_none (auditlog_tests.tests.UUIDPrimaryKeyModelModelWithActorTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/Users/kuba.jecminek/Code/django-auditlog/.tox/py39-django42/lib/python3.9/site-packages/django/db/backends/utils.py", line 89, in _execute
    return self.cursor.execute(sql, params)
psycopg2.errors.NotNullViolation: null value in column "object_pk" of relation "auditlog_logentry" violates not-null constraint
DETAIL:  Failing row contains (512, null, null, UUIDPrimaryKeyModel object (None), 1, {"text": ["None", "I am strange."], "boolean": ["None", "False"]..., 2025-03-18 16:45:42.081858+00, null, 11, null, null, null, null, , null, null).


The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/Users/kuba.jecminek/Code/django-auditlog/auditlog_tests/tests.py", line 242, in test_create_duplicate_with_pk_none
    obj.save()
  File "/Users/kuba.jecminek/Code/django-auditlog/.tox/py39-django42/lib/python3.9/site-packages/django/db/models/base.py", line 814, in save
    self.save_base(
  File "/Users/kuba.jecminek/Code/django-auditlog/.tox/py39-django42/lib/python3.9/site-packages/django/db/models/base.py", line 861, in save_base
    pre_save.send(
  File "/Users/kuba.jecminek/Code/django-auditlog/.tox/py39-django42/lib/python3.9/site-packages/django/dispatch/dispatcher.py", line 176, in send
    return [
  File "/Users/kuba.jecminek/Code/django-auditlog/.tox/py39-django42/lib/python3.9/site-packages/django/dispatch/dispatcher.py", line 177, in <listcomp>
    (receiver, receiver(signal=self, sender=sender, **named))
  File "/Users/kuba.jecminek/Code/django-auditlog/auditlog/receivers.py", line 27, in wrapper
    signal_handler(*args, **kwargs)
  File "/Users/kuba.jecminek/Code/django-auditlog/auditlog/receivers.py", line 59, in log_update
    _create_log_entry(
  File "/Users/kuba.jecminek/Code/django-auditlog/auditlog/receivers.py", line 146, in _create_log_entry
    raise error
  File "/Users/kuba.jecminek/Code/django-auditlog/auditlog/receivers.py", line 124, in _create_log_entry
    log_entry = LogEntry.objects.log_create(
  File "/Users/kuba.jecminek/Code/django-auditlog/auditlog/models.py", line 77, in log_create
    return self.create(**kwargs)
  File "/Users/kuba.jecminek/Code/django-auditlog/.tox/py39-django42/lib/python3.9/site-packages/django/db/models/manager.py", line 87, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "/Users/kuba.jecminek/Code/django-auditlog/.tox/py39-django42/lib/python3.9/site-packages/django/db/models/query.py", line 658, in create
    obj.save(force_insert=True, using=self.db)
  File "/Users/kuba.jecminek/Code/django-auditlog/.tox/py39-django42/lib/python3.9/site-packages/django/db/models/base.py", line 814, in save
    self.save_base(
  File "/Users/kuba.jecminek/Code/django-auditlog/.tox/py39-django42/lib/python3.9/site-packages/django/db/models/base.py", line 877, in save_base
    updated = self._save_table(
  File "/Users/kuba.jecminek/Code/django-auditlog/.tox/py39-django42/lib/python3.9/site-packages/django/db/models/base.py", line 1020, in _save_table
    results = self._do_insert(
  File "/Users/kuba.jecminek/Code/django-auditlog/.tox/py39-django42/lib/python3.9/site-packages/django/db/models/base.py", line 1061, in _do_insert
    return manager._insert(
  File "/Users/kuba.jecminek/Code/django-auditlog/.tox/py39-django42/lib/python3.9/site-packages/django/db/models/manager.py", line 87, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "/Users/kuba.jecminek/Code/django-auditlog/.tox/py39-django42/lib/python3.9/site-packages/django/db/models/query.py", line 1805, in _insert
    return query.get_compiler(using=using).execute_sql(returning_fields)
  File "/Users/kuba.jecminek/Code/django-auditlog/.tox/py39-django42/lib/python3.9/site-packages/django/db/models/sql/compiler.py", line 1822, in execute_sql
    cursor.execute(sql, params)
  File "/Users/kuba.jecminek/Code/django-auditlog/.tox/py39-django42/lib/python3.9/site-packages/django/db/backends/utils.py", line 67, in execute
    return self._execute_with_wrappers(
  File "/Users/kuba.jecminek/Code/django-auditlog/.tox/py39-django42/lib/python3.9/site-packages/django/db/backends/utils.py", line 80, in _execute_with_wrappers
    return executor(sql, params, many, context)
  File "/Users/kuba.jecminek/Code/django-auditlog/.tox/py39-django42/lib/python3.9/site-packages/django/db/backends/utils.py", line 89, in _execute
    return self.cursor.execute(sql, params)
  File "/Users/kuba.jecminek/Code/django-auditlog/.tox/py39-django42/lib/python3.9/site-packages/django/db/utils.py", line 91, in __exit__
    raise dj_exc_value.with_traceback(traceback) from exc_value
  File "/Users/kuba.jecminek/Code/django-auditlog/.tox/py39-django42/lib/python3.9/site-packages/django/db/backends/utils.py", line 89, in _execute
    return self.cursor.execute(sql, params)
django.db.utils.IntegrityError: null value in column "object_pk" of relation "auditlog_logentry" violates not-null constraint
DETAIL:  Failing row contains (512, null, null, UUIDPrimaryKeyModel object (None), 1, {"text": ["None", "I am strange."], "boolean": ["None", "False"]..., 2025-03-18 16:45:42.081858+00, null, 11, null, null, null, null, , null, null).

Also, please add an entry to changelog file.

Will do!

@hramezani
Copy link
Member

Thanks @kubajecminek

@hramezani hramezani merged commit 4c1d573 into jazzband:master Mar 19, 2025
8 checks passed
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

Successfully merging this pull request may close these issues.

2 participants