简体   繁体   中英

Django rest framework:UniqueValidator copare the field convert to upper case

I can save the mac_address to upper in database
And the mac_address value should be unique in database

But if the client send me a lower case json like {"mac_address":'aa:bb:cc:dd:eE'}
and my database already had mac_address with 'AA:BB:CC:DD:EE'
But client still got 201 created success
Why wouldn't my UniqueValidator work ??
Please help me find out

views.py

I try ListCreateAPIView and APIView
Both can't work well I think the problem is UniqueValidator part

I find the document use validate_<field_name> But My code not work

class DataList(generics.ListCreateAPIView):
    queryset = Data.objects.all()
    serializer_class = DataSerializer

    def perform_create(self, serializer):
        mac_address = self.request.data['mac_address'].upper()
        serializer.save(mac_address=mac_address, datetime=datetime.datetime.now(pytz.utc))
class DataList(APIView):
    def post(self, request, format=None):
        serializer = DataSerializer(data=request.data)
        if serializer.is_valid():
            mac_address = request.data['mac_address'].upper()
            serializer.save(mac_address=mac_address, datetime=datetime.datetime.utcnow().replace(tzinfo=pytz.utc))
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

And the serialize validator needs to convert to lower case first then query the database.

class DataSerializer(serializers.ModelSerializer):
    datetime = ReadOnlyField()
    mac_address = CharField(max_length=50,
    validators=[UniqueValidator(queryset=Data.objects.all())]
)
    def validate_mac_address(self,value):
        return value.upper()

define valid_email method into your serializer

class DataSerializer(serializers.ModelSerializer):

    email = CharField(
        max_length=255,
        validators=[UniqueValidator(queryset=BlogPost.objects.all())]
    )

    // your content and other stuff goes here

    def valid_email(self,value):
        return value.lower()

Your validator should be doing the actual validation:

class DataSerializer(serializers.ModelSerializer):
    datetime = ReadOnlyField()
    mac_address = CharField(max_length=50)

    def validate_mac_address(self,value):
        if Data.objects.filter(mac_address=value.upper()).exists():
            raise serializers.ValidationError("MAC address should be unique")
        return value.upper()

Your UniqueValidator is working as its expected of it. Because the default lookup for UniqueValidator is 'exact'. Whereas you are in need of 'iexact' which does a case insensitive lookup. So change the mac_address serializer field to :

mac_address = CharField(max_length=50,
    validators=[UniqueValidator(queryset=Data.objects.all(), lookup='iexact')]
)

Note: Using the validate_ prefix method will work but problems may arise when you are trying to use the serializer for partial update. At that time you want the serializer to exempt the checkup of uniqueness for mac_address field or at least exclude the current object from the queryset that you are putting the constraint on.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM