loaddata not looking for natural keys

272 views
Skip to first unread message

bobhaugen

unread,
Mar 22, 2014, 3:33:44 PM3/22/14
to django...@googlegroups.com
loaddata error message:
File "/home/bob/.virtualenvs/vn2/lib/python2.6/site-packages/django/core/serializers/json.py", line 47, in Deserializer
    raise DeserializationError(e)
DeserializationError: [u"'Cash Contribution' value must be an integer."]

Here's how I dumped the data:
./manage.py dumpdata valueaccounting.AgentType  valueaccounting.Facet valueaccounting.FacetValue valueaccounting.ProcessPattern valueaccounting.PatternFacetValue  valueaccounting.Project --natural --indent=4 > starters.json

Then I did syncdb and migrate.

Then I tried loaddata:
./manage.py loaddata starters.json

Here's the offending json:

    {
        "pk": 22, 
        "model": "valueaccounting.patternfacetvalue", 
        "fields": {
            "facet_value": 4, 
            "pattern": 9, 
            "event_type": "Cash Contribution"
        }
    }, 

Here's the relevant natural key code:

class EventTypeManager(models.Manager):

    def get_by_natural_key(self, name):
        return self.get(name=name)

class EventType(models.Model):
[...]
    objects = EventTypeManager()

    def natural_key(self):
        return (self.name)

So what am I missing?  (I put a pdb trace in the get_by_natural_key method, never got called.) 

I am stumped. But I expect it is some stupid mistake that I can't see...

bobhaugen

unread,
Mar 22, 2014, 3:39:12 PM3/22/14
to django...@googlegroups.com
Oh, and I am using Django 1.4.5.

bobhaugen

unread,
Mar 23, 2014, 8:11:26 AM3/23/14
to django...@googlegroups.com
Ok, now I am really confused.

Here's the code where the error originates in django/core/serializers/python.py:

           # Handle FK fields
            elif field.rel and isinstance(field.rel, models.ManyToOneRel):
                if field_value is not None:
                    import pdb; pdb.set_trace()
                    if hasattr(field.rel.to._default_manager, 'get_by_natural_key'):
                        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
                    else:
                        data[field.attname] = field.rel.to._meta.get_field(field.rel.field_name).to_python(field_value)
                else:
                    data[field.attname] = None



Here's what pdb says:
(Pdb) p field
<django.db.models.fields.related.ForeignKey: event_type>
(Pdb) p field_value
u'Cash Contribution'
(Pdb) p hasattr(field.rel.to._default_manager, 'get_by_natural_key')
True
(Pdb) n
> /home/bob/.virtualenvs/vn2/lib/python2.6/site-packages/django/core/serializers/python.py(109)Deserializer()
-> if hasattr(field_value, '__iter__'):
(Pdb) p hasattr(field_value, '__iter__')
False
(Pdb) p field_value
u'Cash Contribution'
(Pdb) p type(field_value)
<type 'unicode'>
(Pdb) n
> /home/bob/.virtualenvs/vn2/lib/python2.6/site-packages/django/core/serializers/python.py(117)Deserializer()
-> value = field.rel.to._meta.get_field(field.rel.field_name).to_python(field_value)
(Pdb) n
ValidationError: Validati...teger."])
> /home/bob/.virtualenvs/vn2/lib/python2.6/site-packages/django/core/serializers/python.py(117)Deserializer()
-> value = field.rel.to._meta.get_field(field.rel.field_name).to_python(field_value)

I thought unicode fields had iterators? But here's one in ipython:

In [15]: field_value = u'Cash Contribution'

In [16]: field_value.__iter__()
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)

/home/bob/.virtualenvs/vn2/valuenetwork/<ipython console> in <module>()

AttributeError: 'unicode' object has no attribute '__iter__'






bobhaugen

unread,
Mar 24, 2014, 9:38:52 AM3/24/14
to django...@googlegroups.com
Got a clue. I re-read the doc and it says the natural  key value must be a tuple.  Missed that before.

So I changed it like this:
    def natural_key(self):
        return (self.name,)

In the shell, that properly returns a tuple:
(u'Cash Contribution',)

But in the dumpdata results, it is not a tuple:
    {
        "pk": 22, 
        "model": "valueaccounting.patternfacetvalue", 
        "fields": {
            "facet_value": 4, 
            "pattern": 9, 
            "event_type": [
                "Cash Contribution"
            ]
        }
    }, 

So I am still missing something.

bobhaugen

unread,
Mar 24, 2014, 9:47:38 AM3/24/14
to django...@googlegroups.com
Not a tuple, it's now a json array. (Still not seeing things accurately...)

So I would think it would deserialize with __iter__, but I still get the same deserialization error message.

bobhaugen

unread,
Mar 24, 2014, 9:50:49 AM3/24/14
to django...@googlegroups.com
Ok, problem resolved.

I must have done something else wrong the last time I did loaddata, because I tried the whole sequence again with the natural_keys as tuples, and it all worked.

Sorry to bother the list so much.

But to summarize, natural_keys must be tuples, not single unicode values.
Reply all
Reply to author
Forward
0 new messages