Opened 21 months ago
Last modified 20 months ago
#34401 closed Bug
Inconsistent behavior for refresh_from_db() with GenericForeignKey — at Version 1
Reported by: | François Dupayrat | Owned by: | nobody |
---|---|---|---|
Component: | contrib.contenttypes | Version: | 4.1 |
Severity: | Normal | Keywords: | |
Cc: | Triage Stage: | Unreviewed | |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description (last modified by )
Since Django 4, refresh_from_db
exhibit an inconsistent behavior for GenericForeignKey
fields: sometime, the object field is properly refreshed, and sometime it isn't. That issue has been introduced with Django 4 and I've traced it back to this ticket: https://code.djangoproject.com/ticket/33008
and in particular those 2 lines in django/contrib/contenttypes/fields.py
:
if rel_obj is None and self.is_cached(instance): return rel_obj
With those 2 lines removed, the bug doesn't reproduce. I'm unsure if this is an acceptable solution for Django though.
Here is a minimal example to reproduce this bug.
models.py:
from django.contrib.contenttypes.fields import GenericForeignKey from django.contrib.contenttypes.models import ContentType from django.db import models class FirstType(models.Model): pass class SecondType(models.Model): pass class FirstOrSecond(models.Model): association_type = models.ForeignKey(ContentType, blank=True, null=True, on_delete=models.SET_NULL, limit_choices_to=( models.Q(app_label='generic_foreign_key_type', model='firsttype') | models.Q(app_label='generic_foreign_key_type', model='secondtype') )) associated_to_id = models.PositiveIntegerField(blank=True, null=True, db_index=True) associated_to = GenericForeignKey('association_type', 'associated_to_id') def change_association_to(obj_id, target): matching_obj = FirstOrSecond.objects.filter(id=obj_id).first() if matching_obj: matching_obj.associated_to = target matching_obj.save()
tests.py:
from django.test import TestCase from .models import * class GenericForeignKeysTests(TestCase): def setUp(self): self.first_or_second = FirstOrSecond.objects.create() self.first = FirstType.objects.create() self.second = SecondType.objects.create() def test_refresh_from_db(self): change_association_to(self.first_or_second.id, self.first) self.first_or_second.refresh_from_db() self.assertEqual(self.first_or_second.associated_to, self.first) change_association_to(self.first_or_second.id, None) self.first_or_second.refresh_from_db() self.assertEqual(self.first_or_second.associated_to, None) change_association_to(self.first_or_second.id, self.first) self.first_or_second.refresh_from_db() self.assertEqual(self.first_or_second.associated_to, self.first)
The last assertion fails because of this bug.