0
# Resources and Fields
1
2
Core system for defining how Django models map to import/export data, including field mapping, data transformation, and business logic hooks.
3
4
## Capabilities
5
6
### Resource Base Class
7
8
The base Resource class provides the foundation for all import/export operations, with extensive hooks for customization.
9
10
```python { .api }
11
class Resource(metaclass=DeclarativeMetaclass):
12
def __init__(self, **kwargs):
13
"""
14
Initialize resource with optional kwargs for dynamic configuration.
15
16
Parameters:
17
- **kwargs: Dynamic values to enhance import/exports
18
"""
19
20
def import_data(self, dataset, dry_run=False, raise_errors=False, use_transactions=None, collect_failed_rows=False, rollback_on_validation_errors=False, **kwargs):
21
"""
22
Import data from dataset with comprehensive error handling and transaction support.
23
24
Parameters:
25
- dataset: tablib.Dataset containing import data
26
- dry_run: bool, perform validation without saving
27
- raise_errors: bool, raise exceptions on errors
28
- use_transactions: bool, use database transactions
29
- collect_failed_rows: bool, collect failed rows for analysis
30
- rollback_on_validation_errors: bool, rollback on validation errors
31
- **kwargs: Additional import options
32
33
Returns:
34
Result object containing import results and errors
35
"""
36
37
def export(self, queryset=None, **kwargs):
38
"""
39
Export data to dataset format.
40
41
Parameters:
42
- queryset: Django QuerySet to export (defaults to all instances)
43
- **kwargs: Export configuration options
44
45
Returns:
46
tablib.Dataset containing exported data
47
"""
48
49
def import_row(self, row, instance_loader, **kwargs):
50
"""
51
Import a single row of data.
52
53
Parameters:
54
- row: dict, single row data
55
- instance_loader: Instance loader for retrieving existing instances
56
- **kwargs: Row processing options
57
58
Returns:
59
RowResult object
60
"""
61
62
def get_or_init_instance(self, instance_loader, row):
63
"""
64
Get existing instance or initialize new one for row.
65
66
Parameters:
67
- instance_loader: Instance loader
68
- row: dict, row data
69
70
Returns:
71
Tuple of (instance, created_flag)
72
"""
73
74
def get_instance(self, instance_loader, row):
75
"""
76
Get existing instance for row data.
77
78
Parameters:
79
- instance_loader: Instance loader
80
- row: dict, row data
81
82
Returns:
83
Model instance or None
84
"""
85
86
def init_instance(self, row=None):
87
"""
88
Initialize new instance.
89
90
Parameters:
91
- row: dict, optional row data
92
93
Returns:
94
New model instance
95
"""
96
97
def validate_instance(self, instance, import_validation_errors=None, validate_unique=True):
98
"""
99
Validate model instance before saving.
100
101
Parameters:
102
- instance: Model instance to validate
103
- import_validation_errors: List to collect validation errors
104
- validate_unique: bool, perform unique validation
105
"""
106
107
def save_instance(self, instance, is_create, row, **kwargs):
108
"""
109
Save model instance to database.
110
111
Parameters:
112
- instance: Model instance to save
113
- is_create: bool, whether this is a new instance
114
- row: dict, row data
115
- **kwargs: Save options
116
"""
117
118
def delete_instance(self, instance, row, **kwargs):
119
"""
120
Delete model instance from database.
121
122
Parameters:
123
- instance: Model instance to delete
124
- row: dict, row data
125
- **kwargs: Delete options
126
"""
127
128
# Bulk operation methods
129
def bulk_create(self, using_transactions, dry_run, raise_errors, batch_size=None, result=None):
130
"""
131
Perform bulk creation of instances for performance optimization.
132
133
Parameters:
134
- using_transactions: bool, use database transactions
135
- dry_run: bool, perform validation without saving
136
- raise_errors: bool, raise exceptions on errors
137
- batch_size: int, number of instances per batch
138
- result: Result object to update
139
"""
140
141
def bulk_update(self, using_transactions, dry_run, raise_errors, batch_size=None, result=None):
142
"""
143
Perform bulk update of instances for performance optimization.
144
145
Parameters:
146
- using_transactions: bool, use database transactions
147
- dry_run: bool, perform validation without saving
148
- raise_errors: bool, raise exceptions on errors
149
- batch_size: int, number of instances per batch
150
- result: Result object to update
151
"""
152
153
def bulk_delete(self, using_transactions, dry_run, raise_errors, result=None):
154
"""
155
Perform bulk deletion of instances for performance optimization.
156
157
Parameters:
158
- using_transactions: bool, use database transactions
159
- dry_run: bool, perform validation without saving
160
- raise_errors: bool, raise exceptions on errors
161
- result: Result object to update
162
"""
163
164
# Lifecycle hook methods for customization
165
def before_import(self, dataset, **kwargs):
166
"""
167
Called before the import process starts.
168
169
Parameters:
170
- dataset: tablib.Dataset to be imported
171
- **kwargs: Import options
172
"""
173
174
def after_import(self, dataset, result, **kwargs):
175
"""
176
Called after the import process completes.
177
178
Parameters:
179
- dataset: tablib.Dataset that was imported
180
- result: Result object with import results
181
- **kwargs: Import options
182
"""
183
184
def before_import_row(self, row, **kwargs):
185
"""
186
Called before each row is imported.
187
188
Parameters:
189
- row: dict, row data to be imported
190
- **kwargs: Row import options
191
"""
192
193
def after_import_row(self, row, row_result, **kwargs):
194
"""
195
Called after each row is imported.
196
197
Parameters:
198
- row: dict, row data that was imported
199
- row_result: RowResult object with row import results
200
- **kwargs: Row import options
201
"""
202
203
def before_save_instance(self, instance, row, **kwargs):
204
"""
205
Called before saving an instance.
206
207
Parameters:
208
- instance: Model instance to be saved
209
- row: dict, row data
210
- **kwargs: Save options
211
"""
212
213
def after_save_instance(self, instance, row, **kwargs):
214
"""
215
Called after saving an instance.
216
217
Parameters:
218
- instance: Model instance that was saved
219
- row: dict, row data
220
- **kwargs: Save options
221
"""
222
223
def before_delete_instance(self, instance, row, **kwargs):
224
"""
225
Called before deleting an instance.
226
227
Parameters:
228
- instance: Model instance to be deleted
229
- row: dict, row data
230
- **kwargs: Delete options
231
"""
232
233
def after_delete_instance(self, instance, row, **kwargs):
234
"""
235
Called after deleting an instance.
236
237
Parameters:
238
- instance: Model instance that was deleted
239
- row: dict, row data
240
- **kwargs: Delete options
241
"""
242
243
def before_export(self, queryset, **kwargs):
244
"""
245
Called before the export process starts.
246
247
Parameters:
248
- queryset: Django QuerySet to be exported
249
- **kwargs: Export options
250
"""
251
252
def after_export(self, queryset, dataset, **kwargs):
253
"""
254
Called after the export process completes.
255
256
Parameters:
257
- queryset: Django QuerySet that was exported
258
- dataset: tablib.Dataset with exported data
259
- **kwargs: Export options
260
"""
261
262
def import_field(self, field, instance, row, is_m2m=False, **kwargs):
263
"""
264
Import single field value to instance.
265
266
Parameters:
267
- field: Field object
268
- instance: Model instance
269
- row: dict, row data
270
- is_m2m: bool, whether field is many-to-many
271
- **kwargs: Field import options
272
"""
273
274
def save_m2m(self, instance, row, **kwargs):
275
"""
276
Save many-to-many relationships after instance is saved.
277
278
Parameters:
279
- instance: Model instance
280
- row: dict, row data
281
- **kwargs: M2M save options
282
"""
283
284
def skip_row(self, instance, original, row, import_validation_errors=None):
285
"""
286
Determine whether to skip importing this row.
287
288
Parameters:
289
- instance: Model instance
290
- original: Original instance (if updating)
291
- row: dict, row data
292
- import_validation_errors: List of validation errors
293
294
Returns:
295
bool, True to skip row
296
"""
297
298
def for_delete(self, row, instance):
299
"""
300
Determine whether instance should be deleted.
301
302
Parameters:
303
- row: dict, row data
304
- instance: Model instance
305
306
Returns:
307
bool, True to delete instance
308
"""
309
310
def get_import_fields(self):
311
"""
312
Get fields used for import operations.
313
314
Returns:
315
List of Field objects for import
316
"""
317
318
def get_export_fields(self, selected_fields=None):
319
"""
320
Get fields used for export operations.
321
322
Parameters:
323
- selected_fields: Optional list of field names to export
324
325
Returns:
326
List of Field objects for export
327
"""
328
329
def get_import_order(self):
330
"""
331
Get processing order for import operations.
332
333
Returns:
334
List of field names in import order
335
"""
336
337
def get_export_order(self):
338
"""
339
Get field order for export operations.
340
341
Returns:
342
List of field names in export order
343
"""
344
345
def before_import(self, dataset, **kwargs):
346
"""
347
Hook called before import process starts.
348
349
Parameters:
350
- dataset: tablib.Dataset to be imported
351
- **kwargs: Import configuration
352
"""
353
354
def after_import(self, dataset, result, **kwargs):
355
"""
356
Hook called after import process completes.
357
358
Parameters:
359
- dataset: tablib.Dataset that was imported
360
- result: Result object with import results
361
- **kwargs: Import configuration
362
"""
363
364
def before_import_row(self, row, **kwargs):
365
"""
366
Hook called before each row is imported.
367
368
Parameters:
369
- row: dict, row data to be imported
370
- **kwargs: Row processing options
371
"""
372
373
def after_import_row(self, row, row_result, **kwargs):
374
"""
375
Hook called after each row is imported.
376
377
Parameters:
378
- row: dict, row data that was imported
379
- row_result: RowResult object
380
- **kwargs: Row processing options
381
"""
382
383
def before_save_instance(self, instance, row, **kwargs):
384
"""
385
Hook called before instance is saved.
386
387
Parameters:
388
- instance: Model instance to be saved
389
- row: dict, row data
390
- **kwargs: Save options
391
"""
392
393
def after_save_instance(self, instance, row, **kwargs):
394
"""
395
Hook called after instance is saved.
396
397
Parameters:
398
- instance: Model instance that was saved
399
- row: dict, row data
400
- **kwargs: Save options
401
"""
402
403
def before_delete_instance(self, instance, row, **kwargs):
404
"""
405
Hook called before instance is deleted.
406
407
Parameters:
408
- instance: Model instance to be deleted
409
- row: dict, row data
410
- **kwargs: Delete options
411
"""
412
413
def after_delete_instance(self, instance, row, **kwargs):
414
"""
415
Hook called after instance is deleted.
416
417
Parameters:
418
- instance: Model instance that was deleted
419
- row: dict, row data
420
- **kwargs: Delete options
421
"""
422
423
# Bulk operations
424
def bulk_create(self, using_transactions, dry_run, raise_errors, batch_size=None, result=None):
425
"""
426
Bulk create instances for improved performance.
427
428
Parameters:
429
- using_transactions: bool, use database transactions
430
- dry_run: bool, perform dry run without saving
431
- raise_errors: bool, raise exceptions on errors
432
- batch_size: int, batch size for bulk operations
433
- result: Result object to update
434
"""
435
436
def bulk_update(self, using_transactions, dry_run, raise_errors, batch_size=None, result=None):
437
"""
438
Bulk update instances for improved performance.
439
440
Parameters:
441
- using_transactions: bool, use database transactions
442
- dry_run: bool, perform dry run without saving
443
- raise_errors: bool, raise exceptions on errors
444
- batch_size: int, batch size for bulk operations
445
- result: Result object to update
446
"""
447
448
def bulk_delete(self, using_transactions, dry_run, raise_errors, result=None):
449
"""
450
Bulk delete instances for improved performance.
451
452
Parameters:
453
- using_transactions: bool, use database transactions
454
- dry_run: bool, perform dry run without deleting
455
- raise_errors: bool, raise exceptions on errors
456
- result: Result object to update
457
"""
458
```
459
460
### ModelResource Class
461
462
Specialized resource class for Django models with automatic field mapping and Django-specific functionality.
463
464
```python { .api }
465
class ModelResource(Resource, metaclass=ModelDeclarativeMetaclass):
466
def get_queryset(self):
467
"""
468
Get Django QuerySet for export operations.
469
470
Returns:
471
QuerySet for the resource's model
472
"""
473
474
def field_from_django_field(self, field_name, django_field, readonly):
475
"""
476
Create import_export Field from Django model field.
477
478
Parameters:
479
- field_name: str, name of the field
480
- django_field: Django model field instance
481
- readonly: bool, whether field is read-only
482
483
Returns:
484
Field instance configured for Django field
485
"""
486
487
def widget_from_django_field(self, f, default=None):
488
"""
489
Create widget from Django model field.
490
491
Parameters:
492
- f: Django model field instance
493
- default: Default widget class
494
495
Returns:
496
Widget instance appropriate for field type
497
"""
498
499
def widget_kwargs_for_field(self, field_name, django_field):
500
"""
501
Get widget kwargs for Django field.
502
503
Parameters:
504
- field_name: str, name of the field
505
- django_field: Django model field instance
506
507
Returns:
508
Dict of kwargs for widget initialization
509
"""
510
511
def get_display_name(self):
512
"""
513
Get display name for the resource.
514
515
Returns:
516
str, human-readable resource name
517
"""
518
519
class Meta:
520
"""
521
Meta class for ModelResource configuration.
522
523
Attributes:
524
- model: Django model class
525
- fields: Tuple of field names to include
526
- exclude: Tuple of field names to exclude
527
- import_id_fields: Tuple of fields used for import identification
528
- export_order: Tuple defining field order in exports
529
- widgets: Dict mapping field names to widget instances
530
- use_transactions: bool, use database transactions
531
- skip_unchanged: bool, skip unchanged records
532
- use_bulk: bool, use bulk operations for performance
533
- batch_size: int, batch size for bulk operations
534
"""
535
```
536
537
### ModelResource Factory
538
539
Utility function for dynamically creating ModelResource classes.
540
541
```python { .api }
542
def modelresource_factory(model, resource_class=ModelResource, meta_options=None, custom_fields=None, dehydrate_methods=None):
543
"""
544
Factory function for creating ModelResource classes dynamically.
545
546
Parameters:
547
- model: Django model class
548
- resource_class: Base resource class (default: ModelResource)
549
- meta_options: Dict of Meta class options
550
- custom_fields: Dict of custom field definitions
551
- dehydrate_methods: Dict of custom dehydrate methods
552
553
Returns:
554
Dynamically created ModelResource class
555
"""
556
```
557
558
### Field Class
559
560
Represents mapping between instance field and its import/export representation.
561
562
```python { .api }
563
class Field:
564
empty_values = [None, ""]
565
566
def __init__(self, attribute=None, column_name=None, widget=None, default=NOT_PROVIDED, readonly=False, saves_null_values=True, dehydrate_method=None, m2m_add=False):
567
"""
568
Initialize field with mapping configuration.
569
570
Parameters:
571
- attribute: str, instance attribute name
572
- column_name: str, column name in import/export data
573
- widget: Widget instance for data transformation
574
- default: Default value for empty values
575
- readonly: bool, field is read-only on import
576
- saves_null_values: bool, save null values to instance
577
- dehydrate_method: str or callable, custom dehydration method
578
- m2m_add: bool, add to M2M instead of replacing
579
"""
580
581
def clean(self, row, **kwargs):
582
"""
583
Convert import value to Python object.
584
585
Parameters:
586
- row: dict, row data
587
- **kwargs: Cleaning options
588
589
Returns:
590
Cleaned Python value
591
"""
592
593
def export(self, instance, **kwargs):
594
"""
595
Convert instance value to export representation.
596
597
Parameters:
598
- instance: Model instance
599
- **kwargs: Export options
600
601
Returns:
602
Serialized value for export
603
"""
604
605
def get_value(self, instance):
606
"""
607
Get value from instance attribute.
608
609
Parameters:
610
- instance: Model instance
611
612
Returns:
613
Attribute value
614
"""
615
616
def save(self, instance, row, is_m2m=False, **kwargs):
617
"""
618
Save cleaned value to instance.
619
620
Parameters:
621
- instance: Model instance
622
- row: dict, row data
623
- is_m2m: bool, whether field is many-to-many
624
- **kwargs: Save options
625
"""
626
627
def get_dehydrate_method(self, field_name=None):
628
"""
629
Get method name for dehydration.
630
631
Parameters:
632
- field_name: str, field name
633
634
Returns:
635
str, dehydrate method name
636
"""
637
```
638
639
### Resource Configuration
640
641
Resource behavior can be configured through the Meta class or ResourceOptions.
642
643
```python { .api }
644
class ResourceOptions:
645
"""
646
Configuration class for Resource behavior.
647
648
Common options:
649
- model: Django model class
650
- fields: Fields to include in import/export
651
- exclude: Fields to exclude from import/export
652
- import_id_fields: Fields used for import identification
653
- widgets: Custom widgets for specific fields
654
- use_transactions: Use database transactions
655
- skip_unchanged: Skip unchanged records during import
656
- use_bulk: Use bulk operations for performance
657
- batch_size: Batch size for bulk operations
658
- chunk_size: Chunk size for processing large datasets
659
"""
660
```
661
662
### Utility Functions
663
664
```python { .api }
665
def has_natural_foreign_key(model):
666
"""
667
Determine if a model has natural foreign key functions.
668
669
Parameters:
670
- model: Django model class
671
672
Returns:
673
bool, True if model supports natural keys
674
"""
675
```
676
677
## Usage Examples
678
679
### Basic Resource Definition
680
681
```python
682
from import_export import resources, fields, widgets
683
from myapp.models import Book
684
685
class BookResource(resources.ModelResource):
686
title = fields.Field(attribute='title', column_name='Book Title')
687
author = fields.Field(attribute='author', column_name='Author Name')
688
published_date = fields.Field(
689
attribute='published_date',
690
widget=widgets.DateWidget(format='%Y-%m-%d')
691
)
692
693
class Meta:
694
model = Book
695
fields = ('id', 'title', 'author', 'published_date')
696
export_order = ('title', 'author', 'published_date')
697
import_id_fields = ('id',)
698
```
699
700
### Custom Processing with Hooks
701
702
```python
703
class BookResource(resources.ModelResource):
704
class Meta:
705
model = Book
706
707
def before_import_row(self, row, **kwargs):
708
# Clean data before processing
709
row['title'] = row['title'].strip().title()
710
711
def after_save_instance(self, instance, row, **kwargs):
712
# Send notification after saving
713
send_book_created_notification(instance)
714
715
def skip_row(self, instance, original, row, import_validation_errors=None):
716
# Skip books with empty titles
717
return not row.get('title', '').strip()
718
```
719
720
### Bulk Operations Configuration
721
722
```python
723
class BookResource(resources.ModelResource):
724
class Meta:
725
model = Book
726
use_bulk = True
727
batch_size = 1000
728
skip_unchanged = True
729
use_transactions = True
730
```
731
732
### Dynamic Field Configuration
733
734
```python
735
class BookResource(resources.ModelResource):
736
def __init__(self, **kwargs):
737
super().__init__(**kwargs)
738
# Add dynamic field based on kwargs
739
if kwargs.get('include_stats'):
740
self.fields['stats'] = fields.Field(
741
attribute='calculate_stats',
742
readonly=True
743
)
744
745
def calculate_stats(self, instance):
746
return f"Pages: {instance.pages}, Rating: {instance.rating}"
747
```