[Django] #34401: Inconsistent behavior for refresh_from_db() with GenericForeignKey

1 view
Skip to first unread message

Django

unread,
Mar 10, 2023, 9:30:16 AM3/10/23
to django-...@googlegroups.com
#34401: Inconsistent behavior for refresh_from_db() with GenericForeignKey
------------------------------------------------+------------------------
Reporter: François Dupayrat | Owner: nobody
Type: Bug | Status: new
Component: contrib.contenttypes | Version: 4.1
Severity: Normal | Keywords:
Triage Stage: Unreviewed | Has patch: 0
Needs documentation: 0 | Needs tests: 0
Patch needs improvement: 0 | Easy pickings: 0
UI/UX: 0 |
------------------------------------------------+------------------------
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.

--
Ticket URL: <https://code.djangoproject.com/ticket/34401>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

Django

unread,
Mar 10, 2023, 9:32:30 AM3/10/23
to django-...@googlegroups.com
#34401: Inconsistent behavior for refresh_from_db() with GenericForeignKey
-------------------------------------+-------------------------------------

Reporter: François Dupayrat | Owner: nobody
Type: Bug | Status: new
Component: | Version: 4.1
contrib.contenttypes |
Severity: Normal | Resolution:

Keywords: | Triage Stage:
| Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Description changed by François Dupayrat:

Old description:

> class FirstType(models.Model):
> pass
>

> class SecondType(models.Model):
> pass
>

New description:


class FirstType(models.Model):
pass


class SecondType(models.Model):
pass


class FirstOrSecond(models.Model):

tests.py:

--

--
Ticket URL: <https://code.djangoproject.com/ticket/34401#comment:1>

Django

unread,
Mar 12, 2023, 12:07:55 PM3/12/23
to django-...@googlegroups.com
#34401: Inconsistent behavior for refresh_from_db() with GenericForeignKey
-------------------------------------+-------------------------------------
Reporter: François Dupayrat | Owner: nobody
Type: Bug | Status: new
Component: | Version: 4.1
contrib.contenttypes |
Severity: Normal | Resolution:
Keywords: | Triage Stage:
| Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------

Comment (by Sarah Boyce):

Hello François, have you seen #34137 ?
This was closed a few months ago and so if you test against the main
branch or the 4.2 beta release, I think this might be fixed. 🎉
I personally couldn't replicate this, but I could be missing something.

--
Ticket URL: <https://code.djangoproject.com/ticket/34401#comment:2>

Django

unread,
Mar 12, 2023, 3:02:32 PM3/12/23
to django-...@googlegroups.com
#34401: Inconsistent behavior for refresh_from_db() with GenericForeignKey
-------------------------------------+-------------------------------------
Reporter: François Dupayrat | Owner: nobody
Type: Bug | Status: closed
Component: | Version: 4.1
contrib.contenttypes |
Severity: Normal | Resolution: duplicate

Keywords: | Triage Stage:
| Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Mariusz Felisiak):

* status: new => closed
* resolution: => duplicate


Comment:

Thanks Sarah, good catch!

Duplicate of #34137

--
Ticket URL: <https://code.djangoproject.com/ticket/34401#comment:3>

Django

unread,
Mar 13, 2023, 4:42:01 AM3/13/23
to django-...@googlegroups.com
#34401: Inconsistent behavior for refresh_from_db() with GenericForeignKey
-------------------------------------+-------------------------------------
Reporter: François Dupayrat | Owner: nobody
Type: Bug | Status: closed
Component: | Version: 4.1
contrib.contenttypes |
Severity: Normal | Resolution: duplicate
Keywords: | Triage Stage:
| Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------

Comment (by François Dupayrat):

Hello Sarah, thanks for the quick reply.
I did not see that ticket before opening a new one.
I tried the patch in that ticket, and it does fix the issue in my project.

--
Ticket URL: <https://code.djangoproject.com/ticket/34401#comment:4>

Reply all
Reply to author
Forward
0 new messages