Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django-import-export - import of advanced fields?

For a Django model I'm using django-import-export package.

If need to export more then just available model fields, like properties or custom fields, new can be added with import_export.fields.Field class and optionally dehydrate_<field> method.

from import_export import resources, fields, instance_loaders

class ProductResource(resources.ModelResource):
    categories  = fields.Field()
    price       = fields.Field(attribute='unit_price')

    class Meta:
        model  = Product

    def dehydrate_categories(self, product):
        return ';'.join(
                '/%s' % '/'.join([c.name for c in cat.parents()] + [cat.name])
                for cat in product.category.iterator() )

It does work well, but only for exporting. What about import, the reverse process ? Is there some counterpart to dehydrate_ method ?

So far I've overridden get_or_init_instance method:

class ProductResource(resources.ModelResource):
    def get_or_init_instance(self, instance_loader, row):
        row['unit_price'] = row['price']; row.pop('price')
        return super(ProductResource, self).get_or_init_instance(instance_loader, row)

but doubt this is the right way.

Would appreciate any hint how to handle imports of custom fields.

like image 262
David Unric Avatar asked Nov 02 '13 23:11

David Unric


2 Answers

You can override import_obj instead. See Import workflow for more details.

Another approach is to subclass Field and override export and save methods and do all required data manipulation in a field.

like image 62
bmihelac Avatar answered Sep 28 '22 07:09

bmihelac


I know this is very old but I came across the same problem and this is how I fixed it (based on the direction the original asker was heading). First, you can add any custom/modified fields you need by overriding the 'before_import_row' function, like so:

    def before_import_row(self, row, **kwargs):
        row['extra_info'] = 'Some Info'
        return super(RetailLocationResource, self).before_import_row(row, **kwargs)

Then you can pass this into your instance by overriding get_or_init_instance like so:

    def get_or_init_instance(self, instance_loader, row):
        instance, bool = super(RetailLocationResource, self).get_or_init_instance(instance_loader, row)
        instance.extra_info = row['extra_info']
        return instance, bool

Hope this helps anyone!

like image 28
npwhite Avatar answered Sep 28 '22 07:09

npwhite