0

I am trying to validate whether password1, password2 are matching not using object level validation because it is executed after all field level validations, but validate_field only accepts one value. How can I implement the following in rest framework?

def validate_password2(self, data):
        print 'validating...'
        password1, password2 = data['password1'], data['password2']           
        if password1 and password2 and password1 != password2: 
              raise serializers.ValidationError('The two passwords do not match.')         
        return password2

And when errors occur, the data in the form are cleared. How can I retain the input data even when the errors occur like django form.fields?

user2307087
  • 423
  • 11
  • 25

2 Answers2

4

Instead of adding field-level validation, add this check to your object-level validation because you require access to multiple fields.

Even the DRF docs define this:

Object-level validation

To do any other validation that requires access to multiple fields, add a method called .validate() to your Serializer subclass. This method takes a single argument, which is a dictionary of field values. It should raise a ValidationError if necessary, or just return the validated values.

You can just do the following:

def validate(self, data):
    ...
    password1 = data['password1']
    password2 = data['password2']
    if password1 and password2 and password1 != password2:
        raise serializers.ValidationError('The two passwords do not match.')
    ....
    return data

Also to access the initial data when errors have occured, you can use your_serializer.initial_data.

Rahul Gupta
  • 46,769
  • 10
  • 112
  • 126
  • First, thanks for the answer. If I have multiple fields that needs different validations then I have to add all that stuff in `validate` function. right ? and what will happen to built in validations like email validation. What if I access `initial_data` in field level validator ? is it bad practice ? – Pranav Sep 03 '15 at 11:29
  • If your multiple fields validations depend on each other, then you have to do that in `validate()` function, otherwise, do that in `validate_()` function. The built-in validations will hapen regardless of your custom validation, so you don't need to worry about it. If you really need the `initial_data` for doing some validations, then you should use it. – Rahul Gupta Sep 04 '15 at 02:49
  • Thanks, much helpful. Main concern was overriding `validate` will or will not override built-in validations. But now, clear. – Pranav Sep 04 '15 at 05:26
0

Something like this for validating password in DRF

def validate_password2(self, attrs, source):
    """
    password_confirmation check
    """
    password_confirmation = attrs[source]
    password = attrs['password1']

    if password_confirmation != password:
        raise serializers.ValidationError('password didnot match')

    return attrs
chandu
  • 1,053
  • 9
  • 18
  • I am using DRF v 3.1+, so does that accept attrs? As I know of, it only accept one value, the value of the field. – user2307087 Jun 04 '15 at 06:28
  • No idea regarding DRF 3.1+,please check this might help http://stackoverflow.com/questions/27591574/order-of-serializer-validation-in-django-rest-framework http://stackoverflow.com/questions/27591184/additional-serializer-fields-in-django-rest-framework-3 – chandu Jun 04 '15 at 06:54