#33984: Related managers cache gets stale after saving a fetched model with new
PK
-------------------------------------+-------------------------------------
Reporter: joeli | Owner: Mariusz
| Felisiak
Type: Bug | Status: closed
Component: Database layer | Version: 4.1
(models, ORM) |
Severity: Release blocker | Resolution: fixed
Keywords: | Triage Stage: Accepted
Has patch: 1 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Comment (by Steven Mapes):
Is this why model forms now, since Django 4.1.0 raise ValueErrors if you
try access Related Managers within the __init__ even if you check for the
the instance being set along with the relationship?
I.E If you have models and a Model form like this
{{{
# models.py
from django.db import models
class Tag(models.Model):
tag = models.SlugField(max_length=64, unique=True)
class Thing(models.Model):
tag = models.ForeignKey(Tag, on_delete=models.CASCADE,
related_name="things")
active = models.BooleanField(default=True)
}}}
{{{
# forms.py
from django import forms
from example.models import Tag
class TagForm(forms.ModelForm):
class Meta:
model = Tag
fields = ["tag"]
def __init__(self, *args, **kwargs):
super(TagForm, self).__init__(*args, **kwargs)
if self.instance and self.instance.things:
inactive_things = self.instance.things.filter(active=False)
# Do something with it
}}}
Then have the following test
{{{
from unittest.case import TestCase
from example.forms import TagForm
class TagFormCase(TestCase):
def test_required(self):
"""Test required fields"""
form = TagForm({})
self.assertFalse(form.is_valid())
self.assertEqual(
{
"tag": ["This field is required."],
},
form.errors,
)
}}}
The test would pass in all Django versions up to 4.1. From 4.1.0 onwards
it raises a ValueError of ```ValueError: 'Tag' instance needs to have a
primary key value before this relationship can be used.```
In order for the test to pass you need to change the flow control to ```if
self.instance.pk and self.instance.things```. You can't use
```self.instance.things.count()``` as it raises the exception.
However if you overload the primary key on the model to use a UUID such
as:
{{{
# models.py
import uuid
from django.db import models
class Tag(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4,
editable=False)
tag = models.SlugField(max_length=64, unique=True)
class Thing(models.Model):
tag = models.ForeignKey(Tag, on_delete=models.CASCADE,
related_name="things")
active = models.BooleanField(default=True)
}}}
then the original test will pass as the uuid will be set prior to saving
--
Ticket URL: <https://code.djangoproject.com/ticket/33984#comment:18>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
--
You received this message because you are subscribed to the Google Groups
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/django-updates/01070183c65cce99-7ad7a312-165a-4542-b4d4-cf975cd7fb57-000000%40eu-central-1.amazonses.com.