I am using the django-import-export library to handle data import and export in my Django application. I have several models with ForeignKey relationships, and I want to display and use the custom column values instead of the IDs in my import/export files.
# models.py
class YearCategoryMalnutrition(models.Model):
id = models.AutoField(primary_key=True)
year_recorded = models.CharField(max_length=4, default="")
last_update = models.DateTimeField(auto_now=True, null=True)
def __str__(self):
return self.year_recorded
class AgeCategory(models.Model):
AGE_CATEGORIES = (
('0-5 years old (0-60 months)', '0-5 years old (0-60 months)'),
('5.08-10.0 years old (61-120 months)', '5.08-10.0 years old (61-120 months)'),
('10.08-19.0 years old (121-228 months)', '10.08-19.0 years old (121-228 months)'),
('Adults 20 years old above', 'Adults 20 years old above'),
)
age_category_name = models.CharField(
max_length=50,
choices=AGE_CATEGORIES,
default='0-5 years old (0-60 months)',
)
last_update = models.DateTimeField(auto_now=True, null=True)
class Meta:
verbose_name_plural = "Age Categories"
def __str__(self):
return self.age_category_name
class LevelCategory(models.Model):
LEVEL_CATEGORIES = (
('National Level', 'National Level'),
('Regional Level', 'Regional Level'),
('Province Level', 'Province Level'),
('Municipality Level', 'Municipality Level'),
('Barangay Level', 'Barangay Level'),
)
level_category_name = models.CharField(
max_length=50,
choices=LEVEL_CATEGORIES,
default='National Level',
)
last_update = models.DateTimeField(auto_now=True, null=True)
class Meta:
verbose_name_plural = "Level Categories"
def __str__(self):
return self.level_category_name
class NationalLevel(models.Model):
id = models.AutoField(primary_key=True)
country_name = models.CharField(max_length=255, default="Philippines")
overweight = models.FloatField(default=0.0)
underweight = models.FloatField(default=0.0)
stunting = models.FloatField(default=0.0)
wasting = models.FloatField(default=0.0)
overweight_error = models.FloatField(default=0.0)
underweight_error = models.FloatField(default=0.0)
stunting_error = models.FloatField(default=0.0)
wasting_error = models.FloatField(default=0.0)
year_record = models.ForeignKey(YearCategoryMalnutrition, on_delete=models.PROTECT)
age_category = models.ForeignKey(AgeCategory, on_delete=models.PROTECT, null=True)
level_category = models.ForeignKey(LevelCategory, on_delete=models.PROTECT, null=True)
last_update = models.DateTimeField(auto_now=True)
# resources.py
from import_export import resources, fields
from import_export.widgets import ForeignKeyWidget
from .models import NationalLevel, YearCategoryMalnutrition, AgeCategory, LevelCategory
class NationalLevelResource(resources.ModelResource):
year_record = fields.Field(
column_name='year_record',
attribute='year_record',
widget=ForeignKeyWidget(YearCategoryMalnutrition, 'year_recorded')
)
age_category = fields.Field(
column_name='age_category',
attribute='age_category',
widget=ForeignKeyWidget(AgeCategory, 'age_category_name')
)
level_category = fields.Field(
column_name='level_category',
attribute='level_category',
widget=ForeignKeyWidget(LevelCategory, 'level_category_name')
)
class Meta:
model = NationalLevel
fields = ('country_name', 'overweight', 'underweight', 'stunting',
'wasting', 'overweight_error', 'underweight_error', 'stunting_error',
'wasting_error', 'year_record__year_recorded', 'age_category', 'level_category', 'last_update')
export_order = ('country_name', 'overweight', 'underweight', 'stunting',
'wasting', 'overweight_error', 'underweight_error', 'stunting_error',
'wasting_error', 'year_record', 'age_category', 'level_category', 'last_update')
# admin.py
from django.contrib import admin
from import_export.admin import ImportExportModelAdmin
from .models import NationalLevel
from .resources import NationalLevelResource
class NationalLevelAdmin(ImportExportModelAdmin):
list_display = (
'id',
'country_name',
'overweight',
'underweight',
'stunting',
'wasting',
'overweight_error',
'underweight_error',
'stunting_error',
'wasting_error',
'year_record',
'age_category',
'level_category',
'last_update',
)
ordering = ('year_record',)
list_filter = ('year_record', 'age_category', 'level_category')
search_fields = ('country_name',)
list_per_page = 25
resource_class = NationalLevelResource
When I export data, I want to show the value instead of the ID. Additionally, when I import data, I want to accept the value instead of the ID for my year_record.
This section looks to me like it is declared correctly:
class NationalLevelResource(resources.ModelResource):
year_record = fields.Field(
column_name='year_record',
attribute='year_record',
widget=ForeignKeyWidget(YearCategoryMalnutrition, 'year_recorded')
)
You are correctly defining the FK relationship and using 'year_recorded' as the lookup value. It is assumed that year_recorded
can uniquely identify the FK record (Docs).
I think the issue is that you have declared year_record__year_recorded
in your fields
list. Try changing this to year_record
, and see if that helps.