jazzband / jazzband/django-model-utils

FieldTracker not accessable during __init__()

Open
#640 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
Python
Stars
2.8k
Forks
375
PR merge metrics
No merged PRs in 30d

Description

We run into strange error when updating out `django-model-utils` to >= 4.5.1. I could reproduce this error with `django-model-utils` 4.5.1 and 5.0.0

The error stated like that during:

```python

Traceback (most recent call last):
File "", line 1, in
File "/home/user/tmp/tmp/.venv/lib/python3.12/site-packages/model_utils/tracker.py", line 402, in inner
original(instance, *args, **kwargs)
File "/home/user/tmp/tmp/proj/app/models.py", line 11, in __init__
print(self.tracker)
^^^^^^^^^^^^
File "/home/user/tmp/tmp/.venv/lib/python3.12/site-packages/model_utils/tracker.py", line 442, in __get__
return getattr(instance, self.attname)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'TestModel' object has no attribute '_tracker'. Did you mean: 'tracker'?

```

Our model accesses the tracker during `__init__` to verify it is setup correctly, since the Tracker is defined in an abstract class.

After some investigation I found out, that you can not access the tracker during `__init__`, since it seems relay on data generated by Django's `contribute_to_class`, but it gets a little nebulous for me there at this point.

I have compiled a minimal Model zu reproduce the error. It can be used in a new django project to reproduce the error:

```python3
from django.db import models
from model_utils import FieldTracker

class TestModel(models.Model):
comment = models.CharField()
tracker = FieldTracker()

# When removing this everything is fine
def __init__(self, *args, **kwargs):
print(self.tracker)
```

```bash
[user@host ] ~/tmp/tmp/proj$ poetry run python3 manage.py shell
7 objects imported automatically (use -v 2 for details).

Python 3.12.3 (main, Feb 4 2025, 14:48:35) [GCC 13.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from app.models import TestModel
>>> x=TestModel()
Traceback (most recent call last):
File "", line 1, in
File "/home/sob/tmp/tmp/.venv/lib/python3.12/site-packages/model_utils/tracker.py", line 402, in inner
original(instance, *args, **kwargs)
File "/home/sob/tmp/tmp/proj/app/models.py", line 11, in __init__
print(self.tracker)
^^^^^^^^^^^^
File "/home/sob/tmp/tmp/.venv/lib/python3.12/site-packages/model_utils/tracker.py", line 442, in __get__
return getattr(instance, self.attname)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'TestModel' object has no attribute '_tracker'. Did you mean: 'tracker'?
>>>
```

Our current workaround is to check the tracker in `__new__()`, but this is not obvious and may not match any usecase.

I understand that the `FieldTracker` do some tricky stuff to achieve its feature. When a fix is not possible a hint in the documentation may be a good starting point.

Contributor guide

Open the contributing guide

Research direction

Start with the minimal TestModel in app/models.py and reproduce the failure while reading the FieldTracker behavior shown in model_utils/tracker.py. Determine whether tracker access during __init__ should be supported or documented as unavailable. Done means the behavior is corrected or clearly documented, with coverage for the reported initialization case if a fix is made.

Written by the indexing model from the issue text.

Assessment

Tech stack
django, python
Domain
backend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.