#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 django-updates+unsubscr...@googlegroups.com. 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.