Repository: django-import-export/django-import-export (language: python)

Issue:
`after_import_row()` declares `row_number` kwarg but it is never passed
**Describe the bug**

[`after_import_row()`](https://github.com/django-import-export/django-import-export/blob/a5dda8a511f42917c3daf97ac787964ea91ab8af/import_export/resources.py#L702) declares `row_number` kwarg but it is [never passed](https://github.com/django-import-export/django-import-export/blob/a5dda8a511f42917c3daf97ac787964ea91ab8af/import_export/resources.py#L804)

The `row_number` value is actually in kwargs, so `row_number` declaration is unused.  Other methods have this same bug.

**Versions (please complete the following information):**
 - Django Import Export: 3.2.0
 - Python 3.10
 - Django 4.1.9

**Expected behavior**

Param should be passed in `row_number` param.



Discussion / hints:

Fix patch:
diff --git a/README.rst b/README.rst
index fc4271724..f5e662631 100644
--- a/README.rst
+++ b/README.rst
@@ -26,6 +26,9 @@ django-import-export
 .. image:: https://static.pepy.tech/personalized-badge/django-import-export?period=month&units=international_system&left_color=black&right_color=blue&left_text=Downloads/month
     :target: https://pepy.tech/project/django-import-export
 
+.. image:: https://img.shields.io/twitter/url/https/twitter.com/django_import.svg?style=social&label=Follow%20%40django_import
+   :alt: Follow us on X
+
 django-import-export is a Django application and library for importing
 and exporting data from a variety of formats.  Includes Django Admin site integration.
 
diff --git a/docs/advanced_usage.rst b/docs/advanced_usage.rst
index 5c72e5986..65229deaa 100644
--- a/docs/advanced_usage.rst
+++ b/docs/advanced_usage.rst
@@ -440,7 +440,7 @@ You can define your resource to take the associated instance as a param, and the
         def __init__(self, publisher_id):
             self.publisher_id = publisher_id
 
-        def before_save_instance(self, instance, using_transactions, dry_run):
+        def before_save_instance(self, instance, row, **kwargs):
             instance.publisher_id = self.publisher_id
 
         class Meta:
@@ -448,6 +448,8 @@ You can define your resource to take the associated instance as a param, and the
 
 See also :ref:`advanced_usage:How to dynamically set resource values`.
 
+.. _advanced_data_manipulation_on_export:
+
 Advanced data manipulation on export
 ====================================
 
diff --git a/docs/api_mixins.rst b/docs/api_mixins.rst
new file mode 100644
index 000000000..4b9b50d9f
--- /dev/null
+++ b/docs/api_mixins.rst
@@ -0,0 +1,35 @@
+======
+Mixins
+======
+
+.. currentmodule:: import_export.mixins
+
+BaseImportExportMixin
+---------------------
+
+.. autoclass:: import_export.mixins.BaseImportExportMixin
+   :members:
+
+BaseImportMixin
+---------------
+
+.. autoclass:: import_export.mixins.BaseImportMixin
+   :members:
+
+BaseExportMixin
+---------------
+
+.. autoclass:: import_export.mixins.BaseExportMixin
+   :members:
+
+ExportViewMixin
+---------------
+
+.. autoclass:: import_export.mixins.ExportViewMixin
+   :members:
+
+ExportViewFormMixin
+-------------------
+
+.. autoclass:: import_export.mixins.ExportViewFormMixin
+   :members:
diff --git a/docs/changelog.rst b/docs/changelog.rst
index d70f1f3a2..83d6fecc5 100644
--- a/docs/changelog.rst
+++ b/docs/changelog.rst
@@ -1,11 +1,14 @@
 Changelog
 =========
 
+Please refer to :doc:`release notes<release_notes>`.
+
 4.0.0-alpha.6 (unreleased)
 --------------------------
 
-- added specific check for missing ``import_id_fields`` (#1645)
 - removed unused variable ``Result.new_record`` (#1640)
+- Refactor ``resources.py`` to standardise method args (#1641)
+- added specific check for missing ``import_id_fields`` (#1645)
 
 4.0.0-alpha.5 (2023-09-22)
 --------------------------
@@ -13,7 +16,6 @@ Changelog
 - dynamic widget parameters for CharField fixes 'NOT NULL constraint' error in xlsx (#1485)
 - refactor to export HTML / formulae escaping updates (#1638)
 
-
 4.0.0-alpha.0 (2023-09-20)
 --------------------------
 
diff --git a/docs/export_workflow.rst b/docs/export_workflow.rst
new file mode 100644
index 000000000..d5b441b37
--- /dev/null
+++ b/docs/export_workflow.rst
@@ -0,0 +1,57 @@
+====================
+Export workflow
+====================
+
+This document describes the export data workflow in detail, with hooks that enable
+customization of the export process.
+
+Methods highlighted in yellow in the sequence diagram indicate public methods which can
+be overridden.
+
+.. image:: images/export_workflow.svg
+  :alt: Export workflow sequence diagram
+  :scale: 75%
+
+The :meth:`~import_export.resources.Resource.export` method retrieves a ``QuerySet``
+from the database and formats into a :class:`tablib.Dataset`.
+
+Various hook methods are defined to allow you to customize the export data.
+
+This is what happens when the method is invoked:
+
+#. The :meth:`~import_export.resources.Resource.export` method is passed an optional
+   queryset parameter.  The ``kwargs`` dict can hold additional information used to
+   create the export, for example if called from the Admin UI.
+
+#. The :meth:`~import_export.resources.Resource.before_export` hook is called.
+
+#. If no ``QuerySet`` has been passed, then
+   :meth:`~import_export.resources.Resource.get_queryset` method is called.
+
+#. The :meth:`~import_export.resources.Resource.filter_export` hook is called.
+   You can override this method to modify the queryset for export.
+
+#. For each instance in the ``QuerySet``,
+   :meth:`~import_export.resources.Resource.export_resource` is called (with the
+   instance passed as a parameter).
+
+#. For each field defined in :attr:`~import_export.resources.ResourceOptions.fields`:
+
+   * :meth:`~import_export.resources.Resource.export_field` is called with the field and
+     instance as parameters.
+
+   * If a :ref:`dehydrate<advanced_data_manipulation_on_export>`  method is defined on
+     the ``Resource``, then this method is called to extract the field value,
+     Otherwise :meth:`~import_export.fields.Field.export` is called for each defined
+     field, with the instance passed as a parameter.
+
+   * :meth:`~import_export.fields.Field.get_value` is called with the instance to
+     retrieve the export value from the instance.export
+
+   * The field's widget :meth:`~import_export.widgets.Widget.render` method is called
+     to retrieve the export value.
+
+#. Each value is appended to a :class:`tablib.Dataset`.
+
+#. The :class:`tablib.Dataset` is returned from
+   :meth:`~import_export.resources.Resource.export`.
diff --git a/docs/faq.rst b/docs/faq.rst
index 17d3ebe1e..ebad392fd 100755
--- a/docs/faq.rst
+++ b/docs/faq.rst
@@ -52,9 +52,9 @@ There is a workaround, which is to set a temporary flag on the instance being sa
 
     class BookResource(resources.ModelResource):
 
-        def before_save_instance(self, instance, using_transactions, dry_run):
+        def before_save_instance(self, instance, row, **kwargs):
             # during 'confirm' step, dry_run is True
-            instance.dry_run = dry_run
+            instance.dry_run = kwargs.get("dry_run", False)
 
         class Meta:
             model = Book
diff --git a/docs/images/export_workflow.svg b/docs/images/export_workflow.svg
new file mode 100644
index 000000000..abf8c197b
--- /dev/null
+++ b/docs/images/export_workflow.svg
@@ -0,0 +1,1 @@
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="1106" height="1637"><desc>participant%20Resource%0Aparticipant%20Field%0Aparticipant%20Widget%0Aparticipant%20tablib.Dataset%0A%0AResource-%3EResource%3A%22%22export(queryset%3DNone%2C%20%5C*%5C*kwargs)%22%22%0Aactivate%20Resource%0A%0AResource-%3EResource%3A%3Cbackground%3A%23yellow%3E%22%22before_export(queryset%3DNone%2C%20%5C*%5C*kwargs)%22%22%0A%0Anote%20over%20Resource%3A%20A%20Queryset%20instance%20can%20be%20passed%20into%20export().%5CnIf%20no%20Queryset%20is%20passed%2C%20get_queryset()%20is%20called.%0A%0AResource-%3EResource%3A%3Cbackground%3A%23yellow%3E%22%22get_queryset()%22%22%0Aactivate%20Resource%20%23lightblue%0AResource%3C--Resource%3A%22%22Queryset%22%22%0Adeactivate%20Resource%0A%0AResource-%3EResource%3A%3Cbackground%3A%23yellow%3E%22%22filter_export(queryset%2C%20%5C*%5C*kwargs)%22%22%0Aactivate%20Resource%20%23lightblue%0AResource%3C--Resource%3A%22%22Queryset%22%22%0Adeactivate%20Resource%0A%0Aloop%20%23pink%20each%20row%20in%20Queryset%0A%0AResource-%3EResource%3A%3Cbackground%3A%23yellow%3E%22%22export_resource(instance)%22%22%0Aactivate%20Resource%20%23lightblue%0A%0Aloop%20%23green%20each%20field%20in%20export%20field%20list%0AResource-%3EResource%3A%22%22export_field(field%2C%20instance)%22%22%0Aactivate%20Resource%20%23lightpink%0AResource-%3EField%3A%22%22export(instance)%22%22%0Aactivate%20Field%20%23lightblue%0Anote%20over%20Field%3A%20An%20optional%20callable%20can%20be%20defined%20instead%20of%20export().%5Cn%20See%20'dehydrate'%20methods%20in%20docs.%0AField-%3EField%3A%22%22get_value(instance)%22%22%0Aactivate%20Field%20%23lightpink%0Anote%20over%20Field%3A%20Get%20the%20field's%20value%20from%20the%20instance.%0AField%3C--Field%3A%22%22%3C%3Cvalue%3E%3E%22%22%0AField-%3EWidget%3A%22%22render(value%2C%20instance)%22%22%0Aactivate%20Widget%0Anote%20over%20Widget%3A%20Format%20field%20value%20into%20a%5Cnstring%20or%20value%20as%20required.%0AField%3C--Widget%3A%22%22%3C%3Cvalue%3E%3E%0Adeactivate%20Widget%0Adeactivate%20Field%0AResource%3C--Field%3A%22%22%3C%3Cvalue%3E%3E%22%22%0Adeactivate%20Field%0Adeactivate%20Resource%0Aend%0Adeactivate%20Resource%0A%0AResource-%3Etablib.Dataset%3A%22%22append()%22%22%0Aend%0A%0AResource%3C--Resource%3A%22%22%3C%3CDataset%3E%3E%22%22%0Adeactivate%20Resource%0A%0A%0A</desc><defs/><g><g/><g/><g/><g/><g/><g/><g/><g/><g/><g/><g/><g/><g/><g/><g/><g/><g/><g/><g/><g/><g/><g/><g/><g><rect fill="white" stroke="none" x="0" y="0" width="1106" height="1637"/></g><g><rect fill="rgb(255,242,245)" stroke="none" x="97.60016957582032" y="611.6654047979999" width="991.0929539641992" height="891.9021001799996"/><rect fill="rgb(204,230,204)" stroke="none" x="115.19192697582032" y="731.2893551179999" width="885.5424095641991" height="696.6335930399997"/></g><g><path fill="none" stroke="black" paint-order="fill stroke markers" d=" M 203.1507139758203 59.284222437999986 L 203.1507139758203 1637.2648612179996" stroke-miterlimit="10" stroke-width="1.4659797833333332" stroke-dasharray="13.532121076923076,5.863919133333333"/><path fill="none" stroke="black" paint-order="fill stroke markers" d=" M 604.8879080325912 59.284222437999986 L 604.8879080325912 1637.2648612179996" stroke-miterlimit="10" stroke-width="1.4659797833333332" stroke-dasharray="13.532121076923076,5.863919133333333"/><path fill="none" stroke="black" paint-order="fill stroke markers" d=" M 880.5276564766016 59.284222437999986 L 880.5276564766016 1637.2648612179996" stroke-miterlimit="10" stroke-width="1.4659797833333332" stroke-dasharray="13.532121076923076,5.863919133333333"/><path fill="none" stroke="black" paint-order="fill stroke markers" d=" M 1027.1219726400195 59.284222437999986 L 1027.1219726400195 1637.2648612179996" stroke-miterlimit="10" stroke-width="1.4659797833333332" stroke-dasharray="13.532121076923076,5.863919133333333"/></g><g><path fill="none" stroke="none"/><g><path fill="white" stroke="black" paint-order="fill stroke markers" d=" M 152.6928762519961 11.786477457999997 L 253.60855169964452 11.786477457999997 L 253.60855169964452 59.284222437999986 L 152.6928762519961 59.284222437999986 L 152.6928762519961 11.786477457999997 Z" stroke-miterlimit="10" stroke-width="2.814681184" stroke-dasharray=""/></g><g><g/><text fill="black" stroke="none" font-family="sans-serif" font-size="11pt" font-style="normal" font-weight="normal" text-decoration="normal" x="171.7799330309961" y="41.692465037999995" text-anchor="start" dominant-baseline="alphabetic" xml:space="preserve">Resource</text></g><path fill="none" stroke="none"/><g><path fill="white" stroke="black" paint-order="fill stroke markers" d=" M 569.913239864431 11.786477457999997 L 639.8625762007514 11.786477457999997 L 639.8625762007514 59.284222437999986 L 569.913239864431 59.284222437999986 L 569.913239864431 11.786477457999997 Z" stroke-miterlimit="10" stroke-width="2.814681184" stroke-dasharray=""/></g><g><g/><text fill="black" stroke="none" font-family="sans-serif" font-size="11pt" font-style="normal" font-weight="normal" text-decoration="normal" x="589.000296643431" y="41.692465037999995" text-anchor="start" dominant-baseline="alphabetic" xml:space="preserve">Field</text></g><path fill="none" stroke="none"/><g><path fill="white" stroke="black" paint-order="fill stroke markers" d=" M 838.6274359402773 11.786477457999997 L 922.4278770129258 11.786477457999997 L 922.4278770129258 59.284222437999986 L 838.6274359402773 59.284222437999986 L 838.6274359402773 11.786477457999997 Z" stroke-miterlimit="10" stroke-width="2.814681184" stroke-dasharray=""/></g><g><g/><text fill="black" stroke="none" font-family="sans-serif" font-size="11pt" font-style="normal" font-weight="normal" text-decoration="normal" x="857.7144927192774" y="41.692465037999995" text-anchor="start" dominant-baseline="alphabetic" xml:space="preserve">Widget</text></g><path fill="none" stroke="none"/><g><path fill="white" stroke="black" paint-order="fill stroke markers" d=" M 963.2138861979336 11.786477457999997 L 1091.0300590821055 11.786477457999997 L 1091.0300590821055 59.284222437999986 L 963.2138861979336 59.284222437999986 L 963.2138861979336 11.786477457999997 Z" stroke-miterlimit="10" stroke-width="2.814681184" stroke-dasharray=""/></g><g><g/><text fill="black" stroke="none" font-family="sans-serif" font-size="11pt" font-style="normal" font-weight="normal" text-decoration="normal" x="982.3009429769336" y="41.692465037999995" text-anchor="start" dominant-baseline="alphabetic" xml:space="preserve">tablib.Dataset</text></g></g><g><path fill="white" stroke="black" paint-order="fill stroke markers" d=" M 194.3548352758203 140.206306478 L 211.9465926758203 140.206306478 L 211.9465926758203 1552.8244256979997 L 194.3548352758203 1552.8244256979997 L 194.3548352758203 140.206306478" stroke-miterlimit="10" stroke-width="1.4659797833333332" stroke-dasharray=""/><path fill="lightblue" stroke="black" paint-order="fill stroke markers" d=" M 203.1507139758203 368.899152678 L 220.74247137582032 368.899152678 L 220.74247137582032 418.15607339800005 L 203.1507139758203 418.15607339800005 L 203.1507139758203 368.899152678" stroke-miterlimit="10" stroke-width="1.4659797833333332" stroke-dasharray=""/><path fill="lightblue" stroke="black" paint-order="fill stroke markers" d=" M 203.1507139758203 513.151563358 L 220.74247137582032 513.151563358 L 220.74247137582032 562.4084840779999 L 203.1507139758203 562.4084840779999 L 203.1507139758203 513.151563358" stroke-miterlimit="10" stroke-width="1.4659797833333332" stroke-dasharray=""/><path fill="lightblue" stroke="black" paint-order="fill stroke markers" d=" M 203.1507139758203 704.9017190179999 L 220.74247137582032 704.9017190179999 L 220.74247137582032 1427.9229481579996 L 203.1507139758203 1427.9229481579996 L 203.1507139758203 704.9017190179999" stroke-miterlimit="10" stroke-width="1.4659797833333332" stroke-dasharray=""/><path fill="lightpink" stroke="black" paint-order="fill stroke markers" d=" M 211.9465926758203 824.5256693379998 L 229.53835007582032 824.5256693379998 L 229.53835007582032 1401.5353120579996 L 211.9465926758203 1401.5353120579996 L 211.9465926758203 824.5256693379998" stroke-miterlimit="10" stroke-width="1.4659797833333332" stroke-dasharray=""/><path fill="lightblue" stroke="black" paint-order="fill stroke markers" d=" M 596.0920293325912 873.7825900579999 L 613.6837867325912 873.7825900579999 L 613.6837867325912 1401.5353120579996 L 596.0920293325912 1401.5353120579996 L 596.0920293325912 873.7825900579999" stroke-miterlimit="10" stroke-width="1.4659797833333332" stroke-dasharray=""/><path fill="lightpink" stroke="black" paint-order="fill stroke markers" d=" M 604.8879080325912 1030.3492309179999 L 622.4796654325912 1030.3492309179999 L 622.4796654325912 1352.2783913379997 L 604.8879080325912 1352.2783913379997 L 604.8879080325912 1030.3492309179999" stroke-miterlimit="10" stroke-width="1.4659797833333332" stroke-dasharray=""/><path fill="white" stroke="black" paint-order="fill stroke markers" d=" M 871.7317777766016 1218.5810350979998 L 889.3235351766016 1218.5810350979998 L 889.3235351766016 1352.2783913379997 L 871.7317777766016 1352.2783913379997 L 871.7317777766016 1218.5810350979998" stroke-miterlimit="10" stroke-width="1.4659797833333332" stroke-dasharray=""/><g><g><rect fill="white" stroke="none" x="232.76350559915363" y="94.46773723799998" width="277.9976810285938" height="22.86928462"/></g><text fill="black" stroke="none" font-family="monospace" font-size="11pt" font-style="normal" font-weight="normal" text-decoration="normal" x="235.40226920915364" y="110.30031889799997" text-anchor="start" dominant-baseline="alphabetic" xml:space="preserve">export(queryset=None, **kwargs)</text></g><g><path fill="none" stroke="black" paint-order="fill stroke markers" d=" M 203.1507139758203 117.33702185799999 L 282.3136222758203 117.33702185799999 L 282.3136222758203 140.206306478 L 226.43047293515366 140.206306478" stroke-miterlimit="10" stroke-width="1.4659797833333332" stroke-dasharray=""/><g transform="translate(211.9465926758203,140.206306478) translate(-211.9465926758203,-140.206306478)"><path fill="black" stroke="none" paint-order="stroke fill markers" d=" M 226.60639050915364 132.8764075613333 L 211.9465926758203 140.206306478 L 226.60639050915364 147.53620539466667 Z"/></g></g><g><g><rect fill="white" stroke="none" x="232.76350559915363" y="166.593942578" width="339.5796512434375" height="22.86928462"/></g><g><rect fill="yellow" stroke="none" x="235.40226920915364" y="169.40862376200002" width="334.3021240234375" height="17.767674974"/><text fill="black" stroke="none" font-family="monospace" font-size="11pt" font-style="normal" font-weight="normal" text-decoration="normal" x="235.40226920915364" y="182.426524238" text-anchor="start" dominant-baseline="alphabetic" xml:space="preserve">before_export(queryset=None, **kwargs)</text></g><g><path fill="none" stroke="black" paint-order="fill stroke markers" d=" M 211.9465926758203 189.463227198 L 282.3136222758203 189.463227198 L 282.3136222758203 212.332511818 L 226.43047293515366 212.332511818" stroke-miterlimit="10" stroke-width="1.4659797833333332" stroke-dasharray=""/><g transform="translate(211.9465926758203,212.332511818) translate(-211.9465926758203,-212.332511818)"><path fill="black" stroke="none" paint-order="stroke fill markers" d=" M 226.60639050915364 205.00261290133332 L 211.9465926758203 212.332511818 L 226.60639050915364 219.66241073466668 Z"/></g></g><path fill="white" stroke="black" paint-order="fill stroke markers" d=" M 17.591757400000002 238.720147918 L 372.8770888916406 238.720147918 L 388.7096705516406 254.552729578 L 388.7096705516406 296.772947338 L 17.591757400000002 296.772947338 L 17.591757400000002 238.720147918 M 372.8770888916406 238.720147918 L 372.8770888916406 254.552729578 L 388.7096705516406 254.552729578" stroke-miterlimit="10" stroke-width="1.4659797833333332" stroke-dasharray=""/><g><text fill="black" stroke="none" font-family="sans-serif" font-size="11pt" font-style="normal" font-weight="normal" text-decoration="normal" x="42.22021776" y="263.348608278" text-anchor="start" dominant-baseline="alphabetic" xml:space="preserve">A Queryset instance can be passed into export().</text><text fill="black" stroke="none" font-family="sans-serif" font-size="11pt" font-style="normal" font-weight="normal" text-decoration="normal" x="42.22021776" y="280.940365678" text-anchor="start" dominant-baseline="alphabetic" xml:space="preserve">If no Queryset is passed, get_queryset() is called.</text></g><g><g><rect fill="white" stroke="none" x="241.55938429915363" y="323.160583438" width="128.4414676496875" height="22.86928462"/></g><g><rect fill="yellow" stroke="none" x="244.19814790915365" y="325.975264622" width="123.1639404296875" height="17.767674974"/><text fill="black" stroke="none" font-family="monospace" font-size="11pt" font-style="normal" font-weight="normal" text-decoration="normal" x="244.19814790915365" y="338.993165098" text-anchor="start" dominant-baseline="alphabetic" xml:space="preserve">get_queryset()</text></g><g><path fill="none" stroke="black" paint-order="fill stroke markers" d=" M 211.9465926758203 346.02986805800003 L 291.1095009758203 346.02986805800003 L 291.1095009758203 368.899152678 L 235.22635163515366 368.899152678" stroke-miterlimit="10" stroke-width="1.4659797833333332" stroke-dasharray=""/><g transform="translate(220.74247137582032,368.899152678) translate(-220.74247137582032,-368.899152678)"><path fill="black" stroke="none" paint-order="stroke fill markers" d=" M 235.40226920915364 361.56925376133336 L 220.74247137582032 368.899152678 L 235.40226920915364 376.22905159466666 Z"/></g></g><g><g><rect fill="white" stroke="none" x="241.55938429915363" y="395.286788778" width="75.65692175125" height="22.86928462"/></g><text fill="black" stroke="none" font-family="monospace" font-size="11pt" font-style="normal" font-weight="normal" text-decoration="normal" x="244.19814790915365" y="411.11937043800003" text-anchor="start" dominant-baseline="alphabetic" xml:space="preserve">Queryset</text></g><g><path fill="none" stroke="black" paint-order="fill stroke markers" d=" M 220.74247137582032 418.15607339800005 L 291.1095009758203 418.15607339800005 L 291.1095009758203 441.025358018 L 226.43047293515366 441.025358018" stroke-miterlimit="10" stroke-width="1.4659797833333332" stroke-dasharray="7.0367029599999995"/><g transform="translate(211.9465926758203,441.025358018) translate(-211.9465926758203,-441.025358018)"><path fill="black" stroke="none" paint-order="stroke fill markers" d=" M 226.60639050915364 433.69545910133337 L 211.9465926758203 441.025358018 L 226.60639050915364 448.35525693466667 Z"/></g></g><g><g><rect fill="white" stroke="none" x="241.55938429915363" y="467.412994118" width="295.5925296614063" height="22.86928462"/></g><g><rect fill="yellow" stroke="none" x="244.19814790915365" y="470.22767530199997" width="290.31500244140625" height="17.767674974"/><text fill="black" stroke="none" font-family="monospace" font-size="11pt" font-style="normal" font-weight="normal" text-decoration="normal" x="244.19814790915365" y="483.245575778" text-anchor="start" dominant-baseline="alphabetic" xml:space="preserve">filter_export(queryset, **kwargs)</text></g><g><path fill="none" stroke="black" paint-order="fill stroke markers" d=" M 211.9465926758203 490.282278738 L 291.1095009758203 490.282278738 L 291.1095009758203 513.151563358 L 235.22635163515366 513.151563358" stroke-miterlimit="10" stroke-width="1.4659797833333332" stroke-dasharray=""/><g transform="translate(220.74247137582032,513.151563358) translate(-220.74247137582032,-513.151563358)"><path fill="black" stroke="none" paint-order="stroke fill markers" d=" M 235.40226920915364 505.8216644413333 L 220.74247137582032 513.151563358 L 235.40226920915364 520.4814622746667 Z"/></g></g><g><g><rect fill="white" stroke="none" x="241.55938429915363" y="539.539199458" width="75.65692175125" height="22.86928462"/></g><text fill="black" stroke="none" font-family="monospace" font-size="11pt" font-style="normal" font-weight="normal" text-decoration="normal" x="244.19814790915365" y="555.371781118" text-anchor="start" dominant-baseline="alphabetic" xml:space="preserve">Queryset</text></g><g><path fill="none" stroke="black" paint-order="fill stroke markers" d=" M 220.74247137582032 562.4084840779999 L 291.1095009758203 562.4084840779999 L 291.1095009758203 585.2777686979999 L 226.43047293515366 585.2777686979999" stroke-miterlimit="10" stroke-width="1.4659797833333332" stroke-dasharray="7.0367029599999995"/><g transform="translate(211.9465926758203,585.2777686979999) translate(-211.9465926758203,-585.2777686979999)"><path fill="black" stroke="none" paint-order="stroke fill markers" d=" M 226.60639050915364 577.9478697813332 L 211.9465926758203 585.2777686979999 L 226.60639050915364 592.6076676146666 Z"/></g></g><g><g><rect fill="rgb(255,242,245)" stroke="none" x="241.55938429915363" y="659.1631497779999" width="225.21313513015625" height="22.86928462"/></g><g><rect fill="yellow" stroke="none" x="244.19814790915365" y="661.9778309619999" width="219.93560791015625" height="17.767674974"/><text fill="black" stroke="none" font-family="monospace" font-size="11pt" font-style="normal" font-weight="normal" text-decoration="normal" x="244.19814790915365" y="674.9957314379999" text-anchor="start" dominant-baseline="alphabetic" xml:space="preserve">export_resource(instance)</text></g><g><path fill="none" stroke="black" paint-order="fill stroke markers" d=" M 211.9465926758203 682.0324343979999 L 291.1095009758203 682.0324343979999 L 291.1095009758203 704.9017190179999 L 235.22635163515366 704.9017190179999" stroke-miterlimit="10" stroke-width="1.4659797833333332" stroke-dasharray=""/><g transform="translate(220.74247137582032,704.9017190179999) translate(-220.74247137582032,-704.9017190179999)"><path fill="black" stroke="none" paint-order="stroke fill markers" d=" M 235.40226920915364 697.5718201013332 L 220.74247137582032 704.9017190179999 L 235.40226920915364 712.2316179346666 Z"/></g></g><g><g><rect fill="rgb(204,230,204)" stroke="none" x="250.35526299915364" y="778.7871000979999" width="260.4028323957813" height="22.86928462"/></g><text fill="black" stroke="none" font-family="monospace" font-size="11pt" font-style="normal" font-weight="normal" text-decoration="normal" x="252.99402660915365" y="794.6196817579998" text-anchor="start" dominant-baseline="alphabetic" xml:space="preserve">export_field(field, instance)</text></g><g><path fill="none" stroke="black" paint-order="fill stroke markers" d=" M 220.74247137582032 801.6563847179998 L 299.9053796758203 801.6563847179998 L 299.9053796758203 824.5256693379998 L 244.02223033515367 824.5256693379998" stroke-miterlimit="10" stroke-width="1.4659797833333332" stroke-dasharray=""/><g transform="translate(229.53835007582032,824.5256693379998) translate(-229.53835007582032,-824.5256693379998)"><path fill="black" stroke="none" paint-order="stroke fill markers" d=" M 244.19814790915365 817.1957704213331 L 229.53835007582032 824.5256693379998 L 244.19814790915365 831.8555682546665 Z"/></g></g><g><g><rect fill="rgb(204,230,204)" stroke="none" x="339.79703156295574" y="850.9133054379998" width="146.0363162825" height="22.86928462"/></g><text fill="black" stroke="none" font-family="monospace" font-size="11pt" font-style="normal" font-weight="normal" text-decoration="normal" x="342.43579517295575" y="866.7458870979998" text-anchor="start" dominant-baseline="alphabetic" xml:space="preserve">export(instance)</text></g><g><path fill="none" stroke="black" paint-order="fill stroke markers" d=" M 229.53835007582032 873.7825900579999 L 581.6081490732579 873.7825900579999" stroke-miterlimit="10" stroke-width="1.4659797833333332" stroke-dasharray=""/><g transform="translate(596.0920293325912,873.7825900579999) translate(-596.0920293325912,-873.7825900579999)"><path fill="black" stroke="none" paint-order="stroke fill markers" d=" M 581.4322314992579 866.4526911413332 L 596.0920293325912 873.7825900579999 L 581.4322314992579 881.1124889746666 Z"/></g></g><path fill="white" stroke="black" paint-order="fill stroke markers" d=" M 403.40915165208344 900.1702261579998 L 790.534082753099 900.1702261579998 L 806.366664413099 916.0028078179997 L 806.366664413099 958.2230255779998 L 403.40915165208344 958.2230255779998 L 403.40915165208344 900.1702261579998 M 790.534082753099 900.1702261579998 L 790.534082753099 916.0028078179997 L 806.366664413099 916.0028078179997" stroke-miterlimit="10" stroke-width="1.4659797833333332" stroke-dasharray=""/><g><text fill="black" stroke="none" font-family="sans-serif" font-size="11pt" font-style="normal" font-weight="normal" text-decoration="normal" x="428.0376120120834" y="924.7986865179998" text-anchor="start" dominant-baseline="alphabetic" xml:space="preserve">An optional callable can be defined instead of export().</text><text fill="black" stroke="none" font-family="sans-serif" font-size="11pt" font-style="normal" font-weight="normal" text-decoration="normal" x="428.0376120120834" y="942.3904439179998" text-anchor="start" dominant-baseline="alphabetic" xml:space="preserve"> See 'dehydrate' methods in docs.</text></g><g><g><rect fill="rgb(204,230,204)" stroke="none" x="643.2965783559246" y="984.6106616779999" width="172.42858923171875" height="22.86928462"/></g><text fill="black" stroke="none" font-family="monospace" font-size="11pt" font-style="normal" font-weight="normal" text-decoration="normal" x="645.9353419659245" y="1000.4432433379999" text-anchor="start" dominant-baseline="alphabetic" xml:space="preserve">get_value(instance)</text></g><g><path fill="none" stroke="black" paint-order="fill stroke markers" d=" M 613.6837867325912 1007.4799462979998 L 692.8466950325912 1007.4799462979998 L 692.8466950325912 1030.3492309179999 L 636.9635456919245 1030.3492309179999" stroke-miterlimit="10" stroke-width="1.4659797833333332" stroke-dasharray=""/><g transform="translate(622.4796654325912,1030.3492309179999) translate(-622.4796654325912,-1030.3492309179999)"><path fill="black" stroke="none" paint-order="stroke fill markers" d=" M 637.1394632659245 1023.0193320013332 L 622.4796654325912 1030.3492309179999 L 637.1394632659245 1037.6791298346666 Z"/></g></g><path fill="white" stroke="black" paint-order="fill stroke markers" d=" M 455.81425724290375 1056.7368670179999 L 738.1289771622787 1056.7368670179999 L 753.9615588222787 1072.5694486779998 L 753.9615588222787 1097.1979090379998 L 455.81425724290375 1097.1979090379998 L 455.81425724290375 1056.7368670179999 M 738.1289771622787 1056.7368670179999 L 738.1289771622787 1072.5694486779998 L 753.9615588222787 1072.5694486779998" stroke-miterlimit="10" stroke-width="1.4659797833333332" stroke-dasharray=""/><g><text fill="black" stroke="none" font-family="sans-serif" font-size="11pt" font-style="normal" font-weight="normal" text-decoration="normal" x="480.4427176029037" y="1081.3653273779996" text-anchor="start" dominant-baseline="alphabetic" xml:space="preserve">Get the field's value from the instance.</text></g><g><g><rect fill="rgb(204,230,204)" stroke="none" x="643.2965783559246" y="1123.5855451379998" width="84.45434606765625" height="22.86928462"/></g><text fill="black" stroke="none" font-family="monospace" font-size="11pt" font-style="normal" font-weight="normal" text-decoration="normal" x="645.9353419659245" y="1139.4181267979998" text-anchor="start" dominant-baseline="alphabetic" xml:space="preserve">&lt;&lt;value&gt;&gt;</text></g><g><path fill="none" stroke="black" paint-order="fill stroke markers" d=" M 622.4796654325912 1146.454829758 L 692.8466950325912 1146.454829758 L 692.8466950325912 1169.3241143779999 L 636.9635456919245 1169.3241143779999" stroke-miterlimit="10" stroke-width="1.4659797833333332" stroke-dasharray="7.0367029599999995"/><g transform="translate(622.4796654325912,1169.3241143779999) translate(-622.4796654325912,-1169.3241143779999)"><path fill="black" stroke="none" paint-order="stroke fill markers" d=" M 637.1394632659245 1161.9942154613332 L 622.4796654325912 1169.3241143779999 L 637.1394632659245 1176.6540132946666 Z"/></g></g><g><g><rect fill="rgb(204,230,204)" stroke="none" x="643.2965783559246" y="1195.7117504779999" width="207.61828649734375" height="22.86928462"/></g><text fill="black" stroke="none" font-family="monospace" font-size="11pt" font-style="normal" font-weight="normal" text-decoration="normal" x="645.9353419659245" y="1211.5443321379998" text-anchor="start" dominant-baseline="alphabetic" xml:space="preserve">render(value, instance)</text></g><g><path fill="none" stroke="black" paint-order="fill stroke markers" d=" M 622.4796654325912 1218.5810350979998 L 857.2478975172683 1218.5810350979998" stroke-miterlimit="10" stroke-width="1.4659797833333332" stroke-dasharray=""/><g transform="translate(871.7317777766016,1218.5810350979998) translate(-871.7317777766016,-1218.5810350979998)"><path fill="black" stroke="none" paint-order="stroke fill markers" d=" M 857.0719799432683 1211.251136181333 L 871.7317777766016 1218.5810350979998 L 857.0719799432683 1225.9109340146665 Z"/></g></g><path fill="white" stroke="black" paint-order="fill stroke markers" d=" M 769.1168551131836 1244.9686711979998 L 976.1058761800197 1244.9686711979998 L 991.9384578400196 1260.8012528579998 L 991.9384578400196 1303.0214706179997 L 769.1168551131836 1303.0214706179997 L 769.1168551131836 1244.9686711979998 M 976.1058761800197 1244.9686711979998 L 976.1058761800197 1260.8012528579998 L 991.9384578400196 1260.8012528579998" stroke-miterlimit="10" stroke-width="1.4659797833333332" stroke-dasharray=""/><g><text fill="black" stroke="none" font-family="sans-serif" font-size="11pt" font-style="normal" font-weight="normal" text-decoration="normal" x="793.7453154731836" y="1269.5971315579995" text-anchor="start" dominant-baseline="alphabetic" xml:space="preserve">Format field value into a</text><text fill="black" stroke="none" font-family="sans-serif" font-size="11pt" font-style="normal" font-weight="normal" text-decoration="normal" x="793.7453154731836" y="1287.1888889579996" text-anchor="start" dominant-baseline="alphabetic" xml:space="preserve">string or value as required.</text></g><g><g><rect fill="rgb(204,230,204)" stroke="none" x="704.8785485707683" y="1329.4091067179997" width="84.45434606765625" height="22.86928462"/></g><text fill="black" stroke="none" font-family="monospace" font-size="11pt" font-style="normal" font-weight="normal" text-decoration="normal" x="707.5173121807683" y="1345.2416883779997" text-anchor="start" dominant-baseline="alphabetic" xml:space="preserve">&lt;&lt;value&gt;&gt;</text></g><g><path fill="none" stroke="black" paint-order="fill stroke markers" d=" M 871.7317777766016 1352.2783913379997 L 636.9635456919245 1352.2783913379997" stroke-miterlimit="10" stroke-width="1.4659797833333332" stroke-dasharray="7.0367029599999995"/><g transform="translate(622.4796654325912,1352.2783913379997) translate(-622.4796654325912,-1352.2783913379997)"><path fill="black" stroke="none" paint-order="stroke fill markers" d=" M 637.1394632659245 1344.948492421333 L 622.4796654325912 1352.2783913379997 L 637.1394632659245 1359.6082902546664 Z"/></g></g><g><g><rect fill="rgb(204,230,204)" stroke="none" x="370.5880166703776" y="1378.6660274379997" width="84.45434606765625" height="22.86928462"/></g><text fill="black" stroke="none" font-family="monospace" font-size="11pt" font-style="normal" font-weight="normal" text-decoration="normal" x="373.2267802803776" y="1394.4986090979996" text-anchor="start" dominant-baseline="alphabetic" xml:space="preserve">&lt;&lt;value&gt;&gt;</text></g><g><path fill="none" stroke="black" paint-order="fill stroke markers" d=" M 596.0920293325912 1401.5353120579996 L 244.02223033515367 1401.5353120579996" stroke-miterlimit="10" stroke-width="1.4659797833333332" stroke-dasharray="7.0367029599999995"/><g transform="translate(229.53835007582032,1401.5353120579996) translate(-229.53835007582032,-1401.5353120579996)"><path fill="black" stroke="none" paint-order="stroke fill markers" d=" M 244.19814790915365 1394.2054131413329 L 229.53835007582032 1401.5353120579996 L 244.19814790915365 1408.8652109746663 Z"/></g></g><g><g><rect fill="rgb(255,242,245)" stroke="none" x="581.705821782295" y="1454.3105842579996" width="75.65692175125" height="22.86928462"/></g><text fill="black" stroke="none" font-family="monospace" font-size="11pt" font-style="normal" font-weight="normal" text-decoration="normal" x="584.3445853922949" y="1470.1431659179996" text-anchor="start" dominant-baseline="alphabetic" xml:space="preserve">append()</text></g><g><path fill="none" stroke="black" paint-order="fill stroke markers" d=" M 211.9465926758203 1477.1798688779995 L 1012.6380923806862 1477.1798688779995" stroke-miterlimit="10" stroke-width="1.4659797833333332" stroke-dasharray=""/><g transform="translate(1027.1219726400195,1477.1798688779995) translate(-1027.1219726400195,-1477.1798688779995)"><path fill="black" stroke="none" paint-order="stroke fill markers" d=" M 1012.4621748066862 1469.8499699613328 L 1027.1219726400195 1477.1798688779995 L 1012.4621748066862 1484.5097677946662 Z"/></g></g><g><g><rect fill="white" stroke="none" x="232.76350559915363" y="1529.9551410779995" width="102.04919470046875" height="22.86928462"/></g><text fill="black" stroke="none" font-family="monospace" font-size="11pt" font-style="normal" font-weight="normal" text-decoration="normal" x="235.40226920915364" y="1545.7877227379995" text-anchor="start" dominant-baseline="alphabetic" xml:space="preserve">&lt;&lt;Dataset&gt;&gt;</text></g><g><path fill="none" stroke="black" paint-order="fill stroke markers" d=" M 211.9465926758203 1552.8244256979997 L 282.3136222758203 1552.8244256979997 L 282.3136222758203 1575.6937103179996 L 217.63459423515366 1575.6937103179996" stroke-miterlimit="10" stroke-width="1.4659797833333332" stroke-dasharray="7.0367029599999995"/><g transform="translate(203.1507139758203,1575.6937103179996) translate(-203.1507139758203,-1575.6937103179996)"><path fill="black" stroke="none" paint-order="stroke fill markers" d=" M 217.81051180915364 1568.363811401333 L 203.1507139758203 1575.6937103179996 L 217.81051180915364 1583.0236092346663 Z"/></g></g><g><g/><path fill="none" stroke="black" paint-order="fill stroke markers" d=" M 97.60016957582032 611.6654047979999 L 1088.6931235400195 611.6654047979999 L 1088.6931235400195 1503.5675049779995 L 97.60016957582032 1503.5675049779995 L 97.60016957582032 611.6654047979999 Z" stroke-miterlimit="10" stroke-width="2.5131082" stroke-dasharray=""/><path fill="pink" stroke="black" paint-order="fill stroke markers" d=" M 97.60016957582032 611.6654047979999 L 97.60016957582032 632.7755136779999 L 157.53807890707031 632.7755136779999 L 168.0931333470703 622.220459238 L 168.0931333470703 611.6654047979999 L 97.60016957582032 611.6654047979999" stroke-miterlimit="10" stroke-width="2.5131082" stroke-dasharray=""/><text fill="black" stroke="none" font-family="sans-serif" font-size="8.8pt" font-style="normal" font-weight="bold" text-decoration="normal" x="115.19192697582031" y="625.738810718" text-anchor="start" dominant-baseline="alphabetic" xml:space="preserve">loop</text><g><rect fill="rgb(255,242,245)" stroke="none" x="183.0461271370703" y="613.07274539" width="131.73571813796875" height="18.295427696"/></g><text fill="black" stroke="none" font-family="sans-serif" font-size="8.8pt" font-style="normal" font-weight="bold" text-decoration="normal" x="185.6848907470703" y="625.738810718" text-anchor="start" dominant-baseline="alphabetic" xml:space="preserve">[each row in Queryset]</text></g><g><g/><path fill="none" stroke="black" paint-order="fill stroke markers" d=" M 115.19192697582032 731.2893551179999 L 1000.7343365400195 731.2893551179999 L 1000.7343365400195 1427.9229481579996 L 115.19192697582032 1427.9229481579996 L 115.19192697582032 731.2893551179999 Z" stroke-miterlimit="10" stroke-width="2.5131082" stroke-dasharray=""/><path fill="green" stroke="black" paint-order="fill stroke markers" d=" M 115.19192697582032 731.2893551179999 L 115.19192697582032 752.3994639979999 L 175.12983630707032 752.3994639979999 L 185.6848907470703 741.8444095579999 L 185.6848907470703 731.2893551179999 L 115.19192697582032 731.2893551179999" stroke-miterlimit="10" stroke-width="2.5131082" stroke-dasharray=""/><text fill="black" stroke="none" font-family="sans-serif" font-size="8.8pt" font-style="normal" font-weight="bold" text-decoration="normal" x="132.78368437582031" y="745.3627610379999" text-anchor="start" dominant-baseline="alphabetic" xml:space="preserve">loop</text><g><rect fill="rgb(204,230,204)" stroke="none" x="200.6378845370703" y="732.69669571" width="167.56712377761718" height="18.295427696"/></g><text fill="black" stroke="none" font-family="sans-serif" font-size="8.8pt" font-style="normal" font-weight="bold" text-decoration="normal" x="203.27664814707032" y="745.3627610379999" text-anchor="start" dominant-baseline="alphabetic" xml:space="preserve">[each field in export field list]</text></g></g><g/><g/><g/><g/></g></g></g></g></g></svg>
\ No newline at end of file
diff --git a/docs/images/import_workflow.svg b/docs/images/import_workflow.svg
new file mode 100644
index 000000000..032a6cf39
--- /dev/null
+++ b/docs/images/import_workflow.svg
@@ -0,0 +1,1 @@
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="1448" height="2643"><desc>%23%20sequencediagram.org%0A%0Aparticipant%20Resource%0Aparticipant%20Result%0Aparticipant%20RowResult%0Aparticipant%20InstanceLoader%0Aparticipant%20Field%0Aparticipant%20Widget%0A%0AResource-%3EResource%3A%22%22import_data(data%2C%20%5C*%5C*kwargs)%22%22%0Aactivate%20Resource%0AResource-%3EResult%3A%22%22__init__()%22%22%0Aactivate%20Result%0AResource%3C--Result%3A%22%22Result%22%22%0Adeactivate%20Result%0A%0AResource-%3EResource%3A%3Cbackground%3A%23yellow%3E%22%22before_import(dataset%2C%20%5C*%5C*kwargs)%22%22%0A%0Aloop%20%23pink%20each%20row%20in%20dataset%0AResource-%3EResource%3A%22%22import_row(row%2C%20instance_loader%2C%20%5C*%5C*kwargs)%22%22%0Aactivate%20Resource%20%23lightblue%0AResource-%3ERowResult%3A%22%22__init__()%22%22%0Aactivate%20RowResult%0AResource%3C--RowResult%3A%22%22RowResult%22%22%0Adeactivate%20RowResult%0A%0AResource-%3EResource%3A%3Cbackground%3A%23yellow%3E%22%22before_import_row(row%2C%20%5C*%5C*kwargs)%22%22%0A%0A%0AResource-%3EResource%3A%3Cbackground%3A%23yellow%3E%22%22get_or_init_instance(instance_loader%2C%20%5Cn%20%20%20%20row)%22%22%0Aactivate%20Resource%20%23lightgrey%0A%0AResource-%3EResource%3A%3Cbackground%3A%23yellow%3E%22%22get_instance(instance_loader%2C%20row)%22%22%0Aactivate%20Resource%20%23lightgreen%0AResource-%3EInstanceLoader%3A%22%22get_instance(row)%22%22%0Aactivate%20InstanceLoader%0Anote%20over%20InstanceLoader%3A%20Existing%20Instance%20is%20returned%20if%20exists%2C%5Cn%20otherwise%20a%20new%20Instance%20is%20created.%0A%0AResource%3C--InstanceLoader%3A%22%22Instance%22%22%0Adeactivate%20InstanceLoader%0AResource--%3EResource%3A%22%22Instance%22%22%0Adeactivate%20Resource%0AResource--%3EResource%3A%22%22Instance%2C%20bool%22%22%0Adeactivate%20Resource%0A%0AResource-%3EResource%3A%3Cbackground%3A%23yellow%3E%22%22after_init_instance(instance%2C%20new%2C%20row%20%5Cn%20%20%20%5C*%5C*kwargs)%22%22%0A%0AResource-%3EResource%3A%3Cbackground%3A%23yellow%3E%22%22for_delete(row%2C%20instance)%22%22%0Aactivate%20Resource%20%23lightgrey%0Anote%20over%20Resource%3A%20If%20True%2C%20row%20is%20deleted.%0AResource--%3EResource%3A%22%22bool%22%22%0A%0Adeactivate%20Resource%0A%0AResource-%3EResource%3A%22%22import_instance(instance%2C%20row%2C%20%5C*%5C*kwargs)%22%22%0Aactivate%20Resource%20%23lightgrey%0A%0Aloop%20%23green%20each%20field%20in%20row%0AResource-%3EField%3A%22%22save(instance%2C%20row%2C%20is_m2m%2C%20%5C*%5C*kwargs)%22%22%0Anote%20over%20Field%3A%20save%20logic%20determines%20the%20correct%20value%5Cnand%20sets%20attribute%20on%20instance.%0AField-%3EField%3A%22%22clean(row%2C%20%5C*%5C*kwargs)%22%22%0Aactivate%20Field%0AField-%3EWidget%3A%22%22clean(value%2C%20row%2C%20%5C*%5C*kwargs)%22%22%0Aactivate%20Widget%0AField%3C--Widget%3A%22%22value%22%22%0Adeactivate%20Widget%0Adeactivate%20Field%0Aend%0A%0Adeactivate%20Resource%0A%0AResource-%3EResource%3A%3Cbackground%3A%23yellow%3E%22%22skip_row(instance%2C%20original%2C%20row%2C%20%5Cn%20%20%20%20import_validation_errors)%22%22%0Aactivate%20Resource%20%23lightgrey%0Anote%20over%20Resource%3A%20If%20True%2C%20row%20is%20skipped.%0AResource--%3EResource%3A%22%22bool%22%22%0Adeactivate%20Resource%0A%0AResource-%3EResource%3A%3Cbackground%3A%23yellow%3E%22%22validate_instance(instance%2C%20%5Cn%20%20%20import_validation_errors)%22%22%0AResource-%3EResource%3A%3Cbackground%3A%23yellow%3E%22%22save_instance(instance%2C%20row%2C%20new%2C%20%5Cn%20%20%20%20%5C*%5C*kwargs)%22%22%0AResource-%3EResource%3A%3Cbackground%3A%23yellow%3E%22%22save_m2m(instance%2C%20row%2C%20%5C*%5C*kwargs)%22%22%0A%0AResource-%3EResource%3A%3Cbackground%3A%23yellow%3E%22%22after_import_row(row%2C%20row_result%2C%20%5Cn%20%20%20%20%5C*%5C*kwargs)%22%22%0A%0A%0AResource--%3EResource%3A%22%22RowResult%22%22%0Adeactivate%20Resource%0Aend%0A%0AResource%3C--Resource%3A%22%22Result%22%22%0Adeactivate%20Resource%0A</desc><defs/><g><g/><g/><g/><g/><g/><g/><g/><g/><g/><g/><g/><g/><g/><g/><g/><g/><g/><g/><g/><g/><g/><g/><g/><g/><g/><g/><g/><g/><g/><g/><g/><g/><g/><g/><g/><g/><g/><g/><g/><g/><g/><g/><g><rect fill="white" stroke="none" x="0" y="0" width="1448" height="2643"/></g><g><rect fill="rgb(255,242,245)" stroke="none" x="-8.795878700000003" y="337.233989358" width="1430.7230054772579" height="2172.5820388999996"/><rect fill="rgb(204,230,204)" stroke="none" x="71.70536283421876" y="1489.4940990579998" width="1332.6300065430391" height="351.8351479999999"/></g><g><path fill="none" stroke="black" paint-order="fill stroke markers" d=" M 133.27651373421875 59.284222437999986 L 133.27651373421875 2643.5133844979996" stroke-miterlimit="10" stroke-width="1.4659797833333332" stroke-dasharray="13.532121076923076,5.863919133333333"/><path fill="none" stroke="black" paint-order="fill stroke markers" d=" M 578.9992837566147 59.284222437999986 L 578.9992837566147 2643.5133844979996" stroke-miterlimit="10" stroke-width="1.4659797833333332" stroke-dasharray="13.532121076923076,5.863919133333333"/><path fill="none" stroke="black" paint-order="fill stroke markers" d=" M 690.9820355129546 59.284222437999986 L 690.9820355129546 2643.5133844979996" stroke-miterlimit="10" stroke-width="1.4659797833333332" stroke-dasharray="13.532121076923076,5.863919133333333"/><path fill="none" stroke="black" paint-order="fill stroke markers" d=" M 862.5993740383842 59.284222437999986 L 862.5993740383842 2643.5133844979996" stroke-miterlimit="10" stroke-width="1.4659797833333332" stroke-dasharray="13.532121076923076,5.863919133333333"/><path fill="none" stroke="black" paint-order="fill stroke markers" d=" M 1040.7306514676225 59.284222437999986 L 1040.7306514676225 2643.5133844979996" stroke-miterlimit="10" stroke-width="1.4659797833333332" stroke-dasharray="13.532121076923076,5.863919133333333"/><path fill="none" stroke="black" paint-order="fill stroke markers" d=" M 1342.7642184772578 59.284222437999986 L 1342.7642184772578 2643.5133844979996" stroke-miterlimit="10" stroke-width="1.4659797833333332" stroke-dasharray="13.532121076923076,5.863919133333333"/></g><g><path fill="none" stroke="none"/><g><path fill="white" stroke="black" paint-order="fill stroke markers" d=" M 82.81867601039454 11.786477457999997 L 183.73435145804297 11.786477457999997 L 183.73435145804297 59.284222437999986 L 82.81867601039454 59.284222437999986 L 82.81867601039454 11.786477457999997 Z" stroke-miterlimit="10" stroke-width="2.814681184" stroke-dasharray=""/></g><g><g/><text fill="black" stroke="none" font-family="sans-serif" font-size="11pt" font-style="normal" font-weight="normal" text-decoration="normal" x="101.90573278939453" y="41.692465037999995" text-anchor="start" dominant-baseline="alphabetic" xml:space="preserve">Resource</text></g><path fill="none" stroke="none"/><g><path fill="white" stroke="black" paint-order="fill stroke markers" d=" M 539.1355698731224 11.786477457999997 L 618.8629976401069 11.786477457999997 L 618.8629976401069 59.284222437999986 L 539.1355698731224 59.284222437999986 L 539.1355698731224 11.786477457999997 Z" stroke-miterlimit="10" stroke-width="2.814681184" stroke-dasharray=""/></g><g><g/><text fill="black" stroke="none" font-family="sans-serif" font-size="11pt" font-style="normal" font-weight="normal" text-decoration="normal" x="558.2226266521225" y="41.692465037999995" text-anchor="start" dominant-baseline="alphabetic" xml:space="preserve">Result</text></g><path fill="none" stroke="none"/><g><path fill="white" stroke="black" paint-order="fill stroke markers" d=" M 636.4547550401069 11.786477457999997 L 745.5093159858022 11.786477457999997 L 745.5093159858022 59.284222437999986 L 636.4547550401069 59.284222437999986 L 636.4547550401069 11.786477457999997 Z" stroke-miterlimit="10" stroke-width="2.814681184" stroke-dasharray=""/></g><g><g/><text fill="black" stroke="none" font-family="sans-serif" font-size="11pt" font-style="normal" font-weight="normal" text-decoration="normal" x="655.5418118191069" y="41.692465037999995" text-anchor="start" dominant-baseline="alphabetic" xml:space="preserve">RowResult</text></g><path fill="none" stroke="none"/><g><path fill="white" stroke="black" paint-order="fill stroke markers" d=" M 792.9790530992279 11.786477457999997 L 932.2196949775405 11.786477457999997 L 932.2196949775405 59.284222437999986 L 792.9790530992279 59.284222437999986 L 792.9790530992279 11.786477457999997 Z" stroke-miterlimit="10" stroke-width="2.814681184" stroke-dasharray=""/></g><g><g/><text fill="black" stroke="none" font-family="sans-serif" font-size="11pt" font-style="normal" font-weight="normal" text-decoration="normal" x="812.066109878228" y="41.692465037999995" text-anchor="start" dominant-baseline="alphabetic" xml:space="preserve">InstanceLoader</text></g><path fill="none" stroke="none"/><g><path fill="white" stroke="black" paint-order="fill stroke markers" d=" M 1005.7559832994623 11.786477457999997 L 1075.7053196357826 11.786477457999997 L 1075.7053196357826 59.284222437999986 L 1005.7559832994623 59.284222437999986 L 1005.7559832994623 11.786477457999997 Z" stroke-miterlimit="10" stroke-width="2.814681184" stroke-dasharray=""/></g><g><g/><text fill="black" stroke="none" font-family="sans-serif" font-size="11pt" font-style="normal" font-weight="normal" text-decoration="normal" x="1024.8430400784623" y="41.692465037999995" text-anchor="start" dominant-baseline="alphabetic" xml:space="preserve">Field</text></g><path fill="none" stroke="none"/><g><path fill="white" stroke="black" paint-order="fill stroke markers" d=" M 1300.8639979409336 11.786477457999997 L 1384.664439013582 11.786477457999997 L 1384.664439013582 59.284222437999986 L 1300.8639979409336 59.284222437999986 L 1300.8639979409336 11.786477457999997 Z" stroke-miterlimit="10" stroke-width="2.814681184" stroke-dasharray=""/></g><g><g/><text fill="black" stroke="none" font-family="sans-serif" font-size="11pt" font-style="normal" font-weight="normal" text-decoration="normal" x="1319.9510547199336" y="41.692465037999995" text-anchor="start" dominant-baseline="alphabetic" xml:space="preserve">Widget</text></g></g><g><path fill="white" stroke="black" paint-order="fill stroke markers" d=" M 124.48063503421875 140.206306478 L 142.07239243421876 140.206306478 L 142.07239243421876 2559.0729489779997 L 124.48063503421875 2559.0729489779997 L 124.48063503421875 140.206306478" stroke-miterlimit="10" stroke-width="1.4659797833333332" stroke-dasharray=""/><path fill="white" stroke="black" paint-order="fill stroke markers" d=" M 570.2034050566147 189.46322719799997 L 587.7951624566147 189.46322719799997 L 587.7951624566147 238.72014791799995 L 570.2034050566147 238.72014791799995 L 570.2034050566147 189.46322719799997" stroke-miterlimit="10" stroke-width="1.4659797833333332" stroke-dasharray=""/><path fill="lightblue" stroke="black" paint-order="fill stroke markers" d=" M 133.27651373421875 430.47030357799997 L 150.86827113421876 430.47030357799997 L 150.86827113421876 2460.559107538 L 133.27651373421875 2460.559107538 L 133.27651373421875 430.47030357799997" stroke-miterlimit="10" stroke-width="1.4659797833333332" stroke-dasharray=""/><path fill="white" stroke="black" paint-order="fill stroke markers" d=" M 682.1861568129546 479.72722429799995 L 699.7779142129546 479.72722429799995 L 699.7779142129546 528.9841450179999 L 682.1861568129546 528.9841450179999 L 682.1861568129546 479.72722429799995" stroke-miterlimit="10" stroke-width="1.4659797833333332" stroke-dasharray=""/><path fill="lightgrey" stroke="black" paint-order="fill stroke markers" d=" M 142.07239243421876 690.8283130979999 L 159.66414983421876 690.8283130979999 L 159.66414983421876 1067.291921458 L 142.07239243421876 1067.291921458 L 142.07239243421876 690.8283130979999" stroke-miterlimit="10" stroke-width="1.4659797833333332" stroke-dasharray=""/><path fill="lightgreen" stroke="black" paint-order="fill stroke markers" d=" M 150.86827113421876 762.9545184379998 L 168.46002853421876 762.9545184379998 L 168.46002853421876 995.1657161179998 L 150.86827113421876 995.1657161179998 L 150.86827113421876 762.9545184379998" stroke-miterlimit="10" stroke-width="1.4659797833333332" stroke-dasharray=""/><path fill="white" stroke="black" paint-order="fill stroke markers" d=" M 853.8034953383842 812.2114391579998 L 871.3952527383842 812.2114391579998 L 871.3952527383842 945.9087953979998 L 853.8034953383842 945.9087953979998 L 853.8034953383842 812.2114391579998" stroke-miterlimit="10" stroke-width="1.4659797833333332" stroke-dasharray=""/><path fill="lightgrey" stroke="black" paint-order="fill stroke markers" d=" M 142.07239243421876 1252.005374158 L 159.66414983421876 1252.005374158 L 159.66414983421876 1368.110972998 L 142.07239243421876 1368.110972998 L 142.07239243421876 1252.005374158" stroke-miterlimit="10" stroke-width="1.4659797833333332" stroke-dasharray=""/><path fill="lightgrey" stroke="black" paint-order="fill stroke markers" d=" M 142.07239243421876 1463.106462958 L 159.66414983421876 1463.106462958 L 159.66414983421876 1841.3292470579997 L 142.07239243421876 1841.3292470579997 L 142.07239243421876 1463.106462958" stroke-miterlimit="10" stroke-width="1.4659797833333332" stroke-dasharray=""/><path fill="white" stroke="black" paint-order="fill stroke markers" d=" M 1031.9347727676225 1716.4277695179999 L 1049.5265301676225 1716.4277695179999 L 1049.5265301676225 1814.9416109579997 L 1031.9347727676225 1814.9416109579997 L 1031.9347727676225 1716.4277695179999" stroke-miterlimit="10" stroke-width="1.4659797833333332" stroke-dasharray=""/><path fill="white" stroke="black" paint-order="fill stroke markers" d=" M 1333.9683397772578 1765.6846902379998 L 1351.5600971772578 1765.6846902379998 L 1351.5600971772578 1814.9416109579997 L 1333.9683397772578 1814.9416109579997 L 1333.9683397772578 1765.6846902379998" stroke-miterlimit="10" stroke-width="1.4659797833333332" stroke-dasharray=""/><path fill="lightgrey" stroke="black" paint-order="fill stroke markers" d=" M 142.07239243421876 1931.0472097979998 L 159.66414983421876 1931.0472097979998 L 159.66414983421876 2047.1528086379997 L 142.07239243421876 2047.1528086379997 L 142.07239243421876 1931.0472097979998" stroke-miterlimit="10" stroke-width="1.4659797833333332" stroke-dasharray=""/><g><g><rect fill="white" stroke="none" x="162.88930535755208" y="94.46773723799998" width="242.80798376296875" height="22.86928462"/></g><text fill="black" stroke="none" font-family="monospace" font-size="11pt" font-style="normal" font-weight="normal" text-decoration="normal" x="165.5280689675521" y="110.30031889799997" text-anchor="start" dominant-baseline="alphabetic" xml:space="preserve">import_data(data, **kwargs)</text></g><g><path fill="none" stroke="black" paint-order="fill stroke markers" d=" M 133.27651373421875 117.33702185799999 L 212.43942203421875 117.33702185799999 L 212.43942203421875 140.206306478 L 156.5562726935521 140.206306478" stroke-miterlimit="10" stroke-width="1.4659797833333332" stroke-dasharray=""/><g transform="translate(142.07239243421876,140.206306478) translate(-142.07239243421876,-140.206306478)"><path fill="black" stroke="none" paint-order="stroke fill markers" d=" M 156.73219026755208 132.8764075613333 L 142.07239243421876 140.206306478 L 156.73219026755208 147.53620539466667 Z"/></g></g><g><g><rect fill="white" stroke="none" x="309.51201355338543" y="166.59394257799997" width="93.2517703840625" height="22.86928462"/></g><text fill="black" stroke="none" font-family="monospace" font-size="11pt" font-style="normal" font-weight="normal" text-decoration="normal" x="312.15077716338544" y="182.42652423799998" text-anchor="start" dominant-baseline="alphabetic" xml:space="preserve">__init__()</text></g><g><path fill="none" stroke="black" paint-order="fill stroke markers" d=" M 142.07239243421876 189.46322719799997 L 555.7195247972813 189.46322719799997" stroke-miterlimit="10" stroke-width="1.4659797833333332" stroke-dasharray=""/><g transform="translate(570.2034050566147,189.46322719799997) translate(-570.2034050566147,-189.46322719799997)"><path fill="black" stroke="none" paint-order="stroke fill markers" d=" M 555.5436072232814 182.1333282813333 L 570.2034050566147 189.46322719799997 L 555.5436072232814 196.79312611466665 Z"/></g></g><g><g><rect fill="white" stroke="none" x="327.10686218619793" y="215.85086329799995" width="58.062073118437496" height="22.86928462"/></g><text fill="black" stroke="none" font-family="monospace" font-size="11pt" font-style="normal" font-weight="normal" text-decoration="normal" x="329.74562579619794" y="231.68344495799997" text-anchor="start" dominant-baseline="alphabetic" xml:space="preserve">Result</text></g><g><path fill="none" stroke="black" paint-order="fill stroke markers" d=" M 570.2034050566147 238.72014791799995 L 156.5562726935521 238.72014791799995" stroke-miterlimit="10" stroke-width="1.4659797833333332" stroke-dasharray="7.0367029599999995"/><g transform="translate(142.07239243421876,238.72014791799995) translate(-142.07239243421876,-238.72014791799995)"><path fill="black" stroke="none" paint-order="stroke fill markers" d=" M 156.73219026755208 231.39024900133327 L 142.07239243421876 238.72014791799995 L 156.73219026755208 246.05004683466663 Z"/></g></g><g><g><rect fill="white" stroke="none" x="162.88930535755208" y="265.10778401799996" width="286.795105345" height="22.86928462"/></g><g><rect fill="yellow" stroke="none" x="165.5280689675521" y="267.92246520199996" width="281.517578125" height="17.767674974"/><text fill="black" stroke="none" font-family="monospace" font-size="11pt" font-style="normal" font-weight="normal" text-decoration="normal" x="165.5280689675521" y="280.940365678" text-anchor="start" dominant-baseline="alphabetic" xml:space="preserve">before_import(dataset, **kwargs)</text></g><g><path fill="none" stroke="black" paint-order="fill stroke markers" d=" M 142.07239243421876 287.977068638 L 212.43942203421875 287.977068638 L 212.43942203421875 310.84635325799997 L 156.5562726935521 310.84635325799997" stroke-miterlimit="10" stroke-width="1.4659797833333332" stroke-dasharray=""/><g transform="translate(142.07239243421876,310.84635325799997) translate(-142.07239243421876,-310.84635325799997)"><path fill="black" stroke="none" paint-order="stroke fill markers" d=" M 156.73219026755208 303.5164543413333 L 142.07239243421876 310.84635325799997 L 156.73219026755208 318.1762521746666 Z"/></g></g><g><g><rect fill="rgb(255,242,245)" stroke="none" x="171.68518405755208" y="384.73173433799997" width="374.7693485090625" height="22.86928462"/></g><text fill="black" stroke="none" font-family="monospace" font-size="11pt" font-style="normal" font-weight="normal" text-decoration="normal" x="174.3239476675521" y="400.564315998" text-anchor="start" dominant-baseline="alphabetic" xml:space="preserve">import_row(row, instance_loader, **kwargs)</text></g><g><path fill="none" stroke="black" paint-order="fill stroke markers" d=" M 142.07239243421876 407.601018958 L 221.23530073421875 407.601018958 L 221.23530073421875 430.47030357799997 L 165.3521513935521 430.47030357799997" stroke-miterlimit="10" stroke-width="1.4659797833333332" stroke-dasharray=""/><g transform="translate(150.86827113421876,430.47030357799997) translate(-150.86827113421876,-430.47030357799997)"><path fill="black" stroke="none" paint-order="stroke fill markers" d=" M 165.5280689675521 423.1404046613333 L 150.86827113421876 430.47030357799997 L 165.5280689675521 437.8002024946666 Z"/></g></g><g><g><rect fill="rgb(255,242,245)" stroke="none" x="369.9013287815554" y="456.857939678" width="93.2517703840625" height="22.86928462"/></g><text fill="black" stroke="none" font-family="monospace" font-size="11pt" font-style="normal" font-weight="normal" text-decoration="normal" x="372.5400923915554" y="472.690521338" text-anchor="start" dominant-baseline="alphabetic" xml:space="preserve">__init__()</text></g><g><path fill="none" stroke="black" paint-order="fill stroke markers" d=" M 150.86827113421876 479.72722429799995 L 667.7022765536212 479.72722429799995" stroke-miterlimit="10" stroke-width="1.4659797833333332" stroke-dasharray=""/><g transform="translate(682.1861568129546,479.72722429799995) translate(-682.1861568129546,-479.72722429799995)"><path fill="black" stroke="none" paint-order="stroke fill markers" d=" M 667.5263589796213 472.3973253813333 L 682.1861568129546 479.72722429799995 L 667.5263589796213 487.0571232146666 Z"/></g></g><g><g><rect fill="rgb(255,242,245)" stroke="none" x="374.3000409397585" y="506.11486039799996" width="84.45434606765625" height="22.86928462"/></g><text fill="black" stroke="none" font-family="monospace" font-size="11pt" font-style="normal" font-weight="normal" text-decoration="normal" x="376.9388045497585" y="521.947442058" text-anchor="start" dominant-baseline="alphabetic" xml:space="preserve">RowResult</text></g><g><path fill="none" stroke="black" paint-order="fill stroke markers" d=" M 682.1861568129546 528.9841450179999 L 165.3521513935521 528.9841450179999" stroke-miterlimit="10" stroke-width="1.4659797833333332" stroke-dasharray="7.0367029599999995"/><g transform="translate(150.86827113421876,528.9841450179999) translate(-150.86827113421876,-528.9841450179999)"><path fill="black" stroke="none" paint-order="stroke fill markers" d=" M 165.5280689675521 521.6542461013332 L 150.86827113421876 528.9841450179999 L 165.5280689675521 536.3140439346666 Z"/></g></g><g><g><rect fill="rgb(255,242,245)" stroke="none" x="171.68518405755208" y="555.371781118" width="286.795105345" height="22.86928462"/></g><g><rect fill="yellow" stroke="none" x="174.3239476675521" y="558.1864623019999" width="281.517578125" height="17.767674974"/><text fill="black" stroke="none" font-family="monospace" font-size="11pt" font-style="normal" font-weight="normal" text-decoration="normal" x="174.3239476675521" y="571.2043627779999" text-anchor="start" dominant-baseline="alphabetic" xml:space="preserve">before_import_row(row, **kwargs)</text></g><g><path fill="none" stroke="black" paint-order="fill stroke markers" d=" M 150.86827113421876 578.2410657379999 L 221.23530073421875 578.2410657379999 L 221.23530073421875 601.1103503579999 L 165.3521513935521 601.1103503579999" stroke-miterlimit="10" stroke-width="1.4659797833333332" stroke-dasharray=""/><g transform="translate(150.86827113421876,601.1103503579999) translate(-150.86827113421876,-601.1103503579999)"><path fill="black" stroke="none" paint-order="stroke fill markers" d=" M 165.5280689675521 593.7804514413332 L 150.86827113421876 601.1103503579999 L 165.5280689675521 608.4402492746666 Z"/></g></g><g><g><rect fill="rgb(255,242,245)" stroke="none" x="180.48106275755208" y="627.4979864579999" width="339.5796512434375" height="22.86928462"/></g><g><rect fill="rgb(255,242,245)" stroke="none" x="180.48106275755208" y="645.0897438579999" width="75.65692175125" height="22.86928462"/></g><g><rect fill="yellow" stroke="none" x="183.1198263675521" y="630.3126676419998" width="334.3021240234375" height="17.767674974"/><text fill="black" stroke="none" font-family="monospace" font-size="11pt" font-style="normal" font-weight="normal" text-decoration="normal" x="183.1198263675521" y="643.3305681179999" text-anchor="start" dominant-baseline="alphabetic" xml:space="preserve">get_or_init_instance(instance_loader, </text><g><rect fill="yellow" stroke="none" x="183.1198263675521" y="647.9044250419998" width="70.37939453125" height="17.767674974"/><text fill="black" stroke="none" font-family="monospace" font-size="11pt" font-style="normal" font-weight="normal" text-decoration="normal" x="183.1198263675521" y="660.9223255179999" text-anchor="start" dominant-baseline="alphabetic" xml:space="preserve">    row)</text></g><g><path fill="none" stroke="black" paint-order="fill stroke markers" d=" M 150.86827113421876 667.9590284779998 L 230.03117943421876 667.9590284779998 L 230.03117943421876 690.8283130979999 L 174.1480300935521 690.8283130979999" stroke-miterlimit="10" stroke-width="1.4659797833333332" stroke-dasharray=""/><g transform="translate(159.66414983421876,690.8283130979999) translate(-159.66414983421876,-690.8283130979999)"><path fill="black" stroke="none" paint-order="stroke fill markers" d=" M 174.3239476675521 683.4984141813331 L 159.66414983421876 690.8283130979999 L 174.3239476675521 698.1582120146666 Z"/></g></g><g><g><rect fill="rgb(255,242,245)" stroke="none" x="189.27694145755206" y="717.2159491979999" width="304.3899539778125" height="22.86928462"/></g><g><rect fill="yellow" stroke="none" x="191.91570506755207" y="720.0306303819998" width="299.1124267578125" height="17.767674974"/><text fill="black" stroke="none" font-family="monospace" font-size="11pt" font-style="normal" font-weight="normal" text-decoration="normal" x="191.91570506755207" y="733.0485308579998" text-anchor="start" dominant-baseline="alphabetic" xml:space="preserve">get_instance(instance_loader, row)</text></g><g><path fill="none" stroke="black" paint-order="fill stroke markers" d=" M 159.66414983421876 740.0852338179998 L 238.82705813421873 740.0852338179998 L 238.82705813421873 762.9545184379998 L 182.94390879355205 762.9545184379998" stroke-miterlimit="10" stroke-width="1.4659797833333332" stroke-dasharray=""/><g transform="translate(168.46002853421874,762.9545184379998) translate(-168.46002853421874,-762.9545184379998)"><path fill="black" stroke="none" paint-order="stroke fill markers" d=" M 183.11982636755206 755.6246195213331 L 168.46002853421874 762.9545184379998 L 183.11982636755206 770.2844173546665 Z"/></g></g><g><g><rect fill="rgb(255,242,245)" stroke="none" x="433.71489163684834" y="789.3421545379998" width="154.83374059890625" height="22.86928462"/></g><text fill="black" stroke="none" font-family="monospace" font-size="11pt" font-style="normal" font-weight="normal" text-decoration="normal" x="436.35365524684835" y="805.1747361979998" text-anchor="start" dominant-baseline="alphabetic" xml:space="preserve">get_instance(row)</text></g><g><path fill="none" stroke="black" paint-order="fill stroke markers" d=" M 168.46002853421874 812.2114391579998 L 839.3196150790509 812.2114391579998" stroke-miterlimit="10" stroke-width="1.4659797833333332" stroke-dasharray=""/><g transform="translate(853.8034953383842,812.2114391579998) translate(-853.8034953383842,-812.2114391579998)"><path fill="black" stroke="none" paint-order="stroke fill markers" d=" M 839.1436975050509 804.8815402413331 L 853.8034953383842 812.2114391579998 L 839.1436975050509 819.5413380746666 Z"/></g></g><path fill="white" stroke="black" paint-order="fill stroke markers" d=" M 717.3696716129546 838.5990752579997 L 991.9964948038139 838.5990752579997 L 1007.8290764638139 854.4316569179997 L 1007.8290764638139 896.6518746779998 L 717.3696716129546 896.6518746779998 L 717.3696716129546 838.5990752579997 M 991.9964948038139 838.5990752579997 L 991.9964948038139 854.4316569179997 L 1007.8290764638139 854.4316569179997" stroke-miterlimit="10" stroke-width="1.4659797833333332" stroke-dasharray=""/><g><text fill="black" stroke="none" font-family="sans-serif" font-size="11pt" font-style="normal" font-weight="normal" text-decoration="normal" x="741.9981319729545" y="863.2275356179998" text-anchor="start" dominant-baseline="alphabetic" xml:space="preserve">Existing Instance is returned if exists,</text><text fill="black" stroke="none" font-family="sans-serif" font-size="11pt" font-style="normal" font-weight="normal" text-decoration="normal" x="741.9981319729545" y="880.8192930179998" text-anchor="start" dominant-baseline="alphabetic" xml:space="preserve"> otherwise a new Instance is created.</text></g><g><g><rect fill="rgb(255,242,245)" stroke="none" x="473.30330106067646" y="923.0395107779998" width="75.65692175125" height="22.86928462"/></g><text fill="black" stroke="none" font-family="monospace" font-size="11pt" font-style="normal" font-weight="normal" text-decoration="normal" x="475.9420646706765" y="938.8720924379998" text-anchor="start" dominant-baseline="alphabetic" xml:space="preserve">Instance</text></g><g><path fill="none" stroke="black" paint-order="fill stroke markers" d=" M 853.8034953383842 945.9087953979998 L 182.94390879355205 945.9087953979998" stroke-miterlimit="10" stroke-width="1.4659797833333332" stroke-dasharray="7.0367029599999995"/><g transform="translate(168.46002853421874,945.9087953979998) translate(-168.46002853421874,-945.9087953979998)"><path fill="black" stroke="none" paint-order="stroke fill markers" d=" M 183.11982636755206 938.5788964813331 L 168.46002853421874 945.9087953979998 L 183.11982636755206 953.2386943146665 Z"/></g></g><g><g><rect fill="rgb(255,242,245)" stroke="none" x="189.27694145755206" y="972.2964314979998" width="75.65692175125" height="22.86928462"/></g><text fill="black" stroke="none" font-family="monospace" font-size="11pt" font-style="normal" font-weight="normal" text-decoration="normal" x="191.91570506755207" y="988.1290131579998" text-anchor="start" dominant-baseline="alphabetic" xml:space="preserve">Instance</text></g><g><path fill="none" stroke="black" paint-order="fill stroke markers" d=" M 168.46002853421874 995.1657161179998 L 238.82705813421873 995.1657161179998 L 238.82705813421873 1018.0350007379998 L 174.14803009355205 1018.0350007379998" stroke-miterlimit="10" stroke-width="1.4659797833333332" stroke-dasharray="7.0367029599999995"/><g transform="translate(159.66414983421873,1018.0350007379998) translate(-159.66414983421873,-1018.0350007379998)"><path fill="black" stroke="none" paint-order="stroke fill markers" d=" M 174.32394766755206 1010.7051018213331 L 159.66414983421873 1018.0350007379998 L 174.32394766755206 1025.3648996546665 Z"/></g></g><g><g><rect fill="rgb(255,242,245)" stroke="none" x="180.48106275755208" y="1044.4226368379998" width="128.4414676496875" height="22.86928462"/></g><text fill="black" stroke="none" font-family="monospace" font-size="11pt" font-style="normal" font-weight="normal" text-decoration="normal" x="183.1198263675521" y="1060.2552184979997" text-anchor="start" dominant-baseline="alphabetic" xml:space="preserve">Instance, bool</text></g><g><path fill="none" stroke="black" paint-order="fill stroke markers" d=" M 159.66414983421876 1067.291921458 L 230.03117943421876 1067.291921458 L 230.03117943421876 1090.1612060779999 L 165.3521513935521 1090.1612060779999" stroke-miterlimit="10" stroke-width="1.4659797833333332" stroke-dasharray="7.0367029599999995"/><g transform="translate(150.86827113421876,1090.1612060779999) translate(-150.86827113421876,-1090.1612060779999)"><path fill="black" stroke="none" paint-order="stroke fill markers" d=" M 165.5280689675521 1082.8313071613331 L 150.86827113421876 1090.1612060779999 L 165.5280689675521 1097.4911049946666 Z"/></g></g><g><g><rect fill="rgb(255,242,245)" stroke="none" x="171.68518405755208" y="1116.5488421779999" width="348.3770755598438" height="22.86928462"/></g><g><rect fill="rgb(255,242,245)" stroke="none" x="171.68518405755208" y="1134.1405995779999" width="110.846619016875" height="22.86928462"/></g><g><rect fill="yellow" stroke="none" x="174.3239476675521" y="1119.3635233619998" width="343.09954833984375" height="17.767674974"/><text fill="black" stroke="none" font-family="monospace" font-size="11pt" font-style="normal" font-weight="normal" text-decoration="normal" x="174.3239476675521" y="1132.3814238379998" text-anchor="start" dominant-baseline="alphabetic" xml:space="preserve">after_init_instance(instance, new, row </text><g><rect fill="yellow" stroke="none" x="174.3239476675521" y="1136.9552807619998" width="105.569091796875" height="17.767674974"/><text fill="black" stroke="none" font-family="monospace" font-size="11pt" font-style="normal" font-weight="normal" text-decoration="normal" x="174.3239476675521" y="1149.9731812379998" text-anchor="start" dominant-baseline="alphabetic" xml:space="preserve">   **kwargs)</text></g><g><path fill="none" stroke="black" paint-order="fill stroke markers" d=" M 150.86827113421876 1157.009884198 L 221.23530073421875 1157.009884198 L 221.23530073421875 1179.879168818 L 165.3521513935521 1179.879168818" stroke-miterlimit="10" stroke-width="1.4659797833333332" stroke-dasharray=""/><g transform="translate(150.86827113421876,1179.879168818) translate(-150.86827113421876,-1179.879168818)"><path fill="black" stroke="none" paint-order="stroke fill markers" d=" M 165.5280689675521 1172.5492699013332 L 150.86827113421876 1179.879168818 L 165.5280689675521 1187.2090677346666 Z"/></g></g><g><g><rect fill="rgb(255,242,245)" stroke="none" x="180.48106275755208" y="1206.266804918" width="225.21313513015625" height="22.86928462"/></g><g><rect fill="yellow" stroke="none" x="183.1198263675521" y="1209.0814861019999" width="219.93560791015625" height="17.767674974"/><text fill="black" stroke="none" font-family="monospace" font-size="11pt" font-style="normal" font-weight="normal" text-decoration="normal" x="183.1198263675521" y="1222.099386578" text-anchor="start" dominant-baseline="alphabetic" xml:space="preserve">for_delete(row, instance)</text></g><g><path fill="none" stroke="black" paint-order="fill stroke markers" d=" M 150.86827113421876 1229.136089538 L 230.03117943421876 1229.136089538 L 230.03117943421876 1252.005374158 L 174.1480300935521 1252.005374158" stroke-miterlimit="10" stroke-width="1.4659797833333332" stroke-dasharray=""/><g transform="translate(159.66414983421876,1252.005374158) translate(-159.66414983421876,-1252.005374158)"><path fill="black" stroke="none" paint-order="stroke fill markers" d=" M 174.3239476675521 1244.6754752413333 L 159.66414983421876 1252.005374158 L 174.3239476675521 1259.3352730746667 Z"/></g></g><path fill="white" stroke="black" paint-order="fill stroke markers" d=" M 36.40040322773437 1278.393010258 L 214.32004258070313 1278.393010258 L 230.15262424070312 1294.225591918 L 230.15262424070312 1318.854052278 L 36.40040322773437 1318.854052278 L 36.40040322773437 1278.393010258 M 214.32004258070313 1278.393010258 L 214.32004258070313 1294.225591918 L 230.15262424070312 1294.225591918" stroke-miterlimit="10" stroke-width="1.4659797833333332" stroke-dasharray=""/><g><text fill="black" stroke="none" font-family="sans-serif" font-size="11pt" font-style="normal" font-weight="normal" text-decoration="normal" x="61.02886358773438" y="1303.0214706179997" text-anchor="start" dominant-baseline="alphabetic" xml:space="preserve">If True, row is deleted.</text></g><g><g><rect fill="rgb(255,242,245)" stroke="none" x="180.48106275755208" y="1345.241688378" width="40.467224485624996" height="22.86928462"/></g><text fill="black" stroke="none" font-family="monospace" font-size="11pt" font-style="normal" font-weight="normal" text-decoration="normal" x="183.1198263675521" y="1361.074270038" text-anchor="start" dominant-baseline="alphabetic" xml:space="preserve">bool</text></g><g><path fill="none" stroke="black" paint-order="fill stroke markers" d=" M 159.66414983421876 1368.110972998 L 230.03117943421876 1368.110972998 L 230.03117943421876 1390.980257618 L 165.3521513935521 1390.980257618" stroke-miterlimit="10" stroke-width="1.4659797833333332" stroke-dasharray="7.0367029599999995"/><g transform="translate(150.86827113421876,1390.980257618) translate(-150.86827113421876,-1390.980257618)"><path fill="black" stroke="none" paint-order="stroke fill markers" d=" M 165.5280689675521 1383.6503587013333 L 150.86827113421876 1390.980257618 L 165.5280689675521 1398.3101565346667 Z"/></g></g><g><g><rect fill="rgb(255,242,245)" stroke="none" x="180.48106275755208" y="1417.367893718" width="357.17449987625" height="22.86928462"/></g><text fill="black" stroke="none" font-family="monospace" font-size="11pt" font-style="normal" font-weight="normal" text-decoration="normal" x="183.1198263675521" y="1433.200475378" text-anchor="start" dominant-baseline="alphabetic" xml:space="preserve">import_instance(instance, row, **kwargs)</text></g><g><path fill="none" stroke="black" paint-order="fill stroke markers" d=" M 150.86827113421876 1440.2371783380001 L 230.03117943421876 1440.2371783380001 L 230.03117943421876 1463.106462958 L 174.1480300935521 1463.106462958" stroke-miterlimit="10" stroke-width="1.4659797833333332" stroke-dasharray=""/><g transform="translate(159.66414983421876,1463.106462958) translate(-159.66414983421876,-1463.106462958)"><path fill="black" stroke="none" paint-order="stroke fill markers" d=" M 174.3239476675521 1455.7765640413334 L 159.66414983421876 1463.106462958 L 174.3239476675521 1470.4363618746668 Z"/></g></g><g><g><rect fill="rgb(204,230,204)" stroke="none" x="434.80628718740496" y="1536.991844038" width="330.7822269270313" height="22.86928462"/></g><text fill="black" stroke="none" font-family="monospace" font-size="11pt" font-style="normal" font-weight="normal" text-decoration="normal" x="437.445050797405" y="1552.824425698" text-anchor="start" dominant-baseline="alphabetic" xml:space="preserve">save(instance, row, is_m2m, **kwargs)</text></g><g><path fill="none" stroke="black" paint-order="fill stroke markers" d=" M 159.66414983421876 1559.8611286579999 L 1026.2467712082891 1559.8611286579999" stroke-miterlimit="10" stroke-width="1.4659797833333332" stroke-dasharray=""/><g transform="translate(1040.7306514676225,1559.8611286579999) translate(-1040.7306514676225,-1559.8611286579999)"><path fill="black" stroke="none" paint-order="stroke fill markers" d=" M 1026.070853634289 1552.5312297413332 L 1040.7306514676225 1559.8611286579999 L 1026.070853634289 1567.1910275746666 Z"/></g></g><path fill="white" stroke="black" paint-order="fill stroke markers" d=" M 888.9870101383842 1586.2487647579999 L 1176.6417111368607 1586.2487647579999 L 1192.4742927968607 1602.0813464179998 L 1192.4742927968607 1644.3015641779998 L 888.9870101383842 1644.3015641779998 L 888.9870101383842 1586.2487647579999 M 1176.6417111368607 1586.2487647579999 L 1176.6417111368607 1602.0813464179998 L 1192.4742927968607 1602.0813464179998" stroke-miterlimit="10" stroke-width="1.4659797833333332" stroke-dasharray=""/><g><text fill="black" stroke="none" font-family="sans-serif" font-size="11pt" font-style="normal" font-weight="normal" text-decoration="normal" x="913.6154704983842" y="1610.8772251179996" text-anchor="start" dominant-baseline="alphabetic" xml:space="preserve">save logic determines the correct value</text><text fill="black" stroke="none" font-family="sans-serif" font-size="11pt" font-style="normal" font-weight="normal" text-decoration="normal" x="913.6154704983842" y="1628.4689825179996" text-anchor="start" dominant-baseline="alphabetic" xml:space="preserve">and sets attribute on instance.</text></g><g><g><rect fill="rgb(204,230,204)" stroke="none" x="1070.3434430909558" y="1670.6892002779998" width="181.226013548125" height="22.86928462"/></g><text fill="black" stroke="none" font-family="monospace" font-size="11pt" font-style="normal" font-weight="normal" text-decoration="normal" x="1072.9822067009559" y="1686.5217819379998" text-anchor="start" dominant-baseline="alphabetic" xml:space="preserve">clean(row, **kwargs)</text></g><g><path fill="none" stroke="black" paint-order="fill stroke markers" d=" M 1040.7306514676225 1693.558484898 L 1119.8935597676225 1693.558484898 L 1119.8935597676225 1716.4277695179999 L 1064.0104104269558 1716.4277695179999" stroke-miterlimit="10" stroke-width="1.4659797833333332" stroke-dasharray=""/><g transform="translate(1049.5265301676225,1716.4277695179999) translate(-1049.5265301676225,-1716.4277695179999)"><path fill="black" stroke="none" paint-order="stroke fill markers" d=" M 1064.1863280009559 1709.0978706013332 L 1049.5265301676225 1716.4277695179999 L 1064.1863280009559 1723.7576684346666 Z"/></g></g><g><g><rect fill="rgb(204,230,204)" stroke="none" x="1070.3434430909558" y="1742.8154056179999" width="242.80798376296875" height="22.86928462"/></g><text fill="black" stroke="none" font-family="monospace" font-size="11pt" font-style="normal" font-weight="normal" text-decoration="normal" x="1072.9822067009559" y="1758.6479872779998" text-anchor="start" dominant-baseline="alphabetic" xml:space="preserve">clean(value, row, **kwargs)</text></g><g><path fill="none" stroke="black" paint-order="fill stroke markers" d=" M 1049.5265301676225 1765.6846902379998 L 1319.4844595179245 1765.6846902379998" stroke-miterlimit="10" stroke-width="1.4659797833333332" stroke-dasharray=""/><g transform="translate(1333.9683397772578,1765.6846902379998) translate(-1333.9683397772578,-1765.6846902379998)"><path fill="black" stroke="none" paint-order="stroke fill markers" d=" M 1319.3085419439244 1758.354791321333 L 1333.9683397772578 1765.6846902379998 L 1319.3085419439244 1773.0145891546665 Z"/></g></g><g><g><rect fill="rgb(204,230,204)" stroke="none" x="1167.1151105714246" y="1792.0723263379998" width="49.264648802031246" height="22.86928462"/></g><text fill="black" stroke="none" font-family="monospace" font-size="11pt" font-style="normal" font-weight="normal" text-decoration="normal" x="1169.7538741814246" y="1807.9049079979998" text-anchor="start" dominant-baseline="alphabetic" xml:space="preserve">value</text></g><g><path fill="none" stroke="black" paint-order="fill stroke markers" d=" M 1333.9683397772578 1814.9416109579997 L 1064.0104104269558 1814.9416109579997" stroke-miterlimit="10" stroke-width="1.4659797833333332" stroke-dasharray="7.0367029599999995"/><g transform="translate(1049.5265301676225,1814.9416109579997) translate(-1049.5265301676225,-1814.9416109579997)"><path fill="black" stroke="none" paint-order="stroke fill markers" d=" M 1064.1863280009559 1807.611712041333 L 1049.5265301676225 1814.9416109579997 L 1064.1863280009559 1822.2715098746664 Z"/></g></g><g><g><rect fill="rgb(255,242,245)" stroke="none" x="180.48106275755208" y="1867.7168831579997" width="304.3899539778125" height="22.86928462"/></g><g><rect fill="rgb(255,242,245)" stroke="none" x="180.48106275755208" y="1885.3086405579998" width="260.4028323957813" height="22.86928462"/></g><g><rect fill="yellow" stroke="none" x="183.1198263675521" y="1870.5315643419997" width="299.1124267578125" height="17.767674974"/><text fill="black" stroke="none" font-family="monospace" font-size="11pt" font-style="normal" font-weight="normal" text-decoration="normal" x="183.1198263675521" y="1883.5494648179997" text-anchor="start" dominant-baseline="alphabetic" xml:space="preserve">skip_row(instance, original, row, </text><g><rect fill="yellow" stroke="none" x="183.1198263675521" y="1888.1233217419997" width="255.12530517578125" height="17.767674974"/><text fill="black" stroke="none" font-family="monospace" font-size="11pt" font-style="normal" font-weight="normal" text-decoration="normal" x="183.1198263675521" y="1901.1412222179997" text-anchor="start" dominant-baseline="alphabetic" xml:space="preserve">    import_validation_errors)</text></g><g><path fill="none" stroke="black" paint-order="fill stroke markers" d=" M 150.86827113421876 1908.177925178 L 230.03117943421876 1908.177925178 L 230.03117943421876 1931.0472097979998 L 174.1480300935521 1931.0472097979998" stroke-miterlimit="10" stroke-width="1.4659797833333332" stroke-dasharray=""/><g transform="translate(159.66414983421876,1931.0472097979998) translate(-159.66414983421876,-1931.0472097979998)"><path fill="black" stroke="none" paint-order="stroke fill markers" d=" M 174.3239476675521 1923.717310881333 L 159.66414983421876 1931.0472097979998 L 174.3239476675521 1938.3771087146665 Z"/></g></g><path fill="white" stroke="black" paint-order="fill stroke markers" d=" M 35.1835148 1957.4348458979998 L 215.5369310084375 1957.4348458979998 L 231.3695126684375 1973.2674275579998 L 231.3695126684375 1997.8958879179997 L 35.1835148 1997.8958879179997 L 35.1835148 1957.4348458979998 M 215.5369310084375 1957.4348458979998 L 215.5369310084375 1973.2674275579998 L 231.3695126684375 1973.2674275579998" stroke-miterlimit="10" stroke-width="1.4659797833333332" stroke-dasharray=""/><g><text fill="black" stroke="none" font-family="sans-serif" font-size="11pt" font-style="normal" font-weight="normal" text-decoration="normal" x="59.81197516" y="1982.0633062579996" text-anchor="start" dominant-baseline="alphabetic" xml:space="preserve">If True, row is skipped.</text></g><g><g><rect fill="rgb(255,242,245)" stroke="none" x="180.48106275755208" y="2024.2835240179995" width="40.467224485624996" height="22.86928462"/></g><text fill="black" stroke="none" font-family="monospace" font-size="11pt" font-style="normal" font-weight="normal" text-decoration="normal" x="183.1198263675521" y="2040.1161056779995" text-anchor="start" dominant-baseline="alphabetic" xml:space="preserve">bool</text></g><g><path fill="none" stroke="black" paint-order="fill stroke markers" d=" M 159.66414983421876 2047.1528086379997 L 230.03117943421876 2047.1528086379997 L 230.03117943421876 2070.0220932579996 L 165.3521513935521 2070.0220932579996" stroke-miterlimit="10" stroke-width="1.4659797833333332" stroke-dasharray="7.0367029599999995"/><g transform="translate(150.86827113421876,2070.0220932579996) translate(-150.86827113421876,-2070.0220932579996)"><path fill="black" stroke="none" paint-order="stroke fill markers" d=" M 165.5280689675521 2062.692194341333 L 150.86827113421876 2070.0220932579996 L 165.5280689675521 2077.351992174666 Z"/></g></g><g><g><rect fill="rgb(255,242,245)" stroke="none" x="171.68518405755208" y="2096.409729358" width="251.605408079375" height="22.86928462"/></g><g><rect fill="rgb(255,242,245)" stroke="none" x="171.68518405755208" y="2114.001486758" width="251.605408079375" height="22.86928462"/></g><g><rect fill="yellow" stroke="none" x="174.3239476675521" y="2099.224410542" width="246.327880859375" height="17.767674974"/><text fill="black" stroke="none" font-family="monospace" font-size="11pt" font-style="normal" font-weight="normal" text-decoration="normal" x="174.3239476675521" y="2112.242311018" text-anchor="start" dominant-baseline="alphabetic" xml:space="preserve">validate_instance(instance, </text><g><rect fill="yellow" stroke="none" x="174.3239476675521" y="2116.816167942" width="246.327880859375" height="17.767674974"/><text fill="black" stroke="none" font-family="monospace" font-size="11pt" font-style="normal" font-weight="normal" text-decoration="normal" x="174.3239476675521" y="2129.834068418" text-anchor="start" dominant-baseline="alphabetic" xml:space="preserve">   import_validation_errors)</text></g><g><path fill="none" stroke="black" paint-order="fill stroke markers" d=" M 150.86827113421876 2136.8707713779995 L 221.23530073421875 2136.8707713779995 L 221.23530073421875 2159.7400559979997 L 165.3521513935521 2159.7400559979997" stroke-miterlimit="10" stroke-width="1.4659797833333332" stroke-dasharray=""/><g transform="translate(150.86827113421876,2159.7400559979997) translate(-150.86827113421876,-2159.7400559979997)"><path fill="black" stroke="none" paint-order="stroke fill markers" d=" M 165.5280689675521 2152.410157081333 L 150.86827113421876 2159.7400559979997 L 165.5280689675521 2167.069954914666 Z"/></g></g><g><g><rect fill="rgb(255,242,245)" stroke="none" x="171.68518405755208" y="2186.127692098" width="304.3899539778125" height="22.86928462"/></g><g><rect fill="rgb(255,242,245)" stroke="none" x="171.68518405755208" y="2203.719449498" width="119.64404333328125" height="22.86928462"/></g><g><rect fill="yellow" stroke="none" x="174.3239476675521" y="2188.942373282" width="299.1124267578125" height="17.767674974"/><text fill="black" stroke="none" font-family="monospace" font-size="11pt" font-style="normal" font-weight="normal" text-decoration="normal" x="174.3239476675521" y="2201.960273758" text-anchor="start" dominant-baseline="alphabetic" xml:space="preserve">save_instance(instance, row, new, </text><g><rect fill="yellow" stroke="none" x="174.3239476675521" y="2206.534130682" width="114.36651611328125" height="17.767674974"/><text fill="black" stroke="none" font-family="monospace" font-size="11pt" font-style="normal" font-weight="normal" text-decoration="normal" x="174.3239476675521" y="2219.552031158" text-anchor="start" dominant-baseline="alphabetic" xml:space="preserve">    **kwargs)</text></g><g><path fill="none" stroke="black" paint-order="fill stroke markers" d=" M 150.86827113421876 2226.5887341179996 L 221.23530073421875 2226.5887341179996 L 221.23530073421875 2249.4580187379997 L 165.3521513935521 2249.4580187379997" stroke-miterlimit="10" stroke-width="1.4659797833333332" stroke-dasharray=""/><g transform="translate(150.86827113421876,2249.4580187379997) translate(-150.86827113421876,-2249.4580187379997)"><path fill="black" stroke="none" paint-order="stroke fill markers" d=" M 165.5280689675521 2242.1281198213333 L 150.86827113421876 2249.4580187379997 L 165.5280689675521 2256.787917654666 Z"/></g></g><g><g><rect fill="rgb(255,242,245)" stroke="none" x="171.68518405755208" y="2275.845654838" width="295.5925296614063" height="22.86928462"/></g><g><rect fill="yellow" stroke="none" x="174.3239476675521" y="2278.660336022" width="290.31500244140625" height="17.767674974"/><text fill="black" stroke="none" font-family="monospace" font-size="11pt" font-style="normal" font-weight="normal" text-decoration="normal" x="174.3239476675521" y="2291.678236498" text-anchor="start" dominant-baseline="alphabetic" xml:space="preserve">save_m2m(instance, row, **kwargs)</text></g><g><path fill="none" stroke="black" paint-order="fill stroke markers" d=" M 150.86827113421876 2298.7149394579997 L 221.23530073421875 2298.7149394579997 L 221.23530073421875 2321.584224078 L 165.3521513935521 2321.584224078" stroke-miterlimit="10" stroke-width="1.4659797833333332" stroke-dasharray=""/><g transform="translate(150.86827113421876,2321.584224078) translate(-150.86827113421876,-2321.584224078)"><path fill="black" stroke="none" paint-order="stroke fill markers" d=" M 165.5280689675521 2314.2543251613333 L 150.86827113421876 2321.584224078 L 165.5280689675521 2328.9141229946663 Z"/></g></g><g><g><rect fill="rgb(255,242,245)" stroke="none" x="171.68518405755208" y="2347.971860178" width="304.3899539778125" height="22.86928462"/></g><g><rect fill="rgb(255,242,245)" stroke="none" x="171.68518405755208" y="2365.563617578" width="119.64404333328125" height="22.86928462"/></g><g><rect fill="yellow" stroke="none" x="174.3239476675521" y="2350.786541362" width="299.1124267578125" height="17.767674974"/><text fill="black" stroke="none" font-family="monospace" font-size="11pt" font-style="normal" font-weight="normal" text-decoration="normal" x="174.3239476675521" y="2363.804441838" text-anchor="start" dominant-baseline="alphabetic" xml:space="preserve">after_import_row(row, row_result, </text><g><rect fill="yellow" stroke="none" x="174.3239476675521" y="2368.378298762" width="114.36651611328125" height="17.767674974"/><text fill="black" stroke="none" font-family="monospace" font-size="11pt" font-style="normal" font-weight="normal" text-decoration="normal" x="174.3239476675521" y="2381.396199238" text-anchor="start" dominant-baseline="alphabetic" xml:space="preserve">    **kwargs)</text></g><g><path fill="none" stroke="black" paint-order="fill stroke markers" d=" M 150.86827113421876 2388.4329021979997 L 221.23530073421875 2388.4329021979997 L 221.23530073421875 2411.302186818 L 165.3521513935521 2411.302186818" stroke-miterlimit="10" stroke-width="1.4659797833333332" stroke-dasharray=""/><g transform="translate(150.86827113421876,2411.302186818) translate(-150.86827113421876,-2411.302186818)"><path fill="black" stroke="none" paint-order="stroke fill markers" d=" M 165.5280689675521 2403.9722879013334 L 150.86827113421876 2411.302186818 L 165.5280689675521 2418.6320857346664 Z"/></g></g><g><g><rect fill="rgb(255,242,245)" stroke="none" x="171.68518405755208" y="2437.689822918" width="84.45434606765625" height="22.86928462"/></g><text fill="black" stroke="none" font-family="monospace" font-size="11pt" font-style="normal" font-weight="normal" text-decoration="normal" x="174.3239476675521" y="2453.522404578" text-anchor="start" dominant-baseline="alphabetic" xml:space="preserve">RowResult</text></g><g><path fill="none" stroke="black" paint-order="fill stroke markers" d=" M 150.86827113421876 2460.559107538 L 221.23530073421875 2460.559107538 L 221.23530073421875 2483.428392158 L 156.5562726935521 2483.428392158" stroke-miterlimit="10" stroke-width="1.4659797833333332" stroke-dasharray="7.0367029599999995"/><g transform="translate(142.07239243421876,2483.428392158) translate(-142.07239243421876,-2483.428392158)"><path fill="black" stroke="none" paint-order="stroke fill markers" d=" M 156.73219026755208 2476.0984932413335 L 142.07239243421876 2483.428392158 L 156.73219026755208 2490.7582910746664 Z"/></g></g><g><g><rect fill="white" stroke="none" x="162.88930535755208" y="2536.203664358" width="58.062073118437496" height="22.86928462"/></g><text fill="black" stroke="none" font-family="monospace" font-size="11pt" font-style="normal" font-weight="normal" text-decoration="normal" x="165.5280689675521" y="2552.036246018" text-anchor="start" dominant-baseline="alphabetic" xml:space="preserve">Result</text></g><g><path fill="none" stroke="black" paint-order="fill stroke markers" d=" M 142.07239243421876 2559.0729489779997 L 212.43942203421875 2559.0729489779997 L 212.43942203421875 2581.942233598 L 147.7603939935521 2581.942233598" stroke-miterlimit="10" stroke-width="1.4659797833333332" stroke-dasharray="7.0367029599999995"/><g transform="translate(133.27651373421875,2581.942233598) translate(-133.27651373421875,-2581.942233598)"><path fill="black" stroke="none" paint-order="stroke fill markers" d=" M 147.93631156755208 2574.6123346813333 L 133.27651373421875 2581.942233598 L 147.93631156755208 2589.2721325146663 Z"/></g></g><g><g/><path fill="none" stroke="black" paint-order="fill stroke markers" d=" M -8.795878700000003 337.233989358 L 1421.9271267772579 337.233989358 L 1421.9271267772579 2509.8160282579997 L -8.795878700000003 2509.8160282579997 L -8.795878700000003 337.233989358 Z" stroke-miterlimit="10" stroke-width="2.5131082" stroke-dasharray=""/><path fill="pink" stroke="black" paint-order="fill stroke markers" d=" M -8.795878700000003 337.233989358 L -8.795878700000003 358.34409823799996 L 51.142030631249995 358.34409823799996 L 61.697085071249994 347.78904379799997 L 61.697085071249994 337.233989358 L -8.795878700000003 337.233989358" stroke-miterlimit="10" stroke-width="2.5131082" stroke-dasharray=""/><text fill="black" stroke="none" font-family="sans-serif" font-size="8.8pt" font-style="normal" font-weight="bold" text-decoration="normal" x="8.795878699999996" y="351.30739527799994" text-anchor="start" dominant-baseline="alphabetic" xml:space="preserve">loop</text><g><rect fill="rgb(255,242,245)" stroke="none" x="76.65007886125" y="338.64132994999994" width="121.95309484695312" height="18.295427696"/></g><text fill="black" stroke="none" font-family="sans-serif" font-size="8.8pt" font-style="normal" font-weight="bold" text-decoration="normal" x="79.28884247124999" y="351.30739527799994" text-anchor="start" dominant-baseline="alphabetic" xml:space="preserve">[each row in dataset]</text></g><g><g/><path fill="none" stroke="black" paint-order="fill stroke markers" d=" M 71.70536283421876 1489.4940990579998 L 1404.3353693772578 1489.4940990579998 L 1404.3353693772578 1841.3292470579997 L 71.70536283421876 1841.3292470579997 L 71.70536283421876 1489.4940990579998 Z" stroke-miterlimit="10" stroke-width="2.5131082" stroke-dasharray=""/><path fill="green" stroke="black" paint-order="fill stroke markers" d=" M 71.70536283421876 1489.4940990579998 L 71.70536283421876 1510.604207938 L 131.64327216546877 1510.604207938 L 142.19832660546876 1500.049153498 L 142.19832660546876 1489.4940990579998 L 71.70536283421876 1489.4940990579998" stroke-miterlimit="10" stroke-width="2.5131082" stroke-dasharray=""/><text fill="black" stroke="none" font-family="sans-serif" font-size="8.8pt" font-style="normal" font-weight="bold" text-decoration="normal" x="89.29712023421877" y="1503.567504978" text-anchor="start" dominant-baseline="alphabetic" xml:space="preserve">loop</text><g><rect fill="rgb(204,230,204)" stroke="none" x="157.15132039546876" y="1490.90143965" width="104.99385107253906" height="18.295427696"/></g><text fill="black" stroke="none" font-family="sans-serif" font-size="8.8pt" font-style="normal" font-weight="bold" text-decoration="normal" x="159.79008400546877" y="1503.567504978" text-anchor="start" dominant-baseline="alphabetic" xml:space="preserve">[each field in row]</text></g></g><g/><g/><g/><g/><g/><g/></g></g></g></g></g></g></g></g></g></g></g></g></g></g></g></g></g></g></svg>
\ No newline at end of file
diff --git a/docs/images/src/export_workflow.txt b/docs/images/src/export_workflow.txt
new file mode 100644
index 000000000..221eee38e
--- /dev/null
+++ b/docs/images/src/export_workflow.txt
@@ -0,0 +1,58 @@
+# see import_workflow.txt
+
+participant Resource
+participant Field
+participant Widget
+participant tablib.Dataset
+
+Resource->Resource:""export(queryset=None, \*\*kwargs)""
+activate Resource
+
+Resource->Resource:<background:#yellow>""before_export(queryset=None, \*\*kwargs)""
+
+note over Resource: A Queryset instance can be passed into export().\nIf no Queryset is passed, get_queryset() is called.
+
+Resource->Resource:<background:#yellow>""get_queryset()""
+activate Resource #lightblue
+Resource<--Resource:""Queryset""
+deactivate Resource
+
+Resource->Resource:<background:#yellow>""filter_export(queryset, \*\*kwargs)""
+activate Resource #lightblue
+Resource<--Resource:""Queryset""
+deactivate Resource
+
+loop #pink each row in Queryset
+
+Resource->Resource:<background:#yellow>""export_resource(instance)""
+activate Resource #lightblue
+
+loop #green each field in export field list
+Resource->Resource:""export_field(field, instance)""
+activate Resource #lightpink
+Resource->Field:""export(instance)""
+activate Field #lightblue
+note over Field: An optional callable can be defined instead of export().\n See 'dehydrate' methods in docs.
+Field->Field:""get_value(instance)""
+activate Field #lightpink
+note over Field: Get the field's value from the instance.
+Field<--Field:""<<value>>""
+Field->Widget:""render(value, instance)""
+activate Widget
+note over Widget: Format field value into a\nstring or value as required.
+Field<--Widget:""<<value>>
+deactivate Widget
+deactivate Field
+Resource<--Field:""<<value>>""
+deactivate Field
+deactivate Resource
+end
+deactivate Resource
+
+Resource->tablib.Dataset:""append()""
+end
+
+Resource<--Resource:""<<Dataset>>""
+deactivate Resource
+
+
diff --git a/docs/images/src/import_workflow.txt b/docs/images/src/import_workflow.txt
new file mode 100644
index 000000000..f4e9b9cd4
--- /dev/null
+++ b/docs/images/src/import_workflow.txt
@@ -0,0 +1,93 @@
+# Source for import workflow sequence diagram.
+# This source can be loaded into sequencediagram.org (web app).
+# If this source is changed, then the svg image in 'images/' dir should be regenerated
+# by exporting from the web app.
+
+participant Resource
+participant Result
+participant RowResult
+participant InstanceLoader
+participant Field
+participant Widget
+
+Resource->Resource:""import_data(data, \*\*kwargs)""
+activate Resource
+Resource->Result:""__init__()""
+activate Result
+Resource<--Result:""Result""
+deactivate Result
+
+Resource->Resource:<background:#yellow>""before_import(dataset, \*\*kwargs)""
+
+loop #pink each row in dataset
+Resource->Resource:""import_row(row, instance_loader, \*\*kwargs)""
+activate Resource #lightblue
+Resource->RowResult:""__init__()""
+activate RowResult
+Resource<--RowResult:""RowResult""
+deactivate RowResult
+
+Resource->Resource:<background:#yellow>""before_import_row(row, \*\*kwargs)""
+
+
+Resource->Resource:<background:#yellow>""get_or_init_instance(instance_loader, \n    row)""
+activate Resource #lightgrey
+
+Resource->Resource:<background:#yellow>""get_instance(instance_loader, row)""
+activate Resource #lightgreen
+Resource->InstanceLoader:""get_instance(row)""
+activate InstanceLoader
+note over InstanceLoader: Existing Instance is returned if exists,\n otherwise a new Instance is created.
+
+Resource<--InstanceLoader:""Instance""
+deactivate InstanceLoader
+Resource-->Resource:""Instance""
+deactivate Resource
+Resource-->Resource:""Instance, bool""
+deactivate Resource
+
+Resource->Resource:<background:#yellow>""after_init_instance(instance, new, row \n   \*\*kwargs)""
+
+Resource->Resource:<background:#yellow>""for_delete(row, instance)""
+activate Resource #lightgrey
+note over Resource: If True, row is deleted.
+Resource-->Resource:""bool""
+
+deactivate Resource
+
+Resource->Resource:""import_instance(instance, row, \*\*kwargs)""
+activate Resource #lightgrey
+
+loop #green each field in row
+Resource->Field:""save(instance, row, is_m2m, \*\*kwargs)""
+note over Field: save logic determines the correct value\nand sets attribute on instance.
+Field->Field:""clean(row, \*\*kwargs)""
+activate Field
+Field->Widget:""clean(value, row, \*\*kwargs)""
+activate Widget
+Field<--Widget:""value""
+deactivate Widget
+deactivate Field
+end
+
+deactivate Resource
+
+Resource->Resource:<background:#yellow>""skip_row(instance, original, row, \n    import_validation_errors)""
+activate Resource #lightgrey
+note over Resource: If True, row is skipped.
+Resource-->Resource:""bool""
+deactivate Resource
+
+Resource->Resource:<background:#yellow>""validate_instance(instance, \n   import_validation_errors)""
+Resource->Resource:<background:#yellow>""save_instance(instance, row, new, \n    \*\*kwargs)""
+Resource->Resource:<background:#yellow>""save_m2m(instance, row, \*\*kwargs)""
+
+Resource->Resource:<background:#yellow>""after_import_row(row, row_result, \n    \*\*kwargs)""
+
+
+Resource-->Resource:""RowResult""
+deactivate Resource
+end
+
+Resource<--Resource:""Result""
+deactivate Resource
diff --git a/docs/import_workflow.rst b/docs/import_workflow.rst
index 481ee7c04..f6aa209a6 100644
--- a/docs/import_workflow.rst
+++ b/docs/import_workflow.rst
@@ -1,40 +1,33 @@
 ====================
-Import data workflow
+Import workflow
 ====================
 
-This document describes the import data workflow in detail, with hooks that
-enable customization of the import process. The central aspect of the import
-process is a resource's :meth:`~import_export.resources.Resource.import_data`
-method which is explained below.
+This document describes the import data workflow in detail, with hooks that enable
+customization of the import process.
 
-The :meth:`~import_export.resources.Resource.import_data` method of
-:class:`~import_export.resources.Resource` is responsible for importing data
-from a given dataset.
-
-``dataset`` is required and expected to be a :class:`tablib.Dataset` with
-a header row.
-
-``dry_run`` is a Boolean which determines if changes to the database are
-made or if the import is only simulated. It defaults to ``False``.
+Methods highlighted in yellow in the sequence diagram indicate public methods which can
+be overridden.
 
-``raise_errors`` is a Boolean. If ``True``, import should raise errors.
-The default is ``False``, which means that eventual errors and traceback
-will be saved in ``Result`` instance.
+.. image:: images/import_workflow.svg
+  :alt: Import workflow sequence diagram
+  :scale: 75%
 
+The :meth:`~import_export.resources.Resource.import_data` method of
+:class:`~import_export.resources.Resource` is responsible for importing data
+from a given dataset.  Refer to the method documentation for parameters to this method.
 
 This is what happens when the method is invoked:
 
 #. First, a new :class:`~import_export.results.Result` instance, which holds
    errors and other information gathered during the import, is initialized.
 
-   Then, an :class:`~import_export.instance_loaders.InstanceLoader` responsible
+   Then, an :class:`~import_export.instance_loaders.BaseInstanceLoader` responsible
    for loading existing instances is initialized. A different
    :class:`~import_export.instance_loaders.BaseInstanceLoader` can be specified
    via :class:`~import_export.resources.ResourceOptions`'s
    ``instance_loader_class`` attribute. A
    :class:`~import_export.instance_loaders.CachedInstanceLoader` can be used to
-   reduce number of database queries. See the `source
-   <https://github.com/django-import-export/django-import-export/blob/master/import_export/instance_loaders.py>`_
+   reduce number of database queries. See the :mod:`~import_export.instance_loaders`
    for available implementations.
 
 #. The :meth:`~import_export.resources.Resource.before_import` hook is called.
@@ -65,8 +58,8 @@ This is what happens when the method is invoked:
      is stopped at this point.
 
    * If the instance was not deleted in the previous step,
-     :meth:`~import_export.resources.Resource.import_obj` is called with the
-     ``instance`` as current object, ``row`` as current row and ``dry run``.
+     :meth:`~import_export.resources.Resource.import_row` is called with the
+     ``instance`` as current object instance, ``row`` as current row.
 
      :meth:`~import_export.resources.Resource.import_field` is called for
      each field in :class:`~import_export.resources.Resource` skipping many-
@@ -97,8 +90,6 @@ This is what happens when the method is invoked:
        * :meth:`~import_export.resources.Resource.before_save_instance`
        * :meth:`~import_export.resources.Resource.after_save_instance`
 
-     Both methods receive ``instance`` and ``dry_run`` arguments.
-
    * :meth:`~import_export.resources.Resource.save_m2m` is called to save
      many to many fields.
 
@@ -108,7 +99,7 @@ This is what happens when the method is invoked:
      skipped or deleted.
 
      If an exception is raised during row processing and
-     :meth:`~import_export.resources.Resource.import_data` was invoked with
+     :meth:`~import_export.resources.Resource.import_row` was invoked with
      ``raise_errors=False`` (which is the default) the particular traceback
      is appended to :class:`~import_export.results.RowResult` as well.
 
@@ -125,8 +116,8 @@ Transaction support
 -------------------
 
 If transaction support is enabled, whole import process is wrapped inside
-transaction and rollbacked or committed respectively.
-All methods called from inside of ``import_data`` (create / delete / update)
-receive ``False`` for ``dry_run`` argument.
+transaction and rolled back or committed respectively.
+All methods called from inside of :meth:`~import_export.resources.Resource.import_data`
+(create / delete / update) receive ``False`` for ``dry_run`` argument.
 
 .. _Dataset: https://tablib.readthedocs.io/en/stable/api/#dataset-object
diff --git a/docs/index.rst b/docs/index.rst
index e108ee374..7d8b7c984 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -39,10 +39,12 @@ exporting data with included admin integration.
    getting_started
    advanced_usage
    import_workflow
+   export_workflow
    bulk_import
    celery
    testing
    faq
+   release_notes
    changelog
 
 .. toctree::
@@ -54,6 +56,7 @@ exporting data with included admin integration.
    api_widgets
    api_fields
    api_instance_loaders
+   api_mixins
    api_tmp_storages
    api_results
    api_forms
diff --git a/docs/release_notes.rst b/docs/release_notes.rst
new file mode 100644
index 000000000..fa1e63b7b
--- /dev/null
+++ b/docs/release_notes.rst
@@ -0,0 +1,230 @@
+=============
+Release Notes
+=============
+
+v4
+==
+
+v4 of import-export (released Q4 2023) contains a number of minor changes to the API.
+
+If you have customized import-export by overriding methods, then you will have to
+modify your installation before working with v4.  If you have not overridden any
+methods then you should not be affected by these changes and no changes to your code
+should be necessary.
+
+Test thoroughly before deploying v4 to production.
+
+Refer to
+`this PR <https://github.com/django-import-export/django-import-export/pull/1641/>`_
+for more information.
+
+This guide describes the major changes and how to upgrade.
+
+API changes
+===========
+
+The API changes mostly change method arguments, although some method names have changed.
+
+Methods which process row data have been updated so that method args are standardized.
+This has been done to resolve inconsistency issues where the parameters differed between
+method calls, and to allow easier extensibility.
+
+:class:`import_export.resources.Resource`
+-----------------------------------------
+
+Renamed methods
+^^^^^^^^^^^^^^^
+
+.. list-table::
+   :header-rows: 1
+
+   * - Previous
+     - New
+     - Summary
+
+   * - ``import_obj(self, obj, data, dry_run, **kwargs)``
+     - ``import_instance(self, instance, row, **kwargs)``
+     -  * ``obj`` param renamed to ``instance``
+        * ``data`` param renamed to ``row``
+        * ``dry_run`` param now in ``kwargs``
+
+   * - ``after_import_instance(self, instance, new, row_number=None, **kwargs)``
+     - ``after_init_instance(self, instance, new, row, **kwargs)``
+     -  * ``row`` added as mandatory arg
+        * ``row_number`` now in ``kwargs``
+
+Parameter changes
+^^^^^^^^^^^^^^^^^
+
+This section describes methods in which the parameters have changed.
+
+.. list-table::
+   :header-rows: 1
+
+   * - Previous
+     - New
+     - Summary
+
+   * - ``before_import(self, dataset, using_transactions, dry_run, **kwargs)``
+     - ``before_import(self, dataset, **kwargs)``
+     -  * ``using_transactions`` param now in ``kwargs``
+        * ``dry_run`` param now in ``kwargs``
+
+   * - ``after_import(self, dataset, result, using_transactions, dry_run, **kwargs)``
+     - ``after_import(self, dataset, result, **kwargs)``
+     -  * ``using_transactions`` param now in ``kwargs``
+        * ``dry_run`` param now in ``kwargs``
+
+   * - ``before_import_row(self, row, row_number=None, **kwargs)``
+     - ``before_import_row(self, row, **kwargs)``
+     - * ``row_number`` now in ``kwargs``
+
+   * - ``after_import_row(self, row, row_result, row_number=None, **kwargs)``
+     - ``after_import_row(self, row, row_result, **kwargs)``
+     - * ``row_number`` now in ``kwargs``
+
+   * - ``import_row(self, row, instance_loader, using_transactions=True, dry_run=False, **kwargs)``
+     - ``import_row(self, row, instance_loader, **kwargs)``
+     - * ``dry_run`` param now in ``kwargs``
+       * ``using_transactions`` param now in ``kwargs``
+
+   * - ``save_instance(self, instance, is_create, using_transactions=True, dry_run=False)``
+     - ``save_instance(self, instance, is_create, row, ***kwargs)``
+     - * ``dry_run`` param now in ``kwargs``
+       * ``using_transactions`` param now in ``kwargs``
+       * ``row`` added as mandatory arg
+
+   * - ``save_m2m(self, obj, data, using_transactions, dry_run)``
+     - ``save_m2m(self, instance, row, **kwargs)``
+     - * ``dry_run`` param now in ``kwargs``
+       * ``using_transactions`` param now in ``kwargs``
+       * ``row`` added as mandatory arg
+       * ``obj`` renamed to ``instance``
+       * ``data`` renamed to ``row``
+
+   * - ``before_save_instance(self, instance, using_transactions, dry_run)``
+     - ``before_save_instance(self, instance, row, **kwargs)``
+     - * ``dry_run`` param now in ``kwargs``
+       * ``using_transactions`` param now in ``kwargs``
+       * ``row`` added as mandatory arg
+
+   * - ``after_save_instance(self, instance, using_transactions, dry_run)``
+     - ``after_save_instance(self, instance, row, **kwargs)``
+     - * ``dry_run`` param now in ``kwargs``
+       * ``using_transactions`` param now in ``kwargs``
+       * ``row`` added as mandatory arg
+
+   * - ``delete_instance(self, instance, using_transactions=True, dry_run=False)``
+     - ``delete_instance(self, instance, row, **kwargs)``
+     - * ``dry_run`` param now in ``kwargs``
+       * ``using_transactions`` param now in ``kwargs``
+       * ``row`` added as mandatory arg
+
+   * - ``before_delete_instance(self, instance, dry_run)``
+     - ``before_delete_instance(self, instance, row, **kwargs)``
+     - * ``dry_run`` param now in ``kwargs``
+       * ``using_transactions`` param now in ``kwargs``
+       * ``row`` added as mandatory arg
+
+   * - ``after_delete_instance(self, instance, dry_run)``
+     - ``after_delete_instance(self, instance, row, **kwargs)``
+     - * ``dry_run`` param now in ``kwargs``
+       * ``using_transactions`` param now in ``kwargs``
+       * ``row`` added as mandatory arg
+
+   * - ``before_export(self, queryset, *args, **kwargs)``
+     - ``before_export(self, queryset, **kwargs)``
+     - * unused ``*args`` list removed
+
+   * - ``after_export(self, queryset, data, *args, **kwargs)``
+     - ``after_export(self, queryset, dataset, **kwargs)``
+     - * unused ``*args`` list removed
+       * ``data`` renamed to ``dataset``
+
+   * - ``filter_export(self, queryset, *args, **kwargs)``
+     - ``filter_export(self, queryset, **kwargs)``
+     - * unused ``*args`` list removed
+
+   * - ``export_field(self, field, obj)``
+     - ``export_field(self, field, instance)``
+     - * ``obj`` renamed to ``instance``
+
+   * - ``export(self, *args, queryset=None, **kwargs)``
+     - ``export(self, queryset=None, **kwargs)``
+     - * unused ``*args`` list removed
+
+:class:`import_export.mixins.BaseImportMixin`
+---------------------------------------------
+
+Parameter changes
+^^^^^^^^^^^^^^^^^
+
+.. list-table::
+   :header-rows: 1
+
+   * - Previous
+     - New
+     - Summary
+
+   * - ``get_import_resource_kwargs(self, request, *args, **kwargs)``
+     - ``get_import_resource_kwargs(self, request, **kwargs)``
+     -  * ``using_transactions`` param now in ``kwargs``
+        * ``dry_run`` param now in ``kwargs``
+        * unused ``*args`` list removed
+
+
+:class:`import_export.mixins.BaseExportMixin`
+---------------------------------------------
+
+Parameter changes
+^^^^^^^^^^^^^^^^^
+
+.. list-table::
+   :header-rows: 1
+
+   * - Previous
+     - New
+     - Summary
+
+   * - ``get_export_resource_kwargs(self, request, *args, **kwargs)``
+     - ``get_export_resource_kwargs(self, request, **kwargs)``
+     -  * unused ``*args`` list removed
+
+   * - ``get_export_resource_kwargs(self, request, *args, **kwargs)``
+     - ``get_export_resource_kwargs(self, request, **kwargs)``
+     -  * unused ``*args`` list removed
+
+   * - ``get_data_for_export(self, request, *args, **kwargs)``
+     - ``get_data_for_export(self, request, queryset, **kwargs)``
+     -  * unused ``*args`` list removed
+
+
+:class:`import_export.fields.Field`
+-----------------------------------
+
+Parameter changes
+^^^^^^^^^^^^^^^^^
+
+.. list-table::
+   :header-rows: 1
+
+   * - Previous
+     - New
+     - Summary
+
+   * - ``clean(self, data, **kwargs)``
+     - ``clean(self, row, **kwargs)``
+     - * ``data`` renamed to ``row``
+
+   * - ``get_value(self, instance)``
+     - ``get_value(self, obj)``
+     - * ``obj`` renamed to ``instance``
+
+   * - ``save(self, obj, data, is_m2m=False, **kwargs)``
+     - ``save(self, instance, row, is_m2m=False, **kwargs)``
+     - * ``obj`` renamed to ``instance``
+       * ``data`` renamed to ``row``
+
+   * - ``export(self, obj)``
+     - ``export(self, instance)``
+     - * ``obj`` renamed to ``instance``
diff --git a/import_export/admin.py b/import_export/admin.py
index 1838a5174..031b41481 100644
--- a/import_export/admin.py
+++ b/import_export/admin.py
@@ -177,12 +177,10 @@ def process_dataset(
         **kwargs,
     ):
         res_kwargs = self.get_import_resource_kwargs(
-            request, *args, form=confirm_form, **kwargs
+            request, form=confirm_form, **kwargs
         )
         resource = self.choose_import_resource_class(confirm_form)(**res_kwargs)
-        imp_kwargs = self.get_import_data_kwargs(
-            request, *args, form=confirm_form, **kwargs
-        )
+        imp_kwargs = self.get_import_data_kwargs(request, form=confirm_form, **kwargs)
 
         return resource.import_data(
             dataset,
@@ -472,7 +470,7 @@ def import_action(self, request, *args, **kwargs):
                 if not import_form.errors:
                     # prepare kwargs for import data, if needed
                     res_kwargs = self.get_import_resource_kwargs(
-                        request, *args, form=import_form, **kwargs
+                        request, form=import_form, **kwargs
                     )
                     resource = self.choose_import_resource_class(import_form)(
                         **res_kwargs
@@ -500,7 +498,7 @@ def import_action(self, request, *args, **kwargs):
                         )
         else:
             res_kwargs = self.get_import_resource_kwargs(
-                request, *args, form=import_form, **kwargs
+                request, form=import_form, **kwargs
             )
             resource_classes = self.get_import_resource_classes()
             resources = [
diff --git a/import_export/fields.py b/import_export/fields.py
index e9949124d..a27329985 100644
--- a/import_export/fields.py
+++ b/import_export/fields.py
@@ -69,21 +69,20 @@ def __repr__(self):
             return "<%s: %s>" % (path, column_name)
         return "<%s>" % path
 
-    def clean(self, data, **kwargs):
+    def clean(self, row, **kwargs):
         """
         Translates the value stored in the imported datasource to an
         appropriate Python object and returns it.
         """
         try:
-            value = data[self.column_name]
+            value = row[self.column_name]
         except KeyError:
             raise KeyError(
                 "Column '%s' not found in dataset. Available "
-                "columns are: %s" % (self.column_name, list(data))
+                "columns are: %s" % (self.column_name, list(row))
             )
 
-        # If ValueError is raised here, import_obj() will handle it
-        value = self.widget.clean(value, row=data, **kwargs)
+        value = self.widget.clean(value, row=row, **kwargs)
 
         if value in self.empty_values and self.default != NOT_PROVIDED:
             if callable(self.default):
@@ -92,7 +91,7 @@ def clean(self, data, **kwargs):
 
         return value
 
-    def get_value(self, obj):
+    def get_value(self, instance):
         """
         Returns the value of the object's attribute.
         """
@@ -100,7 +99,7 @@ def get_value(self, obj):
             return None
 
         attrs = self.attribute.split("__")
-        value = obj
+        value = instance
 
         for attr in attrs:
             try:
@@ -118,7 +117,7 @@ def get_value(self, obj):
             value = value()
         return value
 
-    def save(self, obj, data, is_m2m=False, **kwargs):
+    def save(self, instance, row, is_m2m=False, **kwargs):
         """
         If this field is not declared readonly, the object's attribute will
         be set to the value returned by :meth:`~import_export.fields.Field.clean`.
@@ -126,26 +125,26 @@ def save(self, obj, data, is_m2m=False, **kwargs):
         if not self.readonly:
             attrs = self.attribute.split("__")
             for attr in attrs[:-1]:
-                obj = getattr(obj, attr, None)
-            cleaned = self.clean(data, **kwargs)
+                instance = getattr(instance, attr, None)
+            cleaned = self.clean(row, **kwargs)
             if cleaned is not None or self.saves_null_values:
                 if not is_m2m:
-                    setattr(obj, attrs[-1], cleaned)
+                    setattr(instance, attrs[-1], cleaned)
                 else:
                     if self.m2m_add:
-                        getattr(obj, attrs[-1]).add(*cleaned)
+                        getattr(instance, attrs[-1]).add(*cleaned)
                     else:
-                        getattr(obj, attrs[-1]).set(cleaned)
+                        getattr(instance, attrs[-1]).set(cleaned)
 
-    def export(self, obj):
+    def export(self, instance):
         """
-        Returns value from the provided object converted to export
+        Returns value from the provided instance converted to export
         representation.
         """
-        value = self.get_value(obj)
+        value = self.get_value(instance)
         if value is None:
             return ""
-        return self.widget.render(value, obj)
+        return self.widget.render(value, instance)
 
     def get_dehydrate_method(self, field_name=None):
         """
diff --git a/import_export/mixins.py b/import_export/mixins.py
index e57f3820c..6b536705d 100644
--- a/import_export/mixins.py
+++ b/import_export/mixins.py
@@ -69,8 +69,8 @@ def get_import_formats(self):
         """
         return [f for f in self.import_formats if f().can_import()]
 
-    def get_import_resource_kwargs(self, request, *args, **kwargs):
-        return self.get_resource_kwargs(request, *args, **kwargs)
+    def get_import_resource_kwargs(self, request, **kwargs):
+        return self.get_resource_kwargs(request, **kwargs)
 
     def choose_import_resource_class(self, form):
         resource_index = self.get_resource_index(form)
@@ -98,17 +98,15 @@ def choose_export_resource_class(self, form):
         resource_index = self.get_resource_index(form)
         return self.get_export_resource_classes()[resource_index]
 
-    def get_export_resource_kwargs(self, request, *args, **kwargs):
-        return self.get_resource_kwargs(request, *args, **kwargs)
+    def get_export_resource_kwargs(self, request, **kwargs):
+        return self.get_resource_kwargs(request, **kwargs)
 
-    def get_data_for_export(self, request, queryset, *args, **kwargs):
+    def get_data_for_export(self, request, queryset, **kwargs):
         export_form = kwargs.get("export_form")
         export_class = self.choose_export_resource_class(export_form)
-        export_resource_kwargs = self.get_export_resource_kwargs(
-            request, *args, **kwargs
-        )
+        export_resource_kwargs = self.get_export_resource_kwargs(request, **kwargs)
         cls = export_class(**export_resource_kwargs)
-        export_data = cls.export(*args, queryset=queryset, **kwargs)
+        export_data = cls.export(queryset=queryset, **kwargs)
         return export_data
 
     def get_export_filename(self, file_format):
diff --git a/import_export/resources.py b/import_export/resources.py
index 8b23aed45..7d9ada537 100644
--- a/import_export/resources.py
+++ b/import_export/resources.py
@@ -397,8 +397,8 @@ def get_or_init_instance(self, instance_loader, row):
         if not self._meta.force_init_instance:
             instance = self.get_instance(instance_loader, row)
             if instance:
-                return (instance, False)
-        return (self.init_instance(row), True)
+                return instance, False
+        return self.init_instance(row), True
 
     def get_import_id_fields(self):
         """ """
@@ -474,14 +474,14 @@ def validate_instance(
     ):
         """
         Takes any validation errors that were raised by
-        :meth:`~import_export.resources.Resource.import_obj`, and combines them
+        :meth:`~import_export.resources.Resource.import_instance`, and combines them
         with validation errors raised by the instance's ``full_clean()``
         method. The combined errors are then re-raised as single, multi-field
         ValidationError.
 
         If the ``clean_model_instances`` option is False, the instances's
         ``full_clean()`` method is not called, and only the errors raised by
-        ``import_obj()`` are re-raised.
+        ``import_instance()`` are re-raised.
         """
         if import_validation_errors is None:
             errors = {}
@@ -499,110 +499,175 @@ def validate_instance(
         if errors:
             raise ValidationError(errors)
 
-    def save_instance(
-        self, instance, is_create, using_transactions=True, dry_run=False
-    ):
-        """
+    def save_instance(self, instance, is_create, row, **kwargs):
+        r"""
         Takes care of saving the object to the database.
 
         Objects can be created in bulk if ``use_bulk`` is enabled.
 
         :param instance: The instance of the object to be persisted.
+
         :param is_create: A boolean flag to indicate whether this is a new object
         to be created, or an existing object to be updated.
-        :param using_transactions: A flag to indicate whether db transactions are used.
-        :param dry_run: A flag to indicate dry-run mode.
+
+        :param row: A dict representing the import row.
+
+        :param \**kwargs:
+            See :meth:`import_row
         """
-        self.before_save_instance(instance, using_transactions, dry_run)
+        self.before_save_instance(instance, row, **kwargs)
         if self._meta.use_bulk:
             if is_create:
                 self.create_instances.append(instance)
             else:
                 self.update_instances.append(instance)
         else:
-            if not using_transactions and dry_run:
+            if not self._is_using_transactions(kwargs) and self._is_dry_run(kwargs):
                 # we don't have transactions and we want to do a dry_run
                 pass
             else:
                 instance.save()
-        self.after_save_instance(instance, using_transactions, dry_run)
+        self.after_save_instance(instance, row, **kwargs)
 
-    def before_save_instance(self, instance, using_transactions, dry_run):
-        """
+    def before_save_instance(self, instance, row, **kwargs):
+        r"""
         Override to add additional logic. Does nothing by default.
+
+        :param instance: A new or existing model instance.
+
+        :param row: A ``dict`` containing key / value data for the row to be imported.
+
+        :param \**kwargs:
+            See :meth:`import_row`
         """
         pass
 
-    def after_save_instance(self, instance, using_transactions, dry_run):
-        """
+    def after_save_instance(self, instance, row, **kwargs):
+        r"""
         Override to add additional logic. Does nothing by default.
+
+        :param instance: A new or existing model instance.
+
+        :param row: A ``dict`` containing key / value data for the row to be imported.
+
+        :param \**kwargs:
+            See :meth:`import_row`
         """
         pass
 
-    def delete_instance(self, instance, using_transactions=True, dry_run=False):
-        """
+    def delete_instance(self, instance, row, **kwargs):
+        r"""
         Calls :meth:`instance.delete` as long as ``dry_run`` is not set.
         If ``use_bulk`` then instances are appended to a list for bulk import.
+
+        :param instance: A new or existing model instance.
+
+        :param row: A ``dict`` containing key / value data for the row to be imported.
+
+        :param \**kwargs:
+            See :meth:`import_row`
         """
-        self.before_delete_instance(instance, dry_run)
+        self.before_delete_instance(instance, row, **kwargs)
         if self._meta.use_bulk:
             self.delete_instances.append(instance)
         else:
-            if not using_transactions and dry_run:
+            if not self._is_using_transactions(kwargs) and self._is_dry_run(kwargs):
                 # we don't have transactions and we want to do a dry_run
                 pass
             else:
                 instance.delete()
-        self.after_delete_instance(instance, dry_run)
+        self.after_delete_instance(instance, row, **kwargs)
 
-    def before_delete_instance(self, instance, dry_run):
-        """
+    def before_delete_instance(self, instance, row, **kwargs):
+        r"""
         Override to add additional logic. Does nothing by default.
+
+        :param instance: A new or existing model instance.
+
+        :param row: A ``dict`` containing key / value data for the row to be imported.
+
+        :param \**kwargs:
+            See :meth:`import_row`
         """
         pass
 
-    def after_delete_instance(self, instance, dry_run):
-        """
+    def after_delete_instance(self, instance, row, **kwargs):
+        r"""
         Override to add additional logic. Does nothing by default.
+
+        :param instance: A new or existing model instance.
+
+        :param row: A ``dict`` containing key / value data for the row to be imported.
+
+        :param \**kwargs:
+            See :meth:`import_row`
         """
         pass
 
-    def import_field(self, field, obj, data, is_m2m=False, **kwargs):
-        """
-        Calls :meth:`import_export.fields.Field.save` if ``Field.attribute``
-        is specified, and ``Field.column_name`` is found in ``data``.
+    def import_field(self, field, instance, row, is_m2m=False, **kwargs):
+        r"""
+        Handles persistence of the field data.
+
+        :param field: A :class:`import_export.fields.Field` instance.
+
+        :param instance: A new or existing model instance.
+
+        :param row: A ``dict`` containing key / value data for the row to be imported.
+
+        :param is_m2m: A boolean value indicating whether or not this is a
+          many-to-many field.
+
+        :param \**kwargs:
+            See :meth:`import_row`
         """
-        if field.attribute and field.column_name in data:
-            field.save(obj, data, is_m2m, **kwargs)
+        if field.attribute and field.column_name in row:
+            field.save(instance, row, is_m2m, **kwargs)
 
     def get_import_fields(self):
         return [self.fields[f] for f in self.get_import_order()]
 
-    def import_obj(self, obj, data, dry_run, **kwargs):
-        """
+    def import_instance(self, instance, row, **kwargs):
+        r"""
         Traverses every field in this Resource and calls
         :meth:`~import_export.resources.Resource.import_field`. If
         ``import_field()`` results in a ``ValueError`` being raised for
         one of more fields, those errors are captured and reraised as a single,
-        multi-field ValidationError."""
+        multi-field ValidationError.
+
+        :param instance: A new or existing model instance.
+
+        :param row: A ``dict`` containing key / value data for the row to be imported.
+
+        :param \**kwargs:
+            See :meth:`import_row`
+        """
         errors = {}
         for field in self.get_import_fields():
             if isinstance(field.widget, widgets.ManyToManyWidget):
                 continue
             try:
-                self.import_field(field, obj, data, **kwargs)
+                self.import_field(field, instance, row, **kwargs)
             except ValueError as e:
                 errors[field.attribute] = ValidationError(force_str(e), code="invalid")
         if errors:
             raise ValidationError(errors)
 
-    def save_m2m(self, obj, data, using_transactions, dry_run):
-        """
+    def save_m2m(self, instance, row, **kwargs):
+        r"""
         Saves m2m fields.
 
         Model instance need to have a primary key value before
         a many-to-many relationship can be used.
+
+        :param instance: A new or existing model instance.
+
+        :param row: A ``dict`` containing key / value data for the row to be imported.
+
+        :param \**kwargs:
+            See :meth:`import_row`
         """
+        using_transactions = self._is_using_transactions(kwargs)
+        dry_run = self._is_dry_run(kwargs)
         if (not using_transactions and dry_run) or self._meta.use_bulk:
             # we don't have transactions and we want to do a dry_run
             # OR use_bulk is enabled (m2m operations are not supported
@@ -612,7 +677,7 @@ def save_m2m(self, obj, data, using_transactions, dry_run):
             for field in self.get_import_fields():
                 if not isinstance(field.widget, widgets.ManyToManyWidget):
                     continue
-                self.import_field(field, obj, data, True)
+                self.import_field(field, instance, row, True)
 
     def for_delete(self, row, instance):
         """
@@ -620,6 +685,10 @@ def for_delete(self, row, instance):
 
         Default implementation returns ``False``.
         Override this method to handle deletion.
+
+        :param row: A ``dict`` containing key / value data for the row to be imported.
+
+        :param instance: A new or existing model instance.
         """
         return False
 
@@ -650,6 +719,15 @@ def skip_row(self, instance, original, row, import_validation_errors=None):
                 # Add code here
                 return super().skip_row(instance, original, row,
                   import_validation_errors=import_validation_errors)
+
+        :param instance: A new or updated model instance.
+
+        :param original: The original persisted model instance.
+
+        :param row: A ``dict`` containing key / value data for the row to be imported.
+
+        :param import_validation_errors: A ``dict`` containing key / value data for any
+          identified validation errors.
         """
         if (
             not self._meta.skip_unchanged
@@ -690,40 +768,68 @@ def get_diff_headers(self):
         """
         return self.get_user_visible_headers()
 
-    def before_import(self, dataset, using_transactions, dry_run, **kwargs):
-        """
+    def before_import(self, dataset, **kwargs):
+        r"""
         Override to add additional logic. Does nothing by default.
+
+        :param dataset: A ``tablib.Dataset``.
+
+        :param \**kwargs:
+            See :meth:`import_row`
         """
         pass
 
-    def after_import(self, dataset, result, using_transactions, dry_run, **kwargs):
-        """
+    def after_import(self, dataset, result, **kwargs):
+        r"""
         Override to add additional logic. Does nothing by default.
+
+        :param dataset: A ``tablib.Dataset``.
+
+        :param result: A :class:`import_export.results.Result` implementation
+          containing a summary of the import.
+
+        :param \**kwargs:
+            See :meth:`import_row`
         """
         pass
 
-    def before_import_row(self, row, row_number=None, **kwargs):
-        """
+    def before_import_row(self, row, **kwargs):
+        r"""
         Override to add additional logic. Does nothing by default.
+
+        :param row: A ``dict`` containing key / value data for the row to be imported.
+
+        :param \**kwargs:
+            See :meth:`import_row`
         """
         pass
 
-    def after_import_row(self, row, row_result, row_number=None, **kwargs):
-        """
+    def after_import_row(self, row, row_result, **kwargs):
+        r"""
         Override to add additional logic. Does nothing by default.
 
-        :param row: A ``dict`` of the import row.
+        :param row: A ``dict`` containing key / value data for the row to be imported.
 
         :param row_result: A ``RowResult`` instance.
           References the persisted ``instance`` as an attribute.
 
-        :param row_number: The row number from the dataset.
+        :param \**kwargs:
+            See :meth:`import_row`
         """
         pass
 
-    def after_import_instance(self, instance, new, row_number=None, **kwargs):
-        """
+    def after_init_instance(self, instance, new, row, **kwargs):
+        r"""
         Override to add additional logic. Does nothing by default.
+
+        :param instance: A new or existing model instance.
+
+        :param new: a boolean flag indicating whether instance is new or existing.
+
+        :param row: A ``dict`` containing key / value data for the row to be imported.
+
+        :param \**kwargs:
+            See :meth:`import_row`
         """
         pass
 
@@ -735,22 +841,28 @@ def handle_import_error(self, result, error, raise_errors=False):
         if raise_errors:
             raise
 
-    def import_row(
-        self, row, instance_loader, using_transactions=True, dry_run=False, **kwargs
-    ):
-        """
+    def import_row(self, row, instance_loader, **kwargs):
+        r"""
         Imports data from ``tablib.Dataset``. Refer to :doc:`import_workflow`
         for a more complete description of the whole import process.
 
-        :param row: A ``dict`` of the row to import
+        :param row: A ``dict`` of the 'row' to import.
+          A row is a dict of data fields so can be a csv line, a JSON object,
+          a YAML object etc.
 
-        :param instance_loader: The instance loader to be used to load the row
+        :param instance_loader: The instance loader to be used to load the model
+          instance associated with the row (if there is one).
 
-        :param using_transactions: If ``using_transactions`` is set, a transaction
-            is being used to wrap the import
+        :param \**kwargs:
+            See below.
 
-        :param dry_run: If ``dry_run`` is set, or error occurs, transaction
-            will be rolled back.
+        :Keyword Arguments:
+            * dry_run (``boolean``) --
+              A True value means that no data should be persisted.
+            * use_transactions (``boolean``) --
+              A True value means that transactions will be rolled back.
+            * row_number  (``int``) --
+              The index of the row being imported.
         """
         skip_diff = self._meta.skip_diff
         row_result = self.get_row_result_class()()
@@ -760,7 +872,7 @@ def import_row(
         try:
             self.before_import_row(row, **kwargs)
             instance, new = self.get_or_init_instance(instance_loader, row)
-            self.after_import_instance(instance, new, **kwargs)
+            self.after_init_instance(instance, new, row, **kwargs)
             if new:
                 row_result.import_type = RowResult.IMPORT_TYPE_NEW
             else:
@@ -778,17 +890,17 @@ def import_row(
                     row_result.add_instance_info(instance)
                     if self._meta.store_instance:
                         row_result.instance = instance
-                    self.delete_instance(instance, using_transactions, dry_run)
+                    self.delete_instance(instance, row, **kwargs)
                     if not skip_diff:
                         diff.compare_with(self, None)
             else:
                 import_validation_errors = {}
                 try:
-                    self.import_obj(instance, row, dry_run, **kwargs)
+                    self.import_instance(instance, row, **kwargs)
                 except ValidationError as e:
-                    # Validation errors from import_obj() are passed on to
-                    # validate_instance(), where they can be combined with model
-                    # instance validation errors if necessary
+                    # Validation errors are passed on to validate_instance(),
+                    # where they can be combined with model instance validation
+                    # errors if necessary
                     import_validation_errors = e.update_error_dict(
                         import_validation_errors
                     )
@@ -797,8 +909,8 @@ def import_row(
                     row_result.import_type = RowResult.IMPORT_TYPE_SKIP
                 else:
                     self.validate_instance(instance, import_validation_errors)
-                    self.save_instance(instance, new, using_transactions, dry_run)
-                    self.save_m2m(instance, row, using_transactions, dry_run)
+                    self.save_instance(instance, new, row, **kwargs)
+                    self.save_m2m(instance, row, **kwargs)
                 row_result.add_instance_info(instance)
                 if self._meta.store_instance:
                     row_result.instance = instance
@@ -835,11 +947,11 @@ def import_data(
         rollback_on_validation_errors=False,
         **kwargs,
     ):
-        """
+        r"""
         Imports data from ``tablib.Dataset``. Refer to :doc:`import_workflow`
         for a more complete description of the whole import process.
 
-        :param dataset: A ``tablib.Dataset``
+        :param dataset: A ``tablib.Dataset``.
 
         :param raise_errors: Whether errors should be printed to the end user
             or raised regularly.
@@ -851,11 +963,14 @@ def import_data(
             failed rows.
 
         :param rollback_on_validation_errors: If both ``use_transactions`` and
-        ``rollback_on_validation_errors`` are set to ``True``, the import process will
-        be rolled back in case of ValidationError.
+          ``rollback_on_validation_errors`` are set to ``True``, the import process will
+          be rolled back in case of ValidationError.
 
         :param dry_run: If ``dry_run`` is set, or an error occurs, if a transaction
             is being used, it will be rolled back.
+
+        :param \**kwargs:
+            Metadata which may be associated with the import.
         """
 
         if use_transactions is None:
@@ -901,7 +1016,6 @@ def import_data_inner(
         raise_errors,
         using_transactions,
         collect_failed_rows,
-        rollback_on_validation_errors=None,
         **kwargs,
     ):
         result = self.get_result_class()()
@@ -911,7 +1025,7 @@ def import_data_inner(
 
         try:
             with atomic_if_using_transaction(using_transactions, using=db_connection):
-                self.before_import(dataset, using_transactions, dry_run, **kwargs)
+                self.before_import(dataset, **kwargs)
         except Exception as e:
             self.handle_import_error(result, e, raise_errors)
 
@@ -929,12 +1043,16 @@ def import_data_inner(
             with atomic_if_using_transaction(
                 using_transactions and not self._meta.use_bulk, using=db_connection
             ):
+                kwargs.update(
+                    {
+                        "dry_run": dry_run,
+                        "using_transactions": using_transactions,
+                        "row_number": i,
+                    }
+                )
                 row_result = self.import_row(
                     row,
                     instance_loader,
-                    using_transactions=using_transactions,
-                    dry_run=dry_run,
-                    row_number=i,
                     **kwargs,
                 )
             if self._meta.use_bulk:
@@ -1005,9 +1123,7 @@ def import_data_inner(
 
         try:
             with atomic_if_using_transaction(using_transactions, using=db_connection):
-                self.after_import(
-                    dataset, result, using_transactions, dry_run, **kwargs
-                )
+                self.after_import(dataset, result, **kwargs)
         except Exception as e:
             self.handle_import_error(result, e, raise_errors)
 
@@ -1019,38 +1135,59 @@ def get_import_order(self):
     def get_export_order(self):
         return self._get_ordered_field_names("export_order")
 
-    def before_export(self, queryset, *args, **kwargs):
-        """
+    def before_export(self, queryset, **kwargs):
+        r"""
         Override to add additional logic. Does nothing by default.
+
+        :param queryset: The queryset for export.
+
+        :param \**kwargs:
+            Metadata which may be associated with the export.
         """
         pass
 
-    def after_export(self, queryset, data, *args, **kwargs):
-        """
+    def after_export(self, queryset, dataset, **kwargs):
+        r"""
         Override to add additional logic. Does nothing by default.
+
+        :param queryset: The queryset for export.
+
+        :param dataset: A ``tablib.Dataset``.
+
+        :param \**kwargs:
+            Metadata which may be associated with the export.
         """
         pass
 
-    def filter_export(self, queryset, *args, **kwargs):
-        """
+    def filter_export(self, queryset, **kwargs):
+        r"""
         Override to filter an export queryset.
+
+        :param queryset: The queryset for export (optional).
+
+        :param \**kwargs:
+            Metadata which may be associated with the export.
+
+        :returns: The filtered queryset.
         """
         return queryset
 
-    def export_field(self, field, obj):
+    def export_field(self, field, instance):
         field_name = self.get_field_name(field)
         dehydrate_method = field.get_dehydrate_method(field_name)
 
         method = getattr(self, dehydrate_method, None)
         if method is not None:
-            return method(obj)
-        return field.export(obj)
+            return method(instance)
+        return field.export(instance)
 
     def get_export_fields(self):
         return [self.fields[f] for f in self.get_export_order()]
 
-    def export_resource(self, obj):
-        return [self.export_field(field, obj) for field in self.get_export_fields()]
+    def export_resource(self, instance):
+        return [
+            self.export_field(field, instance) for field in self.get_export_fields()
+        ]
 
     def get_export_headers(self):
         headers = [force_str(field.column_name) for field in self.get_export_fields()]
@@ -1082,23 +1219,26 @@ def iter_queryset(self, queryset):
         else:
             yield from queryset.iterator(chunk_size=self.get_chunk_size())
 
-    def export(self, *args, queryset=None, **kwargs):
+    def export(self, queryset=None, **kwargs):
         """
         Exports a resource.
-        :returns: Dataset object.
+
+        :param queryset: The queryset for export (optional).
+
+        :returns: A ``tablib.Dataset``.
         """
-        self.before_export(queryset, *args, **kwargs)
+        self.before_export(queryset, **kwargs)
 
         if queryset is None:
             queryset = self.get_queryset()
-        queryset = self.filter_export(queryset, *args, **kwargs)
+        queryset = self.filter_export(queryset, **kwargs)
         headers = self.get_export_headers()
         dataset = tablib.Dataset(headers=headers)
 
         for obj in self.iter_queryset(queryset):
             dataset.append(self.export_resource(obj))
 
-        self.after_export(queryset, dataset, *args, **kwargs)
+        self.after_export(queryset, dataset, **kwargs)
 
         return dataset
 
@@ -1115,6 +1255,12 @@ def _get_ordered_field_names(self, order_field):
         [order.append(f) for f in defined_fields if f not in order]
         return tuple(order) + tuple(k for k in self.fields if k not in order)
 
+    def _is_using_transactions(self, kwargs):
+        return kwargs.get("using_transactions", False)
+
+    def _is_dry_run(self, kwargs):
+        return kwargs.get("dry_run", False)
+
     def _check_import_id_fields(self, headers):
         import_id_fields = [self.fields[f] for f in self.get_import_id_fields()]
         missing_fields = list()
@@ -1352,11 +1498,12 @@ def init_instance(self, row=None):
         """
         return self._meta.model()
 
-    def after_import(self, dataset, result, using_transactions, dry_run, **kwargs):
+    def after_import(self, dataset, result, **kwargs):
         """
         Reset the SQL sequences after new objects are imported
         """
         # Adapted from django's loaddata
+        dry_run = self._is_dry_run(kwargs)
         if not dry_run and any(
             r.import_type == RowResult.IMPORT_TYPE_NEW for r in result.rows
         ):


Test patch:
diff --git a/tests/core/admin.py b/tests/core/admin.py
index 0630653ec..c73d4a94e 100644
--- a/tests/core/admin.py
+++ b/tests/core/admin.py
@@ -73,15 +73,15 @@ def get_confirm_form_initial(self, request, import_form):
             initial["author"] = import_form.cleaned_data["author"].id
         return initial
 
-    def get_import_resource_kwargs(self, request, *args, **kwargs):
+    def get_import_resource_kwargs(self, request, **kwargs):
         # update resource kwargs so that the Resource is passed the authenticated user
         # This is included as an example of how dynamic values
         # can be passed to resources
-        kwargs = super().get_resource_kwargs(request, *args, **kwargs)
+        kwargs = super().get_resource_kwargs(request, **kwargs)
         kwargs.update({"user": request.user})
         return kwargs
 
-    def get_export_resource_kwargs(self, request, *args, **kwargs):
+    def get_export_resource_kwargs(self, request, **kwargs):
         # this is overridden to demonstrate that custom form fields can be used
         # to override the export query.
         # The dict returned here will be passed as kwargs to EBookResource
diff --git a/tests/core/tests/test_mixins.py b/tests/core/tests/test_mixins.py
index 00651056a..575c81fb6 100644
--- a/tests/core/tests/test_mixins.py
+++ b/tests/core/tests/test_mixins.py
@@ -218,12 +218,11 @@ def test_choose_import_resource_class(self, form):
 
 class BaseExportMixinTest(TestCase):
     class TestBaseExportMixin(mixins.BaseExportMixin):
-        def get_export_resource_kwargs(self, request, *args, **kwargs):
-            self.args = args
+        def get_export_resource_kwargs(self, request, **kwargs):
             self.kwargs = kwargs
-            return super().get_resource_kwargs(request, *args, **kwargs)
+            return super().get_resource_kwargs(request, **kwargs)
 
-    def test_get_data_for_export_sets_args_and_kwargs(self):
+    def test_get_data_for_export_sets_kwargs(self):
         """
         issue 1268
         Ensure that get_export_resource_kwargs() handles the args and kwargs arguments.
@@ -231,12 +230,8 @@ def test_get_data_for_export_sets_args_and_kwargs(self):
         request = MagicMock(spec=HttpRequest)
         m = self.TestBaseExportMixin()
         m.model = Book
-        target_args = (1,)
         target_kwargs = {"a": 1}
-        m.get_data_for_export(
-            request, Book.objects.none(), *target_args, **target_kwargs
-        )
-        self.assertEqual(m.args, target_args)
+        m.get_data_for_export(request, Book.objects.none(), **target_kwargs)
         self.assertEqual(m.kwargs, target_kwargs)
 
     def test_get_export_formats(self):
diff --git a/tests/core/tests/test_resources.py b/tests/core/tests/test_resources.py
index 7319778e8..ae154ed42 100644
--- a/tests/core/tests/test_resources.py
+++ b/tests/core/tests/test_resources.py
@@ -115,7 +115,8 @@ def test_get_export_headers_order(self):
     def test_default_after_import(self):
         self.assertIsNone(
             self.my_resource.after_import(
-                tablib.Dataset(), results.Result(), False, False
+                tablib.Dataset(),
+                results.Result(),
             )
         )
 
@@ -226,10 +227,12 @@ def __init__(self, *args, **kwargs):
         self.after_lines = []
         return super().__init__(*args, **kwargs)
 
-    def before_import_row(self, row, row_number=None, **kwargs):
+    def before_import_row(self, row, **kwargs):
+        row_number = kwargs.pop("row_number")
         self.before_lines.append(row_number)
 
-    def after_import_row(self, row, row_result, row_number=None, **kwargs):
+    def after_import_row(self, row, row_result, **kwargs):
+        row_number = kwargs.pop("row_number")
         self.after_lines.append(row_number)
 
 
@@ -428,16 +431,14 @@ def test_export_prefetch_related(self):
 
     def test_export_handles_named_queryset_parameter(self):
         class _BookResource(BookResource):
-            def before_export(self, queryset, *args, **kwargs):
+            def before_export(self, queryset, **kwargs):
                 self.qs = queryset
-                self.args_ = args
                 self.kwargs_ = kwargs
 
         self.resource = _BookResource()
         # when queryset is supplied, it should be passed to before_export()
-        self.resource.export(1, 2, 3, queryset=Book.objects.all(), **{"a": 1})
+        self.resource.export(queryset=Book.objects.all(), **{"a": 1})
         self.assertEqual(Book.objects.count(), len(self.resource.qs))
-        self.assertEqual((1, 2, 3), self.resource.args_)
         self.assertEqual(dict(a=1), self.resource.kwargs_)
 
     def test_iter_queryset(self):
@@ -834,24 +835,25 @@ class Meta:
 
     def test_save_instance_with_dry_run_flag(self):
         class B(BookResource):
-            def before_save_instance(self, instance, using_transactions, dry_run):
-                super().before_save_instance(instance, using_transactions, dry_run)
+            def before_save_instance(self, instance, row, **kwargs):
+                super().before_save_instance(instance, row, **kwargs)
+                dry_run = kwargs.get("dry_run", False)
                 if dry_run:
                     self.before_save_instance_dry_run = True
                 else:
                     self.before_save_instance_dry_run = False
 
-            def save_instance(
-                self, instance, new, using_transactions=True, dry_run=False
-            ):
-                super().save_instance(instance, new, using_transactions, dry_run)
+            def save_instance(self, instance, new, row, **kwargs):
+                super().save_instance(instance, new, row, **kwargs)
+                dry_run = kwargs.get("dry_run", False)
                 if dry_run:
                     self.save_instance_dry_run = True
                 else:
                     self.save_instance_dry_run = False
 
-            def after_save_instance(self, instance, using_transactions, dry_run):
-                super().after_save_instance(instance, using_transactions, dry_run)
+            def after_save_instance(self, instance, row, **kwargs):
+                super().after_save_instance(instance, row, **kwargs)
+                dry_run = kwargs.get("dry_run", False)
                 if dry_run:
                     self.after_save_instance_dry_run = True
                 else:
@@ -872,14 +874,16 @@ def after_save_instance(self, instance, using_transactions, dry_run):
     def test_save_instance_noop(self, mock_book):
         book = Book.objects.first()
         self.resource.save_instance(
-            book, is_create=False, using_transactions=False, dry_run=True
+            book, False, None, using_transactions=False, dry_run=True
         )
         self.assertEqual(0, mock_book.call_count)
 
     @mock.patch("core.models.Book.save")
     def test_delete_instance_noop(self, mock_book):
         book = Book.objects.first()
-        self.resource.delete_instance(book, using_transactions=False, dry_run=True)
+        self.resource.delete_instance(
+            book, None, using_transactions=False, dry_run=True
+        )
         self.assertEqual(0, mock_book.call_count)
 
     def test_delete_instance_with_dry_run_flag(self):
@@ -889,22 +893,25 @@ class B(BookResource):
             def for_delete(self, row, instance):
                 return self.fields["delete"].clean(row)
 
-            def before_delete_instance(self, instance, dry_run):
-                super().before_delete_instance(instance, dry_run)
+            def before_delete_instance(self, instance, row, **kwargs):
+                super().before_delete_instance(instance, row, **kwargs)
+                dry_run = kwargs.get("dry_run", False)
                 if dry_run:
                     self.before_delete_instance_dry_run = True
                 else:
                     self.before_delete_instance_dry_run = False
 
-            def delete_instance(self, instance, using_transactions=True, dry_run=False):
-                super().delete_instance(instance, using_transactions, dry_run)
+            def delete_instance(self, instance, row, **kwargs):
+                super().delete_instance(instance, row, **kwargs)
+                dry_run = kwargs.get("dry_run", False)
                 if dry_run:
                     self.delete_instance_dry_run = True
                 else:
                     self.delete_instance_dry_run = False
 
-            def after_delete_instance(self, instance, dry_run):
-                super().after_delete_instance(instance, dry_run)
+            def after_delete_instance(self, instance, row, **kwargs):
+                super().after_delete_instance(instance, row, **kwargs)
+                dry_run = kwargs.get("dry_run", False)
                 if dry_run:
                     self.after_delete_instance_dry_run = True
                 else:
@@ -1201,7 +1208,7 @@ def attempted_save(instance, new, using_transactions, real_dry_run):
 
     def test_before_import_access_to_kwargs(self):
         class B(BookResource):
-            def before_import(self, dataset, using_transactions, dry_run, **kwargs):
+            def before_import(self, dataset, **kwargs):
                 if "extra_arg" in kwargs:
                     dataset.headers[dataset.headers.index("author_email")] = "old_email"
                     dataset.insert_col(
@@ -1219,7 +1226,7 @@ def before_import(self, dataset, using_transactions, dry_run, **kwargs):
 
     def test_before_import_raises_error(self):
         class B(BookResource):
-            def before_import(self, dataset, using_transactions, dry_run, **kwargs):
+            def before_import(self, dataset, **kwargs):
                 raise Exception("This is an invalid dataset")
 
         resource = B()
@@ -1331,7 +1338,9 @@ class Meta:
                 model = Entry
                 fields = ("id",)
 
-            def after_save_instance(self, instance, using_transactions, dry_run):
+            def after_save_instance(self, instance, row, **kwargs):
+                using_transactions = kwargs.get("using_transactions", False)
+                dry_run = kwargs.get("dry_run", False)
                 if not using_transactions and dry_run:
                     # we don't have transactions and we want to do a dry_run
                     pass