4

I realize this question has sort of been asked here and here and elsewhere.

...but the responses seem a little inconclusive. I thought perhaps the following concrete example might invite some specific reasons why this is or is not a good strategy.

So, what's wrong with just doing this? Excluded fields and defaults seem to work just fine. Certain ORM methods won't call save(), but then you wouldn't leverage ModelForms either. Is there something else I'm missing? Is it just backwards compatibility?

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

class Person(models.Model):
    favorite_food = models.CharField(max_length=250)

    def clean(self, *args, **kwargs):
        if self.favorite_food == 'bacon':
            raise ValidationError('Bacon is not good for you!')
        super(Person, self).clean(*args, **kwargs)

    def save(self, *args, **kwargs):
        self.full_clean()
        super(Person, self).save(*args, **kwargs)

Doesn't it seem like a good rule of thumb to at least put validation in the model first, in the interest of DRY, "fat models"? ...And to only move validation logic out to ModelForms where the validation context might depend on fields outside of the model, say, for instance, the request.user's permissions? (And even then, if it's that important, maybe they should be in the model anyway?)

I really like validating against bacon there, in one place, instead of here, in the ModelFrom and again in and Admin form... Hoping to hear some solid arguments against doing just that!

Community
  • 1
  • 1
Jason Blum
  • 172
  • 5

1 Answers1

1

This may get closed as too broad, but I'll try and give the best answer I can and that is... maybe.

Django models are just that models, so approach this as a data modelling exercise and not as a forms vs. models thing. Its important to note that Django does provide documentation that actually encourages overriding the `clean* method, in cases like yours.

But, in the broader sense, to answer your question, below are some questions that may help answer yours:

  • Does it make sense to model this logic in the model? - If you have some certainty that a Person should never have bacon as a favourite, then modelling here isn't a problem. It is part of the domain, and enforcing it here is "logical".
  • Will the logic change occasionally? - Models (in my opinion) should remain relatively static, they are an abstraction of your business domain - which hopefully doesn't change often. If you find that your logic will change frequently, putting it into your forms is a better option. Fortunately, you can reuse forms between the main site and your admin site.
  • Will the logic change frequently? - Will the list of 'unacceptable' items change a lot? And at runtime? And by non-developer admins? The now we are back in the modelling phase. Perhaps there needs to be a model to manage "unacceptable foods", against which this model is checked.

Ultimately, whether this is a "good strategy" is highly subjective and dependent on your actual code, not just a fake Food model*. The ability to override the clean method exists for a reason, and as long as you can justify that position then you are good to go.

* Not that I have anything against contrived fake examples using food.

Community
  • 1
  • 1