For example purposes, we'll be use simplified book app, here is our
core.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
To integrate django-import-export with Book
model, we will create
a resource class that will describe how this resource can be imported or
exported.
from import_export import resources from core.models import Book class BookResource(resources.ModelResource): class Meta: model = Book
Now that we have defined a resource class, we can export books:
>>> 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
By default ModelResource
introspects model fields and creates
import_export.fields.Field
attributes with an appropriate widget
for each field.
To affect which model fields will be included in an import-export
resource, use the fields
option to whitelist fields or exclude
option to blacklist fields:
class BookResource(resources.ModelResource): class Meta: model = Book exclude = ('imported', )
When defining 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.
.. seealso:: :doc:`/api_resources`
It is possible to override a resource field to change some of it's options:
from import_export import fields class BookResource(resources.ModelResource): published = fields.Field(column_name='published_date') class Meta: model = Book
Other fields that are not existing in the target model may be added:
from import_export import fields class BookResource(resources.ModelResource): myfield = fields.Field(column_name='myfield') class Meta: model = Book
.. seealso:: :doc:`/api_fields` Available field types and options.
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 import fields class BookResource(resources.ModelResource): full_title = fields.Field() class Meta: model = Book def dehydrate_full_title(self, book): return '%s by %s' % (book.name, book.name.author)
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.
Let's import data:
>>> 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 4th line we use modelresource_factory
to create a default
ModelResource
. ModelResource class created this way is equal
as in :ref:`base-modelresource`.
In 5th line a Dataset
with subset of Book
fields is created.
In rest of code we first pretend to import data with dry_run
set, then
check for any errors and import data.
.. seealso:: :doc:`/import_workflow` for detailed import workflow descripton and customization options.
To delete objects during import, implement for_delete
method on resource
class.
Example resource with delete
field:
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
Import of this resource will delete model instances for rows
that have column delete
set to 1
.
Admin integration is achived by subclassing
ImportExportModelAdmin
or one of the available mixins (ImportMixin
,
ExportMixin
, or ImportExportMixin
):
from import_export.admin import ImportExportModelAdmin class BookAdmin(ImportExportModelAdmin): resource_class = BookResource pass
Another approach to exporting data is by subclassing
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:
from import_export.admin import ImportExportActionModelAdmin class BookAdmin(ImportExportActionModelAdmin): resource_class = BookResource pass
.. seealso:: :doc:`/api_admin` available mixins and options.