1👍
✅
First of all, there is one clash in your Mask
, meaning there will be more than one version for the same type
since:
A is a capital letter of the Latin alphabet;
...
X is a capital letter of the Latin alphabet or a number from 0 to 9;
More precisely 0QWER9@123
corresponds to NAAAAXZXXX
but also to NAAAANZNNN
. Unless you impose some condition, which I will do in my example in order to obtain the desired result (Only the first numeric element gets 'N'
the others will get 'X'
).
Now, to answer your question. I believe an elegant way to implement this would be to write a custom validator that you can place in a separate file:
validators.py
def validate_sn_mask(value):
mask = ""
special_list = ["-", "_", "@"]
first_number = True
for character in value:
if character.isnumeric():
if first_number:
mask += "N"
first_number = False
else:
mask += "X"
elif character.isalpha():
if character.isupper():
mask += "A"
else:
mask += "a"
elif character in special_list:
mask += "Z"
else:
# Although you already have a regex in your Model
raise ValidationError({"msg": "Invalid Mask"})
qs = Type_Of_Equipment.objects.filter(sn_mask=mask)
if not qs:
raise ValidationError({"msg": "Mask has no correspondent type"})
return qs[0]
serializers.py
class EquipmentSerializer(serializers.ModelSerializer):
class Meta:
model = Equipment
fields = ['code', 'sn_number','type_of_equipment']
extra_kwargs = {
'type_of_equipment': {'required': False}
}
def validate(self, attrs):
equipment_type_instance = validate_sn_mask(attrs['sn_number'])
attrs['type_of_equipment'] = equipment_type_instance
return super().validate(attrs)
views.py
class GetOrCreateEquip(APIView):
def get(self, request):
...
def post(self, request):
serializer = EquipmentSerializer(data=request.data)
serializer.is_valid(raise_exception=True)
serializer.save()
return Response(serializer.data)
👤Niko
Source:stackexchange.com