Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

For Nested Serializers, the EnforceValidationFieldMixin.run_validation Method is Never Called #28

Open
NdubisiOnuora opened this issue May 21, 2019 · 2 comments

Comments

@NdubisiOnuora
Copy link
Contributor

Even though EnforceValidationFieldMixin (https://github.com/dealertrack/django-rest-framework-braces/blob/master/drf_braces/serializers/enforce_validation_serializer.py#L10) is added to the MRO of the Serializer and all nested Serializers, the Serializer's.run_validation method still does not run the EnforceValidationFieldMixin.run_validation method or those of any subclasses of EnforceValidationFieldMixin that might override run_validation.

The current problem that I'm trying to solve is to ensure that I can drop errors for invalid data sent to any of the nested Serializers. One example is one in which the nested Serializer expects a dictionary but a list is sent to it instead.

Example:

from drf_braces.serializers.enforce_validation_serializer import create_enforce_validation_serializer, EnforceValidationFieldMixin

from rest_framework import fields, serializers
from rest_framework.fields import empty
from rest_framework.serializers import Serializer


class DropInvalidFieldsMixin(EnforceValidationFieldMixin):

    def run_validation(self, data=empty):
        self.parent.must_validate_fields = []
        try:
            return super(EnforceValidationFieldMixin, self).run_validation(data)
        except serializers.ValidationError:
            field_name = getattr(self, "field_name")
            raise fields.SkipField(
                'This field "{}" is being skipped as per enforce validation logic.'
                ''.format(field_name)
            )


class PlayerSerializer(Serializer):
    name = fields.CharField()


class PlayersSerializer(Serializer):
    player = PlayerSerializer(many=True)


class GameSerializer(Serializer):
    name = fields.CharField()
    country_of_origin = fields.CharField(required=False)
    players = PlayersSerializer(required=False)


serializer_class = create_enforce_validation_serializer(GameSerializer, strict_mode_by_default=False)

serializer = serializer_class(data={"name": "Chop the Money", "country_of_origin": "Nigeria", "players": [{"name": "Olusegun Obasanjo"}, {"name": "Sani Abacha"}] })

>>> serializer.is_valid()
>>> {'players': {u'non_field_errors': [ErrorDetail(string=u'Invalid data. Expected a dictionary, but got list.', code=u'invalid')]}}

I expect that the GameSerializer be valid and the incorrect data in the PlayersSerializer be dropped especially since self.parent.must_validate_fields is set to an empty list in DropInvalidFieldsMixin.run_validation.

@shosca
Copy link
Contributor

shosca commented May 21, 2019

Shouldn't you do this instead?:

class PlayerSerializer(Serializer):
    name = fields.CharField()

class GameSerializer(Serializer):
    name = fields.CharField()
    country_of_origin = fields.CharField(required=False)
    players = PlayersSerializer(required=False, many=True)

@NdubisiOnuora
Copy link
Contributor Author

@shosca: I can't modify the definition of GameSerializer, since another service expects it to be in that format. I'm piggybacking on that service, which does 99% of what I want. 😄

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants