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!
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!
来源:https://stackoverflow.com/questions/27584076/foreign-key-in-django-migration-using-django-import-export