Search code examples
pythondjangoserializationdjango-rest-framework

Validate choice field DRF


Hi all I have my model and its serializer, what I discovered when testing is that serializer is saved no matter what I have in my choice field but in Django admin choice field is empty when the data is wrong and when the data is right I can see the correct option

so,

-> wrong choice data
-> saved regardless 
-> nothing in django admin
-> correct choice data
-> saved
-> correct value in django admin

How can I return validation error if I detect that user posted incorrect data?

what I was trying out is

topic = serializers.ChoiceField(choices=School.topic)

and I don't think that iterating over each tuple and searching for a string is correct or efficient

code

class SchoolViewSet(viewsets.ModelViewSet):

    queryset = School.objects.all()
    serializer_class = SchoolSerializer

    def create(self, request):
        serializer = SchoolSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        else:
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
class School(models.Model):

    SUBJECT = (
       ('Math', 'Mathematic'),
       ('Eng', 'English'),
       ('Cesolved', 'Chemistry'),
   )

    name = models.CharField(blank=False, max_length=50)
    subject = models.CharField(choices=SUBJECT, max_length=15, blank=False)
    created = models.DateTimeField(auto_now_add=True)
    updated = models.DateTimeField(auto_now=True)

    def __str__(self):
        return str(f'{self.name} is {self.subject}')
class SchoolSerializer(serializers.ModelSerializer):
    subject = serializers.ChoiceField(choices=School.SUBJECT)

    def validate(self, data):
        name = data["name"]
        if (5 > len(name)):
            raise serializers.ValidationError({"IError": "Invalid name"})
 
        return data

    class Meta:
        model = School
        fields = "__all__"

Solution

  • I've figured out version for checking if choice passed in the serializer is correct.

    Please let me know if there are better ways to do it

    Basically, I've imported my choice field from models into serializer and then converted it into dict and then in the validate function check if value exists

    CHOICE_DICT = dict(School.SUBJECT)
    
    def validate(self, data):
    
       choice = data["subject"]
       if not (choice in CHOICE_DICT):
          raise serializers.ValidationError({"Invalid Choice": f"Choice field is not valid. Valid choices {Contact.School}"})
    
            return data
    
    

    I don't think that this is the fastest way to do this.