Shane S
Shane S

Reputation: 2293

Django-import-export problem importing foreignkey field

I am using the Django-import-export(version 2.5.0) module in Django(version 3.1.4). So I am able to import all my models fields except for the ForeignKey field. I don't know how to make this one work. Can you look at my code and see what is wrong or needs to change? I need Django Admin to import the ForeignKey field.

models.py

# myapp
from django.db import models
from django.contrib.auth.models import User 

class Agency(models.Model):
    system_name = models.CharField(max_length=255)
    county = models.CharField(max_length=60)
    state = models.CharField(max_length=2)
    active = models.BooleanField(default=True)
    system_no = models.CharField(max_length=7, unique=True)
    
    def __str__(self):
        return self.system_no
    
class SitePart(models.Model):
    # I tried changing the "system_no" to another name "agency_no" through out the *.py's this did not resolve the problem. Maybe I missed something.
    system_no = models.ForeignKey('Agency', on_delete=models.CASCADE, to_field='system_no', null=True, blank=True)
    part_name = models.CharField(max_length=125) 
    status_tuple = [('AB','Abandoned'),('AC','Active Compliant'),('DS','Destroyed'),('IA','Inactive'),
            ('SB','Stand By waiting acitvation'),('MO','Monitoring')]
    status = models.CharField(max_length=2, choices=status_tuple, default= 'SB')
    # sys_site_n is unique
    sys_site_n = models.CharField(max_length=15, unique=True)

    def __str__(self):
        return self.part_name

resources.py

from import_export import fields, resources, widgets
from import_export.widgets import ForeignKeyWidget
from myapp.models import Agency, SitePart
 
class AgencyResource(resources.ModelResource):
    class Meta:
        model = Agency
        import_id_fields = ('system_no',)
        fields = ('system_name', 'county', 'state', 'active', 'system_no',)
        

class SitePartResource(resources.ModelResource):
    system_no = fields.Field(
        column_name='system_no',
        attribute='system_no',
        widget=ForeignKeyWidget(Agency,'system_no'))
    print(system_no)    
    
    class Meta:
        model = SitePart
        import_id_fields = ('sys_site_n',)
        fields = ('system_no','part_name','status', 'sys_site_n',)

admin.py

from django.contrib import admin
from import_export.admin import ImportExportModelAdmin
from myapp.resources import AgencyResource, SitePartResource
from myapp.models import (Agency, County, SitePart)

class AgencyAdmin(ImportExportModelAdmin):
    resource_class = AgencyResource
    list_display = ('system_name', 'county', 'state', 'active', 'system_no',)

class SitePartAdmin(ImportExportModelAdmin):
    list_display = ('system_no', 'part_name', 'status', 'sys_site_n',)
    search_fields = ['system_no',] # Tried removing this, didn't work
    resource_class = SitePartResource

admin.site.register(Agency, AgencyAdmin)
admin.site.register(County)
admin.site.register(SitePart, SitePartAdmin)

Agency Table

system_name county state active system_no
MAGNA SCHOOL INYO CA 1 1300553
PINE SCHOOL INYO CA 1 1300560

SitePart Table

system_no part_name status sys_site_n
1300553 MAGNA SCHOOL AC 1300553-01
1300553 Backup Genrtor SB 1300553-02
1300560 PINE SCHOOL AC 1300560-01
1300560 Backup Genrtor SB 1300560-02

When I do import in django admin the system_no is empty. enter image description here

Upvotes: 0

Views: 1818

Answers (1)

msf
msf

Reputation: 96

I don't have the reputation points to be able to add a comment but I think the issue you're experencing is due to your model's field naming conventions.

Since your foreign key relation inside the SitePart to Agency is called system_no, your SitePartResource's ForeignKey Widget isn't referencing the correct field - it's referencing the related Agency model instance (which I believe is why you aren't getting any errors on import but the value is not being displayed).

To fix this, you just neeed to change the ForeignKey widget to reference the related Agency object's system_no field (not the instance itself). I haven't tested it but changing your FK field to something like the following should work!

#resources.py
class SitePartResource(resources.ModelResource):
    ...

    system_no = fields.Field(
        column_name='system_no',
        attribute='system_no',
        widget=ForeignKeyWidget(
            Agency,
            field='system_no__system_no'
        )
    )
    
    ...
    

EDIT:

#resources.py
class SitePartResource(resources.ModelResource):
    class AgencyForeignKeyWiget(ForeignKeyWidget):
        def get_queryset(self, value, row):
            return self.model.objects.filter(
                system_no__exact=row["system_no"],
            )

    system_no = fields.Field(
        column_name='system_no',
        attribute='system_no',
        widget=AgencyForeignKeyWidget(
            Agency,
            field='system_no'
        )
    )
    
    part_name = fields.Field(column_name="part_name", attribute="part_name")
    status = fields.Field(column_name="part_name", attribute="part_name")
    sys_site_n = fields.Field(column_name="system_site_n", attribute="system_site_n")

    class Meta:
        model = SitePart
        import_id_fields = ("system_no", "system_site_n")
        fields = ('system_no','part_name','status', 'sys_site_n',)

Upvotes: 2

Related Questions