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
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.
deepcopyseems to work fine in >=2.0 but we haven’t done too much testing yet.
Test (placed in
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)
which I executed via the following:
python3.6 tests/runtests.py --parallel 1 model_fields