summaryrefslogtreecommitdiffstats
path: root/docs/getting_started.rst
blob: 0402aee9cde71cd8a6bca7c91300d63675844c5f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
===============
Getting started
===============

For example purposes, we'll use a 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


.. _base-modelresource:

Creating import-export resource
-------------------------------

To integrate `django-import-export` with ``Book`` model, we will create
a resource class in ``admin.py`` 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

Exporting data
--------------

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

Customize resource options
--------------------------

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`
        

Declaring fields
----------------

It is possible to override a resource field to change some of its
options::

    from import_export import fields

    class BookResource(resources.ModelResource):
        published = fields.Field(column_name='published_date')
        
        class Meta:
            model = Book

Other fields that don't exist 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.


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 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)


Customize widgets
-----------------

``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 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.

Deleting data
^^^^^^^^^^^^^

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
-----------------

Admin integration is achived by subclassing (in ``admin.py``)
``ImportExportModelAdmin`` or one of the available mixins (``ImportMixin``, 
``ExportMixin``, or ``ImportExportMixin``)::

    from import_export.admin import ImportExportModelAdmin


    class BookAdmin(ImportExportModelAdmin):
        resource_class = BookResource
        pass

.. 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.

|

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


.. 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.