Reputation: 154
I'm having trouble loading an external data fixture for a model that uses a ContentType
foreign key.
I'm using a manager in the models, like the docs say. Unfortunately, although the docs talk about the importance of a get_by_natural_key
method on a ContentType
foreign key, it then launches into a different example instead. I'm having trouble figuring out just what the manager would look like. My best guess is to use get_by_natural_key
again, and assign app_label
and model
lookups, but I could be way off.
# models.py
from django.db import models
from django.contrib.contenttypes.models import ContentType
from django.utils.translation import ugettext_lazy as _
class InlineTypeManager(models.Manager):
def get_by_natural_key(self, title, app_label, model):
return self.get(title=title, content_type=ContentType.objects.get_by_natural_key(app_label=content_type__name, model=content_type__id))
class InlineType(models.Model):
title = models.CharField(_("title"), max_length=255)
content_type = models.ForeignKey(ContentType, limit_choices_to={"model__in": ("Link", "Document", "Image", "Audio", "Video", "MediaSet", "Flash", "Testimonial")})
objects = InlineTypeManager()
class Meta:
ordering = ["title"]
verbose_name = _("inline type")
verbose_name_plural = _("inline types")
def __unicode__(self):
return u"%s" % (self.title)
https://docs.djangoproject.com/en/dev/topics/serialization/#natural-keys
My initial_data.json
:
[
{
"model": "inlines.inlinetype",
"pk": 1,
"fields": {
"title": "Image",
"content_type": "image"
}
}, {
"model": "inlines.inlinetype",
"pk": 2,
"fields": {
"title": "Video",
"content_type": "video"
}
}
]
When I loaddata
my JSON, I receive the error:
DeserializationError: [u"'image' value must be an integer."]
The point of get_by_natural_key
is to load non-integer fields in a "human-friendly" lookup because hard-coded IDs in the JSON is a bad idea because of its unpredictability, so I'm guessing my manager is failing. Or should I use get_for_model()
/get_for_models()
?
Upvotes: 1
Views: 2950
Reputation: 23871
natural key in Django is
The default serialization strategy for foreign keys and many-to-many relations is to serialize the value of the primary key(s) of the objects in the relation.
You don't need to implement methods such as natural_key and get_by_natural_key in Manager for those models which do not occur as ForeignKey/ManyToManyField in targets to dump. So you could remove InlineTypeManager() lines.
Also, the values of content_type field inside dumped initial_data.json are incorrect. Django only treats a list as natural key, a string like "image" is still treated as surrogate key and will fail because it cannot be coerced to int successfully. Correct ContentType dump looks like
from django.contrib.contenttypes.models import ContentType
from django.utils import simplejson
>>> simplejson.dumps(ContentType.objects.get(model='user').natural_key())
'["auth", "user"]'
Upvotes: 1