views:

275

answers:

2

Am I thinking about this all wrong, or am I missing something really obvious?

Python's style guide say's less code is better (and I don't think that's subjective... It's a fact), so consider this.

To use forms for all validation means that to write a model field subclass with custom validation, you'd have to:

  1. Subclass models.Field
  2. Subclass forms.Field
  3. Add custom validation to your forms.Field subclass
  4. Set your custom form field as the default form field for the custom model field
  5. Always use a django model form if you want to perform validation

With all validation in the model you'd just have to:

  1. Subclass models.Field
  2. Add custom validation to your models.Field subclass

Now you could use your model field in an API that bypasses all use of web forms, and you'd still have validation at lowest level. If you used web forms, the validation would propagate upwards.

Is there a way to do this without having to write the Django team and wait for them to fix this error?

+2  A: 

This sort of thing is already possible in Django's development version:

There are three steps in validating a model, and all three are called by a model’s full_clean() method. Most of the time, this method will be called automatically by a ModelForm. You should only need to call full_clean() if you plan to handle validation errors yourself.

See the docs.

e.g. (as part of your model class):

def clean(self):
    from django.core.exceptions import ValidationError
    # Don't allow draft entries to have a pub_date.
    if self.status == 'draft' and self.pub_date is not None:
        raise ValidationError('Draft entries may not have a publication date.')
    # Set the pub_date for published items if it hasn't been set already.
    if self.status == 'published' and self.pub_date is None:
        self.pub_date = datetime.datetime.now()

The ModelForm's validation process will call into your model's clean method, per this:

As part of its validation process, ModelForm will call the clean() method of each field on your model that has a corresponding field on your form. If you have excluded any model fields, validation will not be run on those fields. Also, your model's clean() method will be called before any uniqueness checks are made. See Validating objects for more information on the model's clean() hook.

Dominic Rodger
Thanks for adding the <ol>s to my post. I didn't know you could do that (ie, too lazy to ready markdown).
orokusaki
Is your answer telling me that if I define clean() on my model, I don't need to run super(MyModel, self).clean() also? It is purely for me?
orokusaki
+1  A: 

It is already being fixed, and will be in Django 1.2.

Daniel Roseman
Nice. That has been my primary beef with Django for the last year. I hate using model forms for anything except prototyping, and the Admin. I cannot tell you how freaking excited I am that they're fixing that.
orokusaki