Search code examples
djangodjango-admindjango-import-export

How to do field validation in django-import-export


Following is my model:

class Product(models.Model):
    product_title = models.CharField(max_length=100, null=False, 
verbose_name='Product title')
    product_description = models.TextField(max_length=250, 
verbose_name='Product description')
    product_qty = models.IntegerField(verbose_name='Quantity')
    product_mrp = models.FloatField(verbose_name='Maximum retail price')
    product_offer_price = models.FloatField(verbose_name='Selling price')

I wanted to have a validation for product_offer_price field before save for which I had posted a QUESTION and it was answered with the working solution.

Validation needed is:

 if product_offer_price > product_mrp:
    raise ValidationError

Now the solution to above question works perfectly for the admin forms.

But, I have implemented django-import-export, in which I am importing Product Data in bulk in admin, and I need similar validation during bulk import.

How to achieve this?


Solution

  • Well, here was a little research process.

    And finally I got it.

    The trouble is avoiding ProductForm in import-export library. Inside library import invoke method save() of instance, but if we raise ValidationError in Model (not in Form) = 500 with DEBUG = False, and traceback page with DEBUG = True. So we should use "before_import" method in import_export Resource and "clean" method in django.forms Form.

    admin.py

    from forms import ProductForm
    from models import Product
    from import_export import resources
    from import_export.admin import ImportExportActionModelAdmin
    from django.forms import ValidationError
    
    class ProductResource(resources.ModelResource):
    
        class Meta:
            model = Product
    
        def before_import(self, dataset, using_transactions, dry_run, **kwargs):
            for row in dataset:
                if int(row[4]) < int(row[5]):
                    raise ValidationError('Product offer price cannot be greater than Product MRP. '
                                          'Error in row with id = %s' % row[0])
    
    
    class ProductAdmin(ImportExportActionModelAdmin):
        list_display = ('product_title', 'product_description', 'product_qty', 'product_mrp', 'product_offer_price')
        form = ProductForm
        resource_class = ProductResource
    
    
    admin.site.register(Product, ProductAdmin)
    

    forms.py

    from django import forms
    from models import Product
    
    
    class ProductForm(forms.ModelForm):
        class Meta:
            model = Product
            exclude = [id, ]
    
        def clean(self):
            product_offer_price = self.cleaned_data.get('product_offer_price')
            product_mrp = self.cleaned_data.get('product_mrp')
            if product_offer_price > product_mrp:
                raise forms.ValidationError("Product offer price cannot be greater than Product MRP.")
            return self.cleaned_data
    

    models.py

    class Product(models.Model):
        product_title = models.CharField(max_length=100, null=False, verbose_name='Product title')
        product_description = models.TextField(max_length=250, verbose_name='Product description')
        product_qty = models.IntegerField(verbose_name='Quantity')
        product_mrp = models.FloatField(verbose_name='Maximum retail price')
        product_offer_price = models.FloatField(verbose_name='Selling price')