Django-import-export 导入外键字段的问题

问题描述

我在 Django(版本 3.1.4)中使用 Django-import-export(版本 2.5.0)模块。所以我可以导入除 ForeignKey 字段之外的所有模型字段。我不知道如何使这个工作。你能看看我的代码,看看有什么问题或需要改变吗?我需要 Django Admin 来导入 ForeignKey 字段。

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',)

class SitePartAdmin(ImportExportModelAdmin):
    list_display = ('system_no',)
    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)

代理表

系统名称 状态 活跃 system_no
麦格纳学校 INYO CA 1 1300553
松树学校 INYO CA 1 1300560

SitePart 表

system_no part_name 状态 sys_site_n
1300553 麦格纳学校 交流 1300553-01
1300553 备份生成 SB 1300553-02
1300560 松树学校 交流 1300560-01
1300560 备份生成 SB 1300560-02

当我在 django admin 中导入时,system_no 为空。

enter image description here

解决方法

我没有能够添加评论的声誉点,但我认为您遇到的问题是由于模型的字段命名约定造成的。

由于 SitePartAgency 内的外键关系称为 system_no,因此您的 SitePartResource 的 ForeignKey 小部件没有引用正确的字段 - 它引用了相关的 Agency 模型实例(我相信这就是您在导入时没有收到任何错误但未显示值的原因)。

要解决此问题,您只需更改 ForeignKey 小部件以引用相关代理对象的 system_no 字段(而不是实例本身)。我还没有测试过,但将您的 FK 字段更改为如下所示应该可以工作!

#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'
        )
    )
    
    ...
    

编辑:

#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',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',)