wq / django-data-wizard

🧙⚙️ Import structured data (e.g. Excel, CSV, XML, JSON) into one or more Django models via an interactive web-based wizard
https://django-data-wizard.wq.io
MIT License
338 stars 53 forks source link

Troubles importing datas when target model has many to many field #34

Closed githule closed 1 year ago

githule commented 3 years ago

Hello,

That's not really an issue or a bug. I am in trouble to get data imported for the following model example :

class IP(models.Model):
    version = models.IntegerField()
    address = models.GenericIPAddressField()
    def __str__(self):
        return "{0}".format(self.address)

class Asset(models.Model):
    hostname = models.CharField(max_length=100, blank=True)
    fqdn = models.CharField(max_length=100, blank=True)
    ip_list = models.ManyToManyField("IP",  blank=True)

My file to import will be the in the following format :

AssetName,AssetIP,FQDN
A0001,192.168.1.1,A0001.int.myorg
A0001,10.1.1.1,A0001.int.myorg
A0002,192.168.1.2,A0002.int.myorg

So the scenario is the following :

Do you think Data Wizard can handle such a scenario ? I read the doc and especially the part on the Custom Serializer but I am not sure to be on a good way. Maybe I have to build an intermediate model and then report the data into multiple target models.

Should I be able to do this scenario with Data Wizard ?

Thanks for your help

sheppard commented 2 years ago

This would be a good use case for a custom serializer. You can override the Serializer.create() method to do whatever you need. Perhaps something like this:

from rest_framework import serializers
import data_wizard
from .models import Asset, IP

class AssetIPSerializer(serializers.Serializer):
    name = serializers.CharField()
    fqdn = serializers.CharField()
    ip_address = serializers.IPAddressField()

    def create(self, validated_data):
        asset, is_new = Asset.objects.get_or_create(
            hostname=validated_data['name'],
            defaults={ 'fqdn': validated_data['fqdn']}
        )
        ip_addr, is_new = IP.objects.get_or_create(
            address=validated_data['ip_address'],
            defaults={'version': '?'},
        )
        asset.ip_list.add(ip_addr)

data_wizard.register("Asset + IP", AssetIPSerializer)