Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Common custom validation for DRF and Django admin

I have user table in which have to put unique email constrain on staff users and unique phone constrain on non staff user. Now I want to maintain this constrain in DRF API and in Django admin, how to achieve this without code duplication.

As I see from DRF 3.0 onwards, all validations are performed explicitly for serializer (If I have overwritten unique_validation or clean method to perform conditional validation, I have to write this custom validation separately for serializer as well) so how to write a custom validation that works both for DRF API and Django admin without code duplication ?

like image 579
r.bhardwaj Avatar asked Oct 17 '22 19:10

r.bhardwaj


1 Answers

If your model doesn't have nested relationships, this should work.


class ValidateModelMixin(object)
    def validate(self, attrs):
        attrs = super().validate(attrs)
        obj = self.Meta.model(**attrs)
        obj.clean()
        return attrs

class SomeModelSerializer(ValidateModelMixin, serializers.ModelSerializer):
    #...
    class Meta:
        model = SomeModel

But in my case, I have nested models and I need to override create() and update() methods in serializer. My solution to keep validations in only one place:


def create(self, validated_data):
        # Remove nested and M2m relationships from validated_data
        firstmodel_set = validated_data.pop('firstmodel_set') if 'firstmodel_set' in validated_data else []
        .....
        # Get instance of project
        instance = Project(**validated_data)
        instance.clean()

        # If clean method doesn't raise any exception, create.
        project = instance.save()
        ......

If you want serialize validations messages .. maybe something like that will help you ...

def validate_instance(instance):
    try:
        # Call model validation
        instance.clean()
    except ValidationError as e:
        raise serializers.ValidationError(e)

Or you can use Signals and make validations on pre_save(). Take a look in https://docs.djangoproject.com/en/1.10/topics/signals/

like image 79
Vitor Hugo Morales Avatar answered Oct 21 '22 05:10

Vitor Hugo Morales