Метод Update_or_create с уникальным полем в Django

Я хотел бы обновить или создать данные в моей базе данных путем импорта CSV-файла.

Я протестировал и когда я импортирую CSV файл, когда "растения" еще не были созданы, он работает, но когда в моей базе данных есть одинаковые названия растений, у меня возникает ошибка целостности:

IntegrityError : duplicate key value violates unique constraint "perma_plants_plant_name_key" DETAIL: Key (name)=(Test bis) already exists.

Так что мой метод update_or_create не работает, потому что в моей модели поле name должно быть уникальным. Как я могу решить эту проблему?

Вот моя модель :

class Plant(models.Model):

    name = models.CharField(max_length=150, unique=True)

    def __str__(self):
        return self.name

Вот мой views.py:

class UploadFileView(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():
            Plant.objects.update_or_create(
                name=row['Name'],
            )
        return Response({"status": "Success : plants created"},
                        status.HTTP_201_CREATED)

Для идентификации растений нам нужно отдельное поле от названия. Мы могли бы использовать стандартный Django "pk" как первичный ключ, но поскольку вы хотите импортировать его из CSV, мы создадим "custom_id" в вашей модели:

class Plant(models.Model):
    name = models.CharField(max_length=150, unique=True)
    custom_id = models.CharField(primary_key=True, max_length=20, unique=True)
    def __str__(self):
        return self.name

Перед добавлением первичного ключа вам, вероятно, придется удалить все растения и очистить базу данных, чтобы она позволила вам выполнить миграцию.

Теперь ваш csv должен иметь две колонки, "name" и "custom_id", а views.py будет выглядеть следующим образом:

class UploadFileView(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():
            Plant.objects.update_or_create(
                custom_id=row['custom_id'],
                defaults={
                    "name":row['Name'],
                    "custom_id": row['custom_id'],
                }
        return Response({"status": "Success : plants created"},
                        status.HTTP_201_CREATED)

При таком коде фактическим идентификатором растения является "custom_id", который должен быть фиксированным и никогда не изменяться после его присвоения. Вы должны соблюдать его каждый раз, когда импортируете CSV. И когда вы добавляете новое растение, вы "изобретаете" новый custom_id (который логически не может быть повторен с любым другим).

Вернуться на верх