3

I'm using django-import-export to load csv files in a migration file which I understand is current best practise for Django 1.7 to load initial data. This worked fine for the first file:

class Country(models.Model):

    ISO2 = models.CharField(max_length=2, primary_key=True)
    name = models.CharField(max_length=50, unique=True)

and the entire migration file contents. note that ISO2 is the primary key so required the addition line import_id_fields = ['ISO2']. Code adapted from answer to this question: Loading initial data with Django 1.7 and data migrations:

from django.conf import settings
import tablib
from import_export import resources
from web.models import Country
import os
import csv

# load initial data - assume it is all in web/fixtures directory

class CountryResource(resources.ModelResource):

    class Meta:
         model = Country
         import_id_fields = ['ISO2']

fixture_dir = os.path.abspath(os.path.join(settings.PROJECT_ROOT, 'web/fixtures'))
fixture_filename = 'web_country.csv'

def load_fixture(apps, schema_editor):
    fixture_file = os.path.join(fixture_dir, fixture_filename)

    with open(fixture_file, 'r') as content_file:
        content = content_file.read()

    resource = CountryResource()

    data = tablib.Dataset()
    data.csv = content


    result = resource.import_data(data,  dry_run=False,
                                 raise_errors=True)

def unload_fixture(apps, schema_editor):
    "Brutally deleting all entries for this model..."

    country = apps.get_model("web", "Country")
    country.objects.all().delete()

class Migration(migrations.Migration):

    dependencies = [
        ('web', '0001_initial'),
    ]

    operations = [
        migrations.RunPython(load_fixture, reverse_code=unload_fixture),
    ]

Now for the next file which has a primary key relationship to that one:

class CountryFootprint(models.Model):
    ISO2 = models.ForeignKey(Country)
    footprint = models.DecimalField(max_digits=18,  decimal_places=6)

and a subset of the migration file, with my attempt to link up the foreign key:

class CountryFootprintResource(resources.ModelResource):

    ISO2_id = fields.Field( widget=widgets.ForeignKeyWidget(Country, 'ISO2'))

    class Meta:
         model = CountryFootprint

This give me:

  django.db.models.fields.related.RelatedObjectDoesNotExist: CountryFootprint has no ISO2.

Also tried:

  ISO2_id = fields.Field(column_name='ISO2_id', attribute='ISO2', widget=widgets.ForeignKeyWidget(Country, 'ISO2'))


  File "/Users/phoebebr/Development/gmd/web/migrations/0003_auto_20141220_1931.py", line 43, in load_fixture
    raise_errors=True)
  File "/Users/phoebebr/.virtualenvs/gmd/lib/python2.7/site-packages/import_export/resources.py", line 359, in import_data
    six.reraise(*sys.exc_info())
  File "/Users/phoebebr/.virtualenvs/gmd/lib/python2.7/site-packages/import_export/resources.py", line 348, in import_data
    row_result.object_repr = force_text(instance)
  File "/Users/phoebebr/.virtualenvs/gmd/lib/python2.7/site-packages/django/utils/encoding.py", line 85, in force_text
    s = six.text_type(s)
TypeError: coercing to Unicode: need string or buffer, Country found

I've read the documentation and I'm sure the answer is there but it's just not jumping out at me!

3
  • just specifying fields = ('ISO2') in the Meta class of CountryFootprintResource doens't work? Commented Dec 20, 2014 at 20:56
  • Tried that, TypeError: coercing to Unicode: need string or buffer, Country found again. Strange, you would think Country would be correct and it's looking for a string. Commented Dec 20, 2014 at 22:45
  • Thanks for the nudge DRC, got there in the end. Commented Dec 21, 2014 at 10:05

1 Answer 1

5

Either of these two lines work:

ISO2_id = fields.Field( widget=widgets.ForeignKeyWidget(Country, 'ISO2'))

or

ISO2_id = fields.Field(column_name='ISO2_id', attribute='ISO2', widget=widgets.ForeignKeyWidget(Country, 'ISO2'))

using just:

fields = ('ISO2', 'footprint')

gives error

django.db.models.fields.related.RelatedObjectDoesNotExist: CountryFootprint has no ISO2.

The coercing to Unicode error was caused by my not having a string returned from the unicode def:

def __unicode__(self):
    return self.ISO2

should have been

def __unicode__(self):
    return self.ISO2.name

so many coding problems solved by a good nights sleep!

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.