Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django custom field validator vs. clean

Tags:

I would like to create TodayOrLaterDateField() which would subclass DateField() field as I am using this condition in many places. The purpose of this field would be avoiding putting dates from the past.

What is the most straightway way of doing this? I am confused with validator vs. clean method. I've tried with clean() but when comparing value to datetime.date.today() I am getting "compare unicode object to date" error.

I'm using Django 1.3

like image 449
Robert Avatar asked Jun 16 '11 15:06

Robert


People also ask

What is clean method in Django?

The clean() method on a Field subclass is responsible for running to_python() , validate() , and run_validators() in the correct order and propagating their errors. If, at any time, any of the methods raise ValidationError , the validation stops and that error is raised.

How can you validate Django model fields?

to_python() method of the models. Field subclass (obviously for that to work you must write custom fields). Possible use cases: when it is absolutely neccessary to ensure, that an empty string doesn't get written into the database (blank=False keyword argument doesn't work here, it is for form validation only)

What can be used to validate all model fields if any field is to be exempted from validation provide it in the exclude parameter?

clean_fields() method documentation: This method will validate all fields on your model. The optional exclude argument lets you provide a list of field names to exclude from validation. It will raise a ValidationError if any fields fail validation.

How does Django validate data?

Django forms submit only if it contains CSRF tokens. It uses uses a clean and easy approach to validate data. The is_valid() method is used to perform validation for each field of the form, it is defined in Django Form class. It returns True if data is valid and place all data into a cleaned_data attribute.


2 Answers

Validators only validate, they don't return the improved format; Clean methods both validate and return a (sometimes amended) value.

I think the way to go here is to just use a DateField with a validator as a inherited class of DateField with a default_validators set.

import datetime
from django.core import exceptions
from django.db import models
from django.utils.translation import ugettext_lazy as _

def validate_date_today_or_later(value):
    'Place this in validators.py and import it to keep your model a bit cleaner'
    if value < datetime.date.today():
        raise exceptions.ValidationError(_('Date must be today or later'))

class TodayOrLaterDateField(models.DateField):
    default_validators = [validate_date_today_or_later,]

edit: You can apply the same validator to your form fields as well if you just want it there and not in your whole app.

like image 115
fijter Avatar answered Sep 23 '22 03:09

fijter


You can extend models.DateField and override to_python method. Didn't tested on Django 1.3 but should work.

import datetime
from django.core import exceptions
from django.db import models

class TodayOrLaterDateField(models.DateField):
    def to_python(self, value):
        value = super(TodayOrLaterDateField, self).to_python(value)
        if value < datetime.date.today():
            raise exceptions.ValidationError(u'Date must be today or later')
        return value
like image 40
caio Avatar answered Sep 21 '22 03:09

caio