Django import-export foreignkey widget never called

I've set a breakpoint in the ForeignKeyWidget, yet it is never called while testing. Some popular LLM has no clue what I'm even asking, so here's all code including the uncalled breakpoint:

#models.py
class Place(BaseModel):
    name = models.CharField(max_length=20)
class Locality(BaseModel):
    place = models.ForeignKey(Place,null=True, blank=True,on_delete=models.CASCADE)
# admin.py
class PlaceForeignKeyWidget(ForeignKeyWidget):

    def clean(self, value, row=None, **kwargs):
        breakpoint() #Why never called?
        try:
            val = super().clean(value)
        except Place.DoesNotExist:
            val = Place.objects.create(name=row[r'place'])
        return val

class LocalityResource(resources.ModelResource):

    place = fields.Field(
        attribute="place",
        column_name="place",
        widget=PlaceForeignKeyWidget(Place,"name")
    )

    class Meta:
        model = Locality
        import_id_fields=("zip_id")
# test.py
from import_export import resources
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 = resources.modelresource_factory(model=Locality)()
    result = locality_resource.import_data(dataset,dry_run=False)
    assert Locality.objects.count()

I suppose the Book,Author Example from the docs might work as well for that problem

modelresource_factory(model=Locality) creates a brand-new autogenerated resource class based only on the model, so it ignores your custom place field/widget entirely. That generated resource uses the default ForeignKeyWidget, not PlaceForeignKeyWidget. This is why clean() never runs.

Use your actual resource class instead:

@pytest.mark.django_db
def test_locality_place_foreignkey():
    locality_resource = LocalityResource()
    result = locality_resource.import_data(dataset, dry_run=False)

    assert Locality.objects.count() == 1

Also make sure Place.name is unique if you're using it for FK lookup, otherwise ForeignKeyWidget can fail with multiple matches.

Your ForeignKeyWidget.clean method is not being called because resources.modelresource_factory creates a new ModelResource class dynamically, which does not include your custom place field definition and PlaceForeignKeyWidget from LocalityResource.

To fix this, use your explicitly defined LocalityResource class in your test:

# test.py
from crm.admin import LocalityResource # Assuming admin.py is importable

@pytest.mark.django_db
def test_locality_place_foreignkey():
    # Act
    locality_resource = LocalityResource() # Use your custom resource directly
    result = locality_resource.import_data(dataset, dry_run=False)
    assert Locality.objects.count()
Вернуться на верх