debian-django-import-export/docs/getting_started.rst

350 lines
10 KiB
ReStructuredText

===============
Getting started
===============
For example purposes, we'll use a simplified book app. Here is our
``models.py``::
# app/models.py
class Author(models.Model):
name = models.CharField(max_length=100)
def __unicode__(self):
return self.name
class Category(models.Model):
name = models.CharField(max_length=100)
def __unicode__(self):
return self.name
class Book(models.Model):
name = models.CharField('Book name', max_length=100)
author = models.ForeignKey(Author, blank=True, null=True)
author_email = models.EmailField('Author email', max_length=75, blank=True)
imported = models.BooleanField(default=False)
published = models.DateField('Published', blank=True, null=True)
price = models.DecimalField(max_digits=10, decimal_places=2, null=True, blank=True)
categories = models.ManyToManyField(Category, blank=True)
def __unicode__(self):
return self.name
.. _base-modelresource:
Creating import-export resource
===============================
To integrate `django-import-export` with our ``Book`` model, we will create a
:class:`~import_export.resources.ModelResource` class in ``admin.py`` that will
describe how this resource can be imported or exported::
# app/admin.py
from import_export import resources
from core.models import Book
class BookResource(resources.ModelResource):
class Meta:
model = Book
Exporting data
==============
Now that we have defined a :class:`~import_export.resources.ModelResource` class,
we can export books::
>>> from app.admin import BookResource
>>> dataset = BookResource().export()
>>> print(dataset.csv)
id,name,author,author_email,imported,published,price,categories
2,Some book,1,,0,2012-12-05,8.85,1
Customize resource options
==========================
By default :class:`~import_export.resources.ModelResource` introspects model
fields and creates :class:`~import_export.fields.Field`-attributes with an
appropriate :class:`~import_export.widgets.Widget` for each field.
To affect which model fields will be included in an import-export
resource, use the ``fields`` option to whitelist fields::
class BookResource(resources.ModelResource):
class Meta:
model = Book
fields = ('id', 'name', 'price',)
Or the ``exclude`` option to blacklist fields::
class BookResource(resources.ModelResource):
class Meta:
model = Book
exclude = ('imported', )
An explicit order for exporting fields can be set using the ``export_order`` option::
class BookResource(resources.ModelResource):
class Meta:
model = Book
fields = ('id', 'name', 'author', 'price',)
export_order = ('id', 'price', 'author', 'name')
The default field for object identification is ``id``, you can optionally set which fields are used as the ``id`` when importing::
class BookResource(resources.ModelResource):
class Meta:
model = Book
import_id_fields = ('isbn',)
fields = ('isbn', 'name', 'author', 'price',)
When defining :class:`~import_export.resources.ModelResource` fields it is possible to follow
model relationships::
class BookResource(resources.ModelResource):
class Meta:
model = Book
fields = ('author__name',)
.. note::
Following relationship fields sets ``field`` as readonly, meaning
this field will be skipped when importing data.
By default all records will be imported, even if no changes are detected.
This can be changed setting the ``skip_unchanged`` option. Also, the ``report_skipped`` option
controls whether skipped records appear in the import ``Result`` object, and if using the admin
whether skipped records will show in the import preview page::
class BookResource(resources.ModelResource):
class Meta:
model = Book
skip_unchanged = True
report_skipped = False
fields = ('id', 'name', 'price',)
.. seealso::
:doc:`/api_resources`
Declaring fields
================
It is possible to override a resource field to change some of its
options::
from import_export.fields import Field
class BookResource(resources.ModelResource):
published = Field(attribute='published', column_name='published_date')
class Meta:
model = Book
Other fields that don't exist in the target model may be added::
from import_export.fields import Field
class BookResource(resources.ModelResource):
myfield = Field(column_name='myfield')
class Meta:
model = Book
.. seealso::
:doc:`/api_fields`
Available field types and options.
Advanced data manipulation
==========================
Not all data can be easily extracted from an object/model attribute.
In order to turn complicated data model into a (generally simpler) processed
data structure, ``dehydrate_<fieldname>`` method should be defined::
from import_export.fields import Field
class BookResource(resources.ModelResource):
full_title = Field()
class Meta:
model = Book
def dehydrate_full_title(self, book):
return '%s by %s' % (book.name, book.author.name)
Customize widgets
=================
A :class:`~import_export.resources.ModelResource` creates a field with a
default widget for a given field type. If the widget should be initialized
with different arguments, set the ``widgets`` dict.
In this example widget, the ``published`` field is overriden to use a
different date format. This format will be used both for importing
and exporting resource.
::
class BookResource(resources.ModelResource):
class Meta:
model = Book
widgets = {
'published': {'format': '%d.%m.%Y'},
}
.. seealso::
:doc:`/api_widgets`
available widget types and options.
Importing data
==============
Let's import some data!
.. code-block:: python
:linenos:
:emphasize-lines: 4,5
>>> import tablib
>>> from import_export import resources
>>> from core.models import Book
>>> book_resource = resources.modelresource_factory(model=Book)()
>>> dataset = tablib.Dataset(['', 'New book'], headers=['id', 'name'])
>>> result = book_resource.import_data(dataset, dry_run=True)
>>> print(result.has_errors())
False
>>> result = book_resource.import_data(dataset, dry_run=False)
In the fourth line we use :func:`~import_export.resources.modelresource_factory`
to create a default :class:`~import_export.resources.ModelResource`.
The ModelResource class created this way is equal to the one shown in the
example in section :ref:`base-modelresource`.
In fifth line a :class:`~tablib.Dataset` with columns ``id`` and ``name``, and one book entry, are created. A field for a primary key field (in this case, ``id``) always needs to be present.
In the rest of the code we first pretend to import data using
:meth:`~import_export.resources.Resource.import_data` and ``dry_run`` set,
then check for any errors and actually import data this time.
.. seealso::
:doc:`/import_workflow`
for a detailed description of the import workflow and its customization options.
Deleting data
-------------
To delete objects during import, implement the
:meth:`~import_export.resources.Resource.for_delete` method on
your :class:`~import_export.resources.Resource` class.
The following is an example resource which expects a ``delete`` field in the
dataset. An import using this resource will delete model instances for rows
that have their column ``delete`` set to ``1``::
class BookResource(resources.ModelResource):
delete = fields.Field(widget=widgets.BooleanWidget())
def for_delete(self, row, instance):
return self.fields['delete'].clean(row)
class Meta:
model = Book
Signals
=======
To hook in the import export workflow, you can connect to ``post_import``, ``post_export`` signals::
from django.dispatch import receiver
from import_export.signals import post_import, post_export
@receiver(post_import, dispatch_uid='balabala...')
def _post_import(model, **kwargs):
# model is the actual model instance which after import
pass
@receiver(post_export, dispatch_uid='balabala...')
def _post_export(model, **kwargs):
# model is the actual model instance which after export
pass
.. _admin-integration:
Admin integration
=================
Exporting via list filters
--------------------------
Admin integration is achieved by subclassing
:class:`~import_export.admin.ImportExportModelAdmin` or one of the available
mixins (:class:`~import_export.admin.ImportMixin`,
:class:`~import_export.admin.ExportMixin`,
:class:`~import_export.admin.ImportExportMixin`)::
# app/admin.py
from import_export.admin import ImportExportModelAdmin
class BookAdmin(ImportExportModelAdmin):
resource_class = BookResource
.. figure:: _static/images/django-import-export-change.png
A screenshot of the change view with Import and Export buttons.
.. figure:: _static/images/django-import-export-import.png
A screenshot of the import view.
.. figure:: _static/images/django-import-export-import-confirm.png
A screenshot of the confirm import view.
Exporting via admin action
--------------------------
Another approach to exporting data is by subclassing
:class:`~import_export.admin.ImportExportActionModelAdmin` which implements
export as an admin action. As a result it's possible to export a list of
objects selected on the change list page::
# app/admin.py
from import_export.admin import ImportExportActionModelAdmin
class BookAdmin(ImportExportActionModelAdmin):
pass
.. figure:: _static/images/django-import-export-action.png
A screenshot of the change view with Import and Export as an admin action.
.. seealso::
:doc:`/api_admin`
available mixins and options.