I would like to be able to import data into my database from a CSV file thanks to the Pandas library, I succeeded for some model data but when the model fields are in many to many I can't.
Here is the model whose data I would like to import:
class LnkPlantPlant(models.Model):
class MAGNET_CHOICES(models.TextChoices):
NONE = None
IDEAL = 'ideal',
GOOD = 'good',
MEDIOCRE = 'mediocre',
BAD = 'bad'
custom_id = models.IntegerField(primary_key=True, unique=True)
plant = models.ManyToManyField('perma_plants.Plant', related_name='%(class)s_plant')
plant_associated = models.ManyToManyField('perma_plants.Plant', related_name='%(class)s_plant_associated')
link = models.CharField(max_length=10, choices=MAGNET_CHOICES.choices, default=MAGNET_CHOICES.NONE, blank=True,
null=True)
description = RichTextField(max_length=255, blank=True, null=True)
Here the model of the plant
:
class Plant(models.Model):
name = models.CharField(max_length=150)
def __str__(self):
return self.name
Here, is my function which allows to import data into the database but I would like to be able to import the name of the many to many fields of the plant
and the plant_associated
:
class UploadLinkPlantData(generics.CreateAPIView):
serializer_class = FileUploadSerializer
def post(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
file = serializer.validated_data['file']
reader = pd.read_csv(file)
for _, row in reader.iterrows():
LnkPlantPlant.objects.update_or_create(
custom_id=row['Custom Id'],
defaults={
"custom_id": row['Custom Id'],
"plant": Plant.objects.get(name=row['Plant']), # doesn't work
"plant_associated": Plant.objects.get(name=row['Plant associated']), # doesn't work
"link": row['Link'],
"description": row['Description']
})
return Response({"status": "Succès : plante(s) crée(s) ou mise(s) à jour."},
status.HTTP_201_CREATED)
Thanks for help !
CodePudding user response:
Inside the loop
lnk_plant, created = LnkPlantPlant.objects.update_or_create(
custom_id=row['Custom Id'],
defaults={
"custom_id": row['Custom Id'],
"link": row['Link'],
"description": row['Description']
})
plants = Plant.objects.filter(name=row['Plant'])
plant_associated = Plant.objects.filter(name=row['Plant associated'])
lnk_plant.plant.set(list(plants))
lnk_plant.plant_associated.set(list(plant_associated))
Note that set
will erase existing m2m relations.
You can use add
to add to relation like that:
lnk_plant.plant.add(*plants)
lnk_plant.plant_associated.add(*plant_associated)
If you also need to create Plant objects, you will have to do that too before.
plant = Plant.objects.create(name=row['Plant'])
lnk_plant.plant.add(plant)