Skip to content

please document how to deserialize by natural key #517

@johncronan

Description

@johncronan

I've created a minimal recreation to verify that this works in Django normally, with model inheritance. You can have a demo/models.py like this:

class FooManager(models.Manager):
    def get_by_natural_key(self, slug):
        return self.get(slug=slug)

class Foo(models.Model):
    slug = models.SlugField(unique=True)
    content = models.CharField(blank=True, max_length=100)
    
    objects = FooManager()
    
    def natural_key(self):
        return (self.slug,)


class Bar(Foo):
    foo = models.OneToOneField(Foo, models.CASCADE, parent_link=True, primary_key=True)
    val = models.IntegerField(default=0)
    
    def natural_key(self):
        return self.foo.natural_key()
    natural_key.dependencies = ['demo.foo']

And then when you create a bar instance: Bar(slug='baz', val=1).save()
We can dump that with ./manage.py dumpdata --natural-primary --natural-foreign demo > dump.json and get a file that works when we run loaddata on it.

Additionally, let's say we want to copy these values, but in a new instance, so run: sed s/baz/qux/g < dump.json > new.json

Then, running loaddata new.json there will be two bar instances, baz and qux. Also, two instances of the base object.

But, repeating the same process, but with Foo changed to a PolymorphicModel and FooManager changed to a PolymorphicManager, I find that the first part, reloading instances that are already in the database, works, while in the second part I get the following error:

Traceback (most recent call last):
  File "...site-packages/django/core/serializers/json.py", line 70, in Deserializer
    yield from PythonDeserializer(objects, **options)
  File "...site-packages/django/core/serializers/python.py", line 174, in Deserializer
    obj = base.build_instance(Model, data, using)
  File "...site-packages/django/core/serializers/base.py", line 332, in build_instance
    natural_key = Model(**data).natural_key()
  File "test/jkc/demo/models.py", line 45, in natural_key
    return self.foo.natural_key()
  File "...site-packages/polymorphic/models.py", line 203, in accessor_function
    attr = objects.get(pk=self.pk)
  File "...site-packages/django/db/models/manager.py", line 85, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "...site-packages/django/db/models/query.py", line 496, in get
    raise self.model.DoesNotExist(
demo.models.DoesNotExist: Foo matching query does not exist.

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "test/jkc/./manage.py", line 22, in <module>
    main()
[... management command stuff]

Any idea why that would occur? Thanks for looking at this.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions