Skip to content

Conversation

@Urth
Copy link
Contributor

@Urth Urth commented Nov 2, 2023

Fixes: #12731

This allows for validation of any m2m relation like tags. The CustomValidator receives the cleaned data from the form/serializer. The model instance is not consistently available in the model forms/serializers so is omitted from both.

Note: the available fields can vary per form/serializer for a model. You should always check if a field is defined in the cleaned data. Alternatively the form/serializer class could be given to the validator to help identify the calling stack.

The patch extends the CustomValidator class with 3 validation functions, documentation is still needed.

    def validate_data(self, data):                                              
        """                                                                     
        Custom validation method for model forms and model serializers, to be overridden by the user.
        Validation failures should raise a ValidationError exception.           
        """                                                                     
        return                                                                  
                                                                                
    def validate_form_data(self, data):                                         
        """                                                                     
        Custom validation method for model forms, to be overridden by the user. 
        Validation failures should raise a ValidationError exception.           
        """                                                                     
        return self.validate_data(data)                                         
                                                                                
    def validate_serializer_data(self, data):                                   
        """                                                                     
        Custom validation method for model serializers, to be overridden by the user.
        Validation failures should raise a ValidationError exception.           
        """                                                                     
        return self.validate_data(data)

These functions allow users to validate M2M relations with regular attributes in the form/serializer validation stage. Using this system you can make exclusive tags based on model attributes or validate combinations of M2M relations

class FooSiteValidator(CustomValidator):
    def validate_data(self, data):
        if data['name'] != 'foo':
            for tag in data['tags']:
                if tag.name == 'FOO':
                    self.fail('FOO tag is reserved for site foo', 'tags')

…d serializers

This allows for validation of any m2m relation like tags.
The validator receives the cleaned data from the form/serializer.
The model instance is not consistently available in the model
forms/serializers so is omitted from both.

Note: the available fields can vary per form/serializer for a model.
You should always check if a field is defined in the cleaned data.
@jeremystretch
Copy link
Member

While I appreciate the thought you've put into this solution, I'm afraid we can't reasonably support three discrete validation paths. We'll need to identify a solution that can be applied at the model level.

@Urth
Copy link
Contributor Author

Urth commented Nov 13, 2023

I agree that having model validation to manage this would be ideal but it is not coming to Django any time soon.
https://code.djangoproject.com/ticket/24731
But this change does provide a solution that matches the validation use cases provided by Django.
I would be happy to remove the distinction between serializer and form validation if that helps.

@jeremystretch
Copy link
Member

@Urth thanks for your work on this. I believe I've identified a simpler approach that doesn't require multiple validation paths in #14516. I have still have some work to do on that, but will continue down this path as it appears very promising.

I'm going to close out this PR for now, but if the alternative approach doesn't pan out I'm happy to revisit.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Jan 13, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Custom validators unable to validate tag presence

2 participants