简体   繁体   English

Django rest 框架:UniqueValidator 将字段转换为大写

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

I can save the mac_address to upper in database我可以将mac_address保存到数据库中的上层
And the mac_address value should be unique in database并且mac_address值在数据库中应该是唯一的

But if the client send me a lower case json like {"mac_address":'aa:bb:cc:dd:eE'}但是如果客户端给我发送一个小写的 json,比如{"mac_address":'aa:bb:cc:dd:eE'}
and my database already had mac_address with 'AA:BB:CC:DD:EE'我的数据库已经有mac_address'AA:BB:CC:DD:EE'
But client still got 201 created success但是客户端还是获得了201 created success
Why wouldn't my UniqueValidator work ??为什么我的UniqueValidator不起作用?
Please help me find out请帮我找出来

views.py视图.py

I try ListCreateAPIView and APIView我尝试ListCreateAPIViewAPIView
Both can't work well I think the problem is UniqueValidator part两者都不能很好地工作我认为问题是UniqueValidator部分

I find the document use validate_<field_name> But My code not work我发现文档使用validate_<field_name>但我的代码不起作用

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在序列化程序中定义valid_email方法

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.您的UniqueValidator正在按预期工作。 Because the default lookup for UniqueValidator is 'exact'.因为UniqueValidator的默认查找是“精确”。 Whereas you are in need of 'iexact' which does a case insensitive lookup.而您需要“iexact”,它进行不区分大小写的查找。 So change the mac_address serializer field to :因此,将mac_address序列化器字段更改为:

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.注意:使用validate_前缀方法会起作用,但是当您尝试使用序列化程序进行部分更新时可能会出现问题。 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.那时您希望序列化程序免除对mac_address字段的唯一性检查,或者至少从您施加约束的查询集中排除当前对象。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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