You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django import-export:自定义ForeignKeyWidget的clean方法未触发

问题分析与解决

核心原因:测试未使用自定义的LocalityResource

你在admin.py中定义了带有自定义PlaceForeignKeyWidget的LocalityResource,但测试代码里通过resources.modelresource_factory(model=Locality)()生成的是框架默认的资源类,完全没有调用你写的自定义资源,因此自定义Widget的clean方法根本不会被执行。

修复步骤

  1. 测试中导入并使用自定义资源类
    修改test.py,直接导入你定义的LocalityResource,替换工厂方法生成的默认类:

    # test.py 修正部分
    from crm.admin import LocalityResource  # 导入自定义资源类
    # 替换原初始化代码
    locality_resource = LocalityResource()
    
  2. 修正import_id_fields的语法错误
    当前代码里import_id_fields=("zip_id")实际是字符串类型,而非元组,会导致导入逻辑异常。需添加逗号确保是元组:

    # admin.py 中 LocalityResource 的 Meta 类
    class Meta:
        model = Locality
        import_id_fields = ("zip_id",)  # 加逗号明确为元组
    
  3. 优化clean方法逻辑(可选)
    自定义Widget的clean方法里,row[r'place']无需转义,可简化为:

    val = Place.objects.create(name=row['place'])
    

完整修正后的测试代码示例

# test.py
from crm.admin import LocalityResource
from crm.models import Locality
import tablib
import pytest

test_headers = [
    "place",
    "zip_id",
]

test_data = [
    "NY",
    "2494",
]
dataset = tablib.Dataset(test_data, headers=test_headers)

@pytest.mark.django_db
def test_locality_place_foreignkey():
    # Act
    locality_resource = LocalityResource()  # 使用自定义资源类
    result = locality_resource.import_data(dataset, dry_run=False)
    assert Locality.objects.count() == 1
    assert Place.objects.filter(name="NY").exists()  # 验证自动创建的Place实例

额外说明

django-import-export的modelresource_factory是快速生成默认资源类的工具,当需要自定义字段、Widget或导入逻辑时,必须直接使用自己定义的ModelResource子类,否则所有自定义配置都会被框架忽略。

内容的提问来源于stack exchange,提问作者jjk

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.01 13:12:34