I'd considered having a `validate` attribute on save(), but this feels unnecessary because we can already have model.full_clean(), having `validate` seems superfluous.
One idea I'd had was to only validate fields which had changed. The reason for this is because we cannot assume data in the model from previous save() will validate correctly on this save() (i.e. in the event of validation rules changing). However the concept of only validating changed fields seems confusing and likely to sting a lot of people. Ultimately I think code based validation cannot be enforced at the model layer for these reasons, with the exception of IntegrityError raised from db constraints (which in my opinion is completely different to validations in code). I'd like to hear what a core dev has to say on the matter, at the very least I think this is worthy of a docs patch to explain this more clearly to users. Cal On Wed, Oct 16, 2013 at 5:20 AM, poswald <[email protected]> wrote: > One problem with it as you've found is that you sometimes do want control > over it on a per-model or even per-instance (per-save) basis. One way to > deal with this is to create something like the following that you can > extend in your models: > > class ValidatedModel(models.Model): > def save(self, validate=True, *args, **kwargs): > if validate: > self.full_clean() > super(ValidatedModel, self).save(*args, **kwargs) > > class Meta: > abstract = True > > > This helps you if you're trying it follow the 'fat model' philosophy and > centralize the validation logic down out of the forms and into the model > layer. It might end up validating twice if used in a model form though, I'm > not sure. I personally wouldn't be against having a setting to change in > the project-wide default behavior in a future Django version, but I think > the ability to override it is important. > > > > > On Wednesday, October 16, 2013 1:15:04 AM UTC+9, Cal Leeming [Simplicity > Media Ltd] wrote: > >> Sorry I should have made myself a little more clear. >> >> When I said "invalidating data inside your models" I was referring to any >> previous data that was saved when the validator was set to a minimum length >> of 4 characters. By then changing the validator to be 5 characters, you are >> effectively breaking save() on any data that was saved before that point, >> and the ability to fix the model data may not be available in that specific >> save() context. For example, a cron job that updates a "last_checked" field >> on the user would not necessarily have data relevant to changes in the >> users phone number (which could have its min/max length changed at any >> point in the validators life time). >> >> Hope that makes more sense >> >> Cal >> >> >> On Tue, Oct 15, 2013 at 5:12 PM, Cal Leeming [Simplicity Media Ltd] < >> cal.l...@**simplicitymedialtd.co.uk> wrote: >> >>> I've been thinking about this a little bit more, and it seems that the >>> design approach of validating on save() is not entirely correct. >>> >>> For example, say you have a validator that ensures a field must be at >>> least 4 characters long, and a few months later the validation is then >>> changed to be 5 characters long. This means any save() call on that field >>> (which may include a modification to a field which is unrelated to the >>> change being made) will then stop that save from happening. By applying the >>> validation at the model level, you are then potentially invalidating data >>> inside your models. This is fine for forms, because it can be handled at >>> the user side (by returning a form error saying X field is incorrect), but >>> would cause problems at the model layer. >>> >>> I think by design it would be very wrong to validate the model fields at >>> the point of save(), despite seeming like it would be the correct thing to >>> do. >>> >>> Could someone please verify if I have come to the correct conclusion >>> here? >>> >>> Cal >>> >>> >>> On Tue, Oct 15, 2013 at 4:43 PM, Cal Leeming [Simplicity Media Ltd] < >>> cal.l...@**simplicitymedialtd.co.uk> wrote: >>> >>>> Hello, >>>> >>>> I am trying to understand why field validators (model.full_clean()) are >>>> not called for model.save() >>>> >>>> I've spent about an hour reviewing all the discussions/replies on this >>>> subject; >>>> http://www.xormedia.com/**django-model-validation-on-**save/<http://www.xormedia.com/django-model-validation-on-save/> >>>> http://stackoverflow.com/**questions/4441539/why-doesnt-** >>>> djangos-model-save-call-full-**clean<http://stackoverflow.com/questions/4441539/why-doesnt-djangos-model-save-call-full-clean> >>>> https://code.djangoproject.**com/ticket/13100<https://code.djangoproject.com/ticket/13100> >>>> https://groups.google.com/**forum/#!topic/django-** >>>> developers/uIhzSwWHj4c<https://groups.google.com/forum/#!topic/django-developers/uIhzSwWHj4c> >>>> >>>> From what I can tell this was rejected on the basis of breaking >>>> backwards compatibility. >>>> >>>> It is unclear whether this would have been desired behavior had >>>> backwards compatibility not been an issue. >>>> >>>> It also seems to me that it would be possible to maintain backwards >>>> compatibility by using settings flags to determine the default behavior, >>>> albeit at the cost of increased complexity. >>>> >>>> So I have four questions; >>>> >>>> 1) Without taking backwards compatibility into consideration, is it >>>> reasonable to expect field validation automatically upon calling >>>> model.save() >>>> 2) At what point would Django devs be willing to break backwards >>>> compatibility? Would this be considered on 2.x, or is it life time? >>>> 3) Could backwards compatibility not be maintained by means of a flag >>>> in settings? For example, settings.MODEL_VALIDATE_ON_**SAVE=True would >>>> cause the validation to be handled using the new approach? >>>> 4) Assuming this cannot/will not be implemented, what would be the most >>>> suitable workaround? Are there any risks in calling full_clean() without >>>> ever using ModelForm? Should ModelForm always be used instead of using a >>>> model directly? etc. >>>> >>>> Any comments/feedback would be much appreciated, I am also happy to >>>> spend time updating docs to reflect responses in this thread. >>>> >>>> Thanks >>>> >>>> Cal >>>> >>> >>> >> -- > You received this message because you are subscribed to the Google Groups > "Django developers" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to [email protected]. > To post to this group, send email to [email protected]. > Visit this group at http://groups.google.com/group/django-developers. > To view this discussion on the web visit > https://groups.google.com/d/msgid/django-developers/fa2c2936-4e44-4132-863c-e93c3ee7da8a%40googlegroups.com > . > For more options, visit https://groups.google.com/groups/opt_out. > -- You received this message because you are subscribed to the Google Groups "Django developers" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. To post to this group, send email to [email protected]. Visit this group at http://groups.google.com/group/django-developers. To view this discussion on the web visit https://groups.google.com/d/msgid/django-developers/CAHKQagH_pMvfd%2BNbP9YmVzStWSLhNtZ8t20OJ7KhbGi9NCYgVQ%40mail.gmail.com. For more options, visit https://groups.google.com/groups/opt_out.
