Unique Constraint Failed In Upsert When Calling bulk_create with update_conficts

Я сталкиваюсь с ошибкой unique constraint failed в django. Цель api - создание или обновление оценок ученика на основе вариации предмета, результатов экзамена и в массовом порядке. Для этого я использовал bulk create с флагом update conflicts.

Вот текущая модель

class Marks(Common):
    exam_results = models.ForeignKey(
        "ExamResults", on_delete=models.CASCADE, related_name="marks"
    )
    subject_variation = models.ForeignKey(
        "SubjectVariation", on_delete=models.CASCADE, related_name="marks"
    )
    student = models.ForeignKey(
        "Student", on_delete=models.CASCADE, related_name="marks"
    )
    marks_obtained = models.FloatField()
    objects = BaseModelManager()class Marks(Common):

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

class MarksUpsertSerializer(serializers.ModelSerializer):
    class Meta:
        model = Marks
        fields = ("exam_results", "subject_variation", "marks_obtained")

class BulkMarksUpsertSerializer(serializers.Serializer):
    marks = MarksUpsertSerializer(many=True)

    def create(self, validated_data):
        marks = [Marks(**item) for item in validated_data["marks"]]
        marks = Marks.objects.bulk_create(
            marks,
            update_conflicts=True,
            update_fields=["marks_obtained"],
            unique_fields=["exam_results", "subject_variation"],
        )
        return marks

но когда я делаю это, он говорит, что нет уникального или исключающего ограничения, соответствующего спецификации ON CONFLICT.

Я предположил, что это связано с тем, что нет ограничений, которые бы говорили, что эти поля должны быть уникальными вместе, поэтому я добавил ограничение на модель marks.

class Meta:
    constraints = [
        models.UniqueConstraint(
            fields=["subject_variation", "exam_results"], name="unique_marks"
        )
    ]

После того, как я сделал миграции и мигрировал, аспект bulk create работает и создает два новых экземпляра меток. Вот полезная нагрузка для справки.

 {
    "marks": [
    {
        "exam_results" : "1",
        "subject_variation" : "1",
        "marks_obtained" : 40,
    },
    {
        "exam_results" : "1",
        "subject_variation" : "2",
        "marks_obtained" : 20,
    }
    
  ]
}

Теперь, поскольку я хочу снова обновить метки, я должен снова вызвать этот api. Однако я получаю ошибку:

{
    "marks": [
        {
            "non_field_errors": [
                "The fields subject_variation, exam_results must make a unique set."
            ]
        },
        {
            "non_field_errors": [
                "The fields subject_variation, exam_results must make a unique set."
            ]
        }
    ]
}

По идее, обновление должно происходить, если эти уникальные ограничения есть, но я получаю эту ошибку. Как с этим бороться? Если я закомментирую ограничения из модели, то все снова заработает. Это работает даже при создании новых экземпляров. Это работает до тех пор, пока я не сделаю миграцию и не мигрирую снова, поскольку мета-класс изменяется для модели. Затем снова возникает та же ошибка.

Спасибо.

Это было исправлено отключением валидаторов в django rest framework,

class MarksUpsertSerializer(serializers.ModelSerializer):
    class Meta:
        model = Marks
        fields = ("exam_results", "subject_variation", "marks_obtained", "student")


class BulkMarksUpsertSerializer(serializers.Serializer):
    marks = MarksUpsertSerializer(many=True, validators=[]) # <-- here

Удалив валидаторы по умолчанию путем перезаписи пустым массивом, валидатор модели отключился, предотвратив выполнение следующего запроса:

SELECT 1 AS "a" FROM "academics_marks" WHERE ("academics_marks"."is_active" AND "academics_marks"."exam_results_id" = 1 AND "academics_marks"."subject_variation_id" = 2) LIMIT 1; args=(1, 1, 2); alias=default```

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