#31863 closed Bug (fixed)
FK field caching behavior change between 1.11.x and 2.x
Reported by: | Gert Burger | Owned by: | Gert Burger |
---|---|---|---|
Component: | Database layer (models, ORM) | Version: | 2.2 |
Severity: | Normal | Keywords: | |
Cc: | Triage Stage: | Ready for checkin | |
Has patch: | yes | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
Whilst upgrading a codebase from 1.11.x to 2.0/2.2 I noticed a weird change in behavior of FK fields when copying model instances.
At the bottom of the post there is a testcase that succeeds on 1.11.x and fails on 2.x
I think the commit that changed the behavior is bfb746f983aa741afa3709794e70f1e0ab6040b5
So my question is two fold:
- Is the behavior in >=2.0 correct? It seems quite unexpected.
- What is the recommended way to clone a model instance? To date we have been using copy() in a similar fashion to the test without issue. deepcopy seems to work fine in >=2.0 but we haven’t done too much testing yet.
Test (placed in tests/model_fields/test_field_caching_change.py):
import copy from django.test import TestCase from .models import Bar, Foo class ForeignKeyCachingBehaviorTest(TestCase): def test_copy(self): foo1 = Foo.objects.create(a='foo1', d=1) foo2 = Foo.objects.create(a='foo2', d=2) bar1 = Bar.objects.create(a=foo1, b='bar1') bar2 = copy.copy(bar1) bar2.pk = None bar2.a = foo2 # bar2 points to foo2 self.assertEqual(bar2.a, foo2) self.assertEqual(bar2.a.id, bar2.a_id) # bar1 is unchanged and must still point to foo1 # These fail on Django >= 2.0 self.assertEqual(bar1.a, foo1) self.assertEqual(bar1.a.id, bar1.a_id)
and executed that via:
python3.6 tests/runtests.py --parallel 1 model_fields
In https://groups.google.com/g/django-developers/c/QMhVPIqVVP4/m/mbezfaBEAwAJ Simon suggests:
..... Model.copy should make sure to make a deep-copy of self._state now that fields are cached in self._state.fields_cache.
which I will attempt to implement.
Change History (14)
comment:1 by , 4 years ago
Triage Stage: | Unreviewed → Accepted |
---|
comment:2 by , 4 years ago
Has patch: | set |
---|
comment:3 by , 4 years ago
Patch needs improvement: | set |
---|
comment:4 by , 4 years ago
Patch needs improvement: | unset |
---|
comment:5 by , 4 years ago
Triage Stage: | Accepted → Ready for checkin |
---|
Can someone please double check the fields on the ticket and PR, not sure if I got them right.
https://github.com/django/django/pull/13281/