Home > Enterprise >  django restframework object-level-validation
django restframework object-level-validation

Time:08-11

These are my models : 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

I want to have an updateserializer for updating, but the field "type" in the Test model, only can be updated if there is no question in Skillarea model which related to Test model( has the same id as updating test, in its test field)

I wrote these serializer and view but it doesnt know data['id'] which i used in validator and sends 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)

CodePudding user response:

I think you can get the id from instance attribute.

class TestUpdateAPIViewSerializer(serializers.ModelSerializer):

    def validate(self, data):
        questions = SkillArea.objects.filter(test=self.instance.id, questions__isnull=False)
        ...
    
  • Related