Django restframework object-level-validation
Вот мои модели: Test, Skillarea, question
MODELS.PY :
class Test(BaseModel):
types = models.ManyToManyField(
TestType,
related_name='tests',
)
title = models.CharField(max_length=255)
summary = models.TextField()
def __str__(self):
return self.title
class SkillArea(BaseModel):
title = models.CharField(max_length=255)
test = models.ForeignKey('Test', on_delete=models.PROTECT, related_name='skill_areas')
questions = models.ManyToManyField(
'assessment.Question',
related_name='skill_areas',
)
def __str__(self):
return self.title
class Question(BaseModel):
question_text = models.TextField()
def get_absolute_url(self):
self.get_type_display()
def __str__(self):
return truncatewords(self.question_text, 7)
class TestType(BaseModel):
title = models.CharField(max_length=255)
def __str__(self):
return self.title
Я хочу иметь updateerializer для обновления, но поле "type" в модели Test, может быть обновлено только если нет вопроса в модели Skillarea, который связан с моделью Test (имеет тот же id, что и обновляемый тест, в его поле test)
Я написал эти сериализатор и представление, но оно не знает data['id']
, который я использовал в валидаторе и посылает KeyError: 'id'
serializer.py :
class TestUpdateAPIViewSerializer(serializers.ModelSerializer):
def validate(self, data):
questions = SkillArea.objects.filter(test=data['id'], questions__isnull=False)
if questions.exists():
raise serializers.ValidationError("You may not edit type")
return data
class Meta:
model = Test
fields = (
'id',
'types',
'title',
'summary',
)
Views.py :
class TestUpdateAPIView(APIView):
def patch(self, request, pk):
test = Test.active_objects.get(pk=pk)
serializer = TestUpdateAPIViewSerializer(instance=test, partial=True, data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_200_OK)
return Response(serializer.data, status=status.HTTP_400_BAD_REQUEST)
Я думаю, что вы можете получить id
из instance
атрибута.
class TestUpdateAPIViewSerializer(serializers.ModelSerializer):
def validate(self, data):
questions = SkillArea.objects.filter(test=self.instance.id, questions__isnull=False)
...