Extensions
This package is simply an extension of the original django-import-export
, so if you want
to know more about the import/export process and advanced resource utilization, you should refer to
the official django-import-export documentation.
This section describes the features that are added by this package.
ImportJob/ExportJob models
The django-import-export-extensions
provides ImportJob
and ExportJob
models to store all the information
about the import/export process. In addition, these models participate in the background import/export process.
Job models are already registered in Django Admin and have custom forms that allow to show all current job information including import/export status.
ImportJob
/ExportJob
models contain useful properties and methods for managing
the import/export process. To learn more, see the Models API documentation.
Celery admin mixins
The mixins for admin models have been rewritten completely, although they inherit from the base mixins
mixins.BaseImportMixin
, mixins.BaseExportMixin
and admin.ImportExportMixinBase
.
The new celery admin mixins add new pages to display import/export status, and use custom
templates for the status and results pages.
Now after starting the import/export, you will first be redirected to the status page and then, after the import/export is complete, to the results page.
ViewSets
There are ImportJobViewSet
and ExportJobViewSet
view sets that make it easy
to implement import/export via API. Just create custom class with resource_class
attribute:
api/views.py
from import_export_extensions.api import views as import_export_views
from . import resources
class BandImportViewSet(import_export_views.ImportJobViewSet):
resource_class = resources.BandResource
class BandExportViewSet(import_export_views.ExportJobViewSet):
resource_class = resources.BandResource
urls.py
from rest_framework.routers import DefaultRouter
from .api import views
band_import_export_router = DefaultRouter()
band_import_export_router.register(
"import-band",
views.BandImportViewSet,
basename="import-band",
)
band_import_export_router.register(
"export-band",
views.BandExportViewSet,
basename="export-band",
)
urlpatterns = band_import_export_router.urls
By default, all import/export jobs for the set resource_class
will be available,
but you can override get_queryset
method to change it. You can also override
get_resource_kwargs
method to provide some values in resource class (for start
action).
These view sets provide all methods required for entire import/export workflow: start, details,
confirm, cancel and list actions. There is also drf-spectacular
integrations, you can see generated openapi UI for these view sets
(drf-spectacular
must be installed in your project):
Filters
CeleryResource
and CeleryModelResource
also support django-filter
to filter queryset for export. Set filterset_class
attribute to your resource class and pass
filter parameters as filter_kwargs
argument to resource:
filters.py
from django_filters import rest_framework as filters
from . import models
class BandFilterSet(filters.FilterSet):
class Meta:
model = models.Band
fields = [
"id",
"title",
]
resources.py
from import_export_extensions import resources
from . import filters
from . import models
class BandResource(resources.CeleryModelResource):
filterset_class = filters.BandFilterSet
class Meta:
model = models.Band
fields = ["id", "title"]
If filterset_class
is set for your resource, you can pass filter_kwargs
to filter export
queryset:
1>>> from .resources import BandResource
2>>> from .models import Band
3>>> Band.objects.bulk_create([Band(title=title) for title in "ABC"])
4>>> BandResource().get_queryset().count()
53
6>>> filter_kwargs = {"title": "A"}
7>>> band_resource_with_filters = BandResource(filter_kwargs=filter_kwargs)
8>>> band_resource_with_filters.get_queryset().count()
91
Pass filter_kwargs
in resource_kwargs
argument to create ExportJob
with filtered queryset:
1>>> export_job = ExportJob.objects.create(
2 resource_path=BandResource.class_path,
3 file_format_path=file_format_path,
4 resource_kwargs={"filter_kwargs": filter_kwargs},
5 )
6>>> export_job.refresh_from_db()
7>>> len(export_job.result)
81
Since we are using the rest framework filter set, ExportJobViewSet
also supports it. It takes
the filter set from resource_class
. You can see that start
action expects query parameters
for filtering:
Force import
This package provides force import feature. When force import is enabled, then rows with errors will be skipped and rest of the rows will be handled.
Admin page
This functionality available in admin:
In case if some rows contain any errors it will be reported on parse/import stage:
API
In api there’re 2 fields: force_import
and skip_parse_step
.
force_import
allows you to skip rows with errors.skip_parse_step
allows you to run the import task immediately, without having to call theconfirm
endpoint.
Widgets
This package also provides additional widgets for some types of data.
FileWidget
Working with file fields is a common issue. FileWidget
allows to import/export files
including links to external resources that store files and save them in DEFAULT_FILE_STORAGE
.
This widget loads a file from link to media dir. And it correctly render the link for export. It
also supports AWS_STORAGE_BUCKET_NAME
setting.
IntermediateManyToManyWidget
IntermediateManyToManyWidget
allows to import/export objects with related items.
Default M2M widget store just IDs of related objects. With intermediate widget
additional data may be stored. Should be used with IntermediateManyToManyField
.
Fields
M2MField
This is resource field for M2M fields. Provides faster import of related fields.
This implementation deletes intermediate models, which were excluded and creates intermediate models only for newly added models.
IntermediateManyToManyField
This is resource field for M2M with custom through
model.
By default,
django-import-export
set up object attributes usingsetattr(obj, attribute_name, value)
, wherevalue
isQuerySet
of related model objects. But django forbid this whenManyToManyField
used with customthrough
model.This field expects be used with custom
IntermediateManyToManyWidget
widget that return not simple value, but dict with intermediate model attributes.