Я столкнулся с ошибкой уникального ограничения в django. Целью API является создание или обновление оценок учащегося на основе вариации предмета, результатов экзамена и в массовом порядке. Для этого я использовал массовое создание с флагом конфликтов обновлений.
Вот актуальная модель
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.
Я предположил, что это потому, что не было предусмотрено никаких ограничений, гласящих, что эти поля должны быть уникальными вместе, поэтому я добавил ограничение в модель меток.
class Meta:
constraints = [
models.UniqueConstraint(
fields=["subject_variation", "exam_results"], name = "unique_marks"
)
]
После того, как я выполняю миграцию и мигрирую, аспект массового создания работает и создает два новых экземпляра меток. Вот полезная нагрузка для справки.
{
"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.
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```
Прямо перед вызовом вставки выполняется следующий запрос: SELECT 1 AS "a" FROM "academics_marks" WHERE ("accademics_marks"."is_active" AND "academics_marks"."exam_results_id" = 1 AND "academics_marks"."subject_variation_id" = 2) ПРЕДЕЛ 1; арг=(1, 1, 2); alias=default, это вызывает ошибку. Как мне обойти это?