#31863: FK field caching behavior change between 1.11.x and 2.x
-------------------------------------+-------------------------------------
               Reporter:  Gert       |          Owner:  Gert Burger
  Burger                             |
                   Type:  Bug        |         Status:  assigned
              Component:  Database   |        Version:  3.1
  layer (models, ORM)                |
               Severity:  Normal     |       Keywords:
           Triage Stage:             |      Has patch:  0
  Unreviewed                         |
    Needs documentation:  0          |    Needs tests:  0
Patch needs improvement:  0          |  Easy pickings:  0
                  UI/UX:  0          |
-------------------------------------+-------------------------------------
 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):

 {{{#!python

 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.

-- 
Ticket URL: <https://code.djangoproject.com/ticket/31863>
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 [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/053.5dc81ec4add29cc41b01ba8f8fcacc74%40djangoproject.com.

Reply via email to