问题
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!
回答1:
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