0

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.

1 Answer 1

0

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.

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

5 Comments

Thank you for addressing my question, but I've already attempted that approach. However, the output of year_record still displays the ID of my foreign key. Now, I suspect the issue lies with the DBMS I'm using, XAMPP Apache. In my Django admin UI, the column name is year_record, but in my DBMS, it appears as year_record_id. Do you think this discrepancy might be the reason why the output is displaying the ID?
No, this is normal and is how django implements fk relationships (docs). You are telling ForeignKeyWidget to ignore that and use the year_recorded field instead. The best way to identify your issue would be to step through with debugger.
what version of django-import-export are you using? try latest v4.0.3. Use resource_classes instead of resource_class.
Thank you very much, this solved my problem. I've been stuck on this for 2 days. You saved me, man. You were right, I suspected that the resource.py wasn't being read in my admin because the problem was only with resource_classes. I wasn't aware that I needed to add 'es' in the new version.
No problem, glad it's working. We have hit this issue recently. I'll update the release notes to clarify.

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.