diff options
| author | Russell Keith-Magee <russell@keith-magee.com> | 2010-03-18 15:22:15 +0000 |
|---|---|---|
| committer | Russell Keith-Magee <russell@keith-magee.com> | 2010-03-18 15:22:15 +0000 |
| commit | 10de2a837f580d76a480a9e0b974cecd2d1d26cb (patch) | |
| tree | 7c510c636247de1a7084bf17ae87f7bf76a9c4f9 | |
| parent | be8a1f612dde1bff3dcdab05c3a916f27946dd31 (diff) | |
Fixed #13030 -- Corrected natural key deserialization to subclasses. Thanks to yishaibeeri for the report and test case.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@12804 bcc190cf-cafb-0310-a4f2-bffc1f526a37
5 files changed, 100 insertions, 1 deletions
diff --git a/django/core/serializers/python.py b/django/core/serializers/python.py index 3defb6aa27..a68ea21f78 100644 --- a/django/core/serializers/python.py +++ b/django/core/serializers/python.py @@ -111,6 +111,10 @@ def Deserializer(object_list, **options): if hasattr(field_value, '__iter__'): obj = field.rel.to._default_manager.db_manager(db).get_by_natural_key(*field_value) value = getattr(obj, field.rel.field_name) + # If this is a natural foreign key to an object that + # has a FK/O2O as the foreign key, use the FK value + if field.rel.to._meta.pk.rel: + value = value.pk else: value = field.rel.to._meta.get_field(field.rel.field_name).to_python(field_value) data[field.attname] = value diff --git a/django/core/serializers/xml_serializer.py b/django/core/serializers/xml_serializer.py index b0d8d49397..5fef3b6936 100644 --- a/django/core/serializers/xml_serializer.py +++ b/django/core/serializers/xml_serializer.py @@ -221,6 +221,10 @@ class Deserializer(base.Deserializer): field_value = [getInnerText(k).strip() for k in keys] obj = field.rel.to._default_manager.db_manager(self.db).get_by_natural_key(*field_value) obj_pk = getattr(obj, field.rel.field_name) + # If this is a natural foreign key to an object that + # has a FK/O2O as the foreign key, use the FK value + if field.rel.to._meta.pk.rel: + obj_pk = obj_pk.pk else: # Otherwise, treat like a normal PK field_value = getInnerText(node).strip() diff --git a/tests/regressiontests/fixtures_regress/fixtures/nk-inheritance.json b/tests/regressiontests/fixtures_regress/fixtures/nk-inheritance.json new file mode 100644 index 0000000000..08e5d4feee --- /dev/null +++ b/tests/regressiontests/fixtures_regress/fixtures/nk-inheritance.json @@ -0,0 +1,18 @@ +[ + { + "pk": 1, + "model": "fixtures_regress.nkchild", + "fields": { + "data": "apple" + } + }, + { + "pk": 1, + "model": "fixtures_regress.reftonkchild", + "fields": { + "text": "my text", + "nk_fk" : ["apple"], + "nk_m2m": [["apple"]] + } + } +] diff --git a/tests/regressiontests/fixtures_regress/fixtures/nk-inheritance2.xml b/tests/regressiontests/fixtures_regress/fixtures/nk-inheritance2.xml new file mode 100644 index 0000000000..7eb17a6b7e --- /dev/null +++ b/tests/regressiontests/fixtures_regress/fixtures/nk-inheritance2.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="utf-8"?> +<django-objects version="1.0"> + <object pk="2" model="fixtures_regress.parent"> + <field type="CharField" name="name">james</field> + </object> + <object pk="2" model="fixtures_regress.nkchild"> + <field type="CharField" name="data">banana</field> + </object> + <object pk="2" model="fixtures_regress.reftonkchild"> + <field type="CharField" name="text">other text</field> + <field to="fixtures_regress.nkchild" name="nk_fk" rel="ManyToOneRel"> + <natural>apple</natural> + </field> + <field to="fixtures_regress.nkchild" name="nk_m2m" rel="ManyToManyRel"> + <object> + <natural>banana</natural> + </object> + <object> + <natural>apple</natural> + </object> + </field> + </object> +</django-objects>
\ No newline at end of file diff --git a/tests/regressiontests/fixtures_regress/models.py b/tests/regressiontests/fixtures_regress/models.py index da8818cd4a..0e727c4935 100644 --- a/tests/regressiontests/fixtures_regress/models.py +++ b/tests/regressiontests/fixtures_regress/models.py @@ -52,6 +52,9 @@ class Absolute(models.Model): class Parent(models.Model): name = models.CharField(max_length=10) + class Meta: + ordering = ('id',) + class Child(Parent): data = models.CharField(max_length=10) @@ -130,6 +133,32 @@ class Book(models.Model): ', '.join(s.name for s in self.stores.all()) ) +class NKManager(models.Manager): + def get_by_natural_key(self, data): + return self.get(data=data) + +class NKChild(Parent): + data = models.CharField(max_length=10, unique=True) + objects = NKManager() + + def natural_key(self): + return self.data + + def __unicode__(self): + return u'NKChild %s:%s' % (self.name, self.data) + +class RefToNKChild(models.Model): + text = models.CharField(max_length=10) + nk_fk = models.ForeignKey(NKChild, related_name='ref_fks') + nk_m2m = models.ManyToManyField(NKChild, related_name='ref_m2ms') + + def __unicode__(self): + return u'%s: Reference to %s [%s]' % ( + self.text, + self.nk_fk, + ', '.join(str(o) for o in self.nk_m2m.all()) + ) + # ome models with pathological circular dependencies class Circle1(models.Model): name = models.CharField(max_length=255) @@ -245,6 +274,27 @@ No fixture data found for 'bad_fixture2'. (File format may be invalid.) >>> management.call_command('loaddata', 'model-inheritance.json', verbosity=0) ############################################### +# Test for ticket #13030 -- natural keys deserialize with fk to inheriting model + +# load data with natural keys +>>> management.call_command('loaddata', 'nk-inheritance.json', verbosity=0) + +>>> NKChild.objects.get(pk=1) +<NKChild: NKChild fred:apple> + +>>> RefToNKChild.objects.get(pk=1) +<RefToNKChild: my text: Reference to NKChild fred:apple [NKChild fred:apple]> + +# ... and again in XML +>>> management.call_command('loaddata', 'nk-inheritance2.xml', verbosity=0) + +>>> NKChild.objects.get(pk=2) +<NKChild: NKChild james:banana> + +>>> RefToNKChild.objects.get(pk=2) +<RefToNKChild: other text: Reference to NKChild fred:apple [NKChild fred:apple, NKChild james:banana]> + +############################################### # Test for ticket #7572 -- MySQL has a problem if the same connection is # used to create tables, load data, and then query over that data. # To compensate, we close the connection after running loaddata. @@ -279,7 +329,7 @@ Weight = 1.2 (<type 'float'>) [{"pk": 1, "model": "fixtures_regress.animal", "fields": {"count": 3, "weight": 1.2, "name": "Lion", "latin_name": "Panthera leo"}}, {"pk": 2, "model": "fixtures_regress.animal", "fields": {"count": 2, "weight": 2.2, "name": "Platypus", "latin_name": "Ornithorhynchus anatinus"}}, {"pk": 10, "model": "fixtures_regress.animal", "fields": {"count": 42, "weight": 1.2, "name": "Emu", "latin_name": "Dromaius novaehollandiae"}}] ############################################### -# Regression for #11428 - Proxy models aren't included when you dumpdata +# Regression for #11428 - Proxy models aren't included when you dumpdata # Flush out the database first >>> management.call_command('reset', 'fixtures_regress', interactive=False, verbosity=0) |
