diff options
author | Matthijs Kooijman <matthijs@stdin.nl> | 2019-12-02 00:50:59 +0100 |
---|---|---|
committer | Mariusz Felisiak <felisiak.mariusz@gmail.com> | 2020-04-07 20:41:59 +0200 |
commit | 4f216e4f8ea9bac61948cb63066cd4747f6d05fb (patch) | |
tree | 4cdceb3137fd8ef24321e692fb7abc04be5efa43 /tests/fixtures | |
parent | 590957a0eb9a87a6f2bd3463226b0a7f1405d817 (diff) | |
download | django-4f216e4f8ea9bac61948cb63066cd4747f6d05fb.tar.gz |
Fixed #31051 -- Allowed dumpdata to handle circular references in natural keys.
Since #26291 forward references in natural keys are properly handled by
loaddata, so sorting depenencies in dumpdata doesn't need to break on
cycles. This patch allows circular references in natural keys by
breaking sort_depenencies() on loops.
Diffstat (limited to 'tests/fixtures')
-rw-r--r-- | tests/fixtures/fixtures/circular_reference_natural_key.json | 16 | ||||
-rw-r--r-- | tests/fixtures/models.py | 21 | ||||
-rw-r--r-- | tests/fixtures/tests.py | 20 |
3 files changed, 52 insertions, 5 deletions
diff --git a/tests/fixtures/fixtures/circular_reference_natural_key.json b/tests/fixtures/fixtures/circular_reference_natural_key.json new file mode 100644 index 0000000000..d9dbe30aac --- /dev/null +++ b/tests/fixtures/fixtures/circular_reference_natural_key.json @@ -0,0 +1,16 @@ +[ + { + "model": "fixtures.circulara", + "fields": { + "key": "x", + "obj": ["y"] + } + }, + { + "model": "fixtures.circularb", + "fields": { + "key": "y", + "obj": ["x"] + } + } +] diff --git a/tests/fixtures/models.py b/tests/fixtures/models.py index db7d7fbd7a..ac64e7b82e 100644 --- a/tests/fixtures/models.py +++ b/tests/fixtures/models.py @@ -118,16 +118,17 @@ class PrimaryKeyUUIDModel(models.Model): id = models.UUIDField(primary_key=True, default=uuid.uuid4) +class NaturalKeyManager(models.Manager): + def get_by_natural_key(self, key): + return self.get(key=key) + + class NaturalKeyThing(models.Model): key = models.CharField(max_length=100, unique=True) other_thing = models.ForeignKey('NaturalKeyThing', on_delete=models.CASCADE, null=True) other_things = models.ManyToManyField('NaturalKeyThing', related_name='thing_m2m_set') - class Manager(models.Manager): - def get_by_natural_key(self, key): - return self.get(key=key) - - objects = Manager() + objects = NaturalKeyManager() def natural_key(self): return (self.key,) @@ -140,7 +141,17 @@ class CircularA(models.Model): key = models.CharField(max_length=3, unique=True) obj = models.ForeignKey('CircularB', models.SET_NULL, null=True) + objects = NaturalKeyManager() + + def natural_key(self): + return (self.key,) + class CircularB(models.Model): key = models.CharField(max_length=3, unique=True) obj = models.ForeignKey('CircularA', models.SET_NULL, null=True) + + objects = NaturalKeyManager() + + def natural_key(self): + return (self.key,) diff --git a/tests/fixtures/tests.py b/tests/fixtures/tests.py index 2ed17d57be..1e723a7b66 100644 --- a/tests/fixtures/tests.py +++ b/tests/fixtures/tests.py @@ -880,3 +880,23 @@ class CircularReferenceTests(DumpDataAssertMixin, TestCase): '{"model": "fixtures.circularb", "pk": 1, ' '"fields": {"key": "y", "obj": 1}}]', ) + + def test_circular_reference_natural_key(self): + management.call_command( + 'loaddata', + 'circular_reference_natural_key.json', + verbosity=0, + ) + obj_a = CircularA.objects.get() + obj_b = CircularB.objects.get() + self.assertEqual(obj_a.obj, obj_b) + self.assertEqual(obj_b.obj, obj_a) + self._dumpdata_assert( + ['fixtures'], + '[{"model": "fixtures.circulara", ' + '"fields": {"key": "x", "obj": ["y"]}}, ' + '{"model": "fixtures.circularb", ' + '"fields": {"key": "y", "obj": ["x"]}}]', + natural_primary_keys=True, + natural_foreign_keys=True, + ) |