On Thursday, 29 September 2022 at 06:29:30 UTC+2 aa...@aaronsmith.co wrote:Why doesn't Django validate Models on save()?I am aware that full_clean() is called when using ModelForms. But most web app development these days, and every django app I've ever worked with, are headless APIs. The default behavior is dangerous for the naive developer.Bringing View-level concepts such as forms or serializers down into celery tasks and management commands breaks separation of concerns, and having multiple validation implementations at different layers in the app is fraught with divergence and unexpected behavior.It's not right. The data store layer should protect the validity of the data.
--
You received this message because you are subscribed to the Google Groups "Django developers (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-develop...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-developers/566b4706-4075-485b-9122-eca24d3b67fcn%40googlegroups.com.
Why doesn't Django validate Models on save()?
--
You received this message because you are subscribed to the Google Groups "Django developers (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-develop...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-developers/37ec0c58-2561-4300-9ead-05160410c389n%40googlegroups.com.
--You received this message because you are subscribed to the Google Groups "Django developers (Contributions to Django itself)" group.To unsubscribe from this group and stop receiving emails from it, send an email to django-develop...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-developers/004c2b9b-6e36-4061-b860-17eb7ebee15en%40googlegroups.com.
It sounds like there is little support for this being the default. But I'd like to propose something that might satisfy the different concerns:1) A `validate` kwarg for `save()`, defaulted to `False`. This maintains backwards compatibility and also moves the validation behavior users coming to Django from other frameworks likely expect, in a more user friendly way than overriding save to call `full_clean()`.And/or...2) An optional Django setting (`VALIDATE_MODELS_DEFAULT`?) to change the default behavior to `True`. The `validate` kwarg above would override this per call, allowing unvalidated saves when necessary.These changes would be simple, backwards compatible, and give individual projects the choice to make Django behave like other ORMs with regard to validation. This being the Django developers mailing list I should not be surprised that most people here support the status quo, but in my personal experience, having had this conversation with dozens of coworkers over the years - 100% of them expressed a strong desire for Django to do this differently.
James - The problem with moving validation up the stack, i.e. to logical branches from Model (Form, Serializer) is that you must duplicate validation logic if your data comes from multiple sources or domains (web forms and API endpoints and CSVs polled from S3. Duplication leads to divergence leads to horrible data integrity bugs and no amount of test coverage can guarantee safety. Even if you consider Django to be "only a web framework" I would still argue that validation should be centralized in the data storage layer. Validity is a core property of data. Serialization and conversion changes between sources and is a different concern than validation.
--
You received this message because you are subscribed to the Google Groups "Django developers (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-develop...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-developers/458d7bbd-b542-4e9a-ab62-91afdfe4b78fn%40googlegroups.com.
> ... the duplication I was referring to is having both Forms and Serializers do validation.That's a separate issue.Can we merge various aspects of DRF into Django, so that it better handles building JSON APIs? Yes, clearly. One step of that is better content type handling, another is serializers. (There are others).On the serializer front, it would be a question of making django.forms better able to handle list-like (possibly do-able with FormSet) and nested data, and so on.Not a small project, but with things like django-readers, and Pydantic (and django-ninja), and attrs/cattrs showing new ideas, re-thinking about serialization in Django is about due.But the issue is here:> ... I also don't relish the thought of needing to use a Form or Serializer every time I alter a Model's data.I'm like literally, "¿Qué? 😳" - Every single time you get data from an untrusted source you simply **must** validate it before use. ("Filter input, escape output", I was drilled.) That applies exactly the same to a CSV file as it does to HTTP request data. (That your CSV is malformed is axiomatic no? :)If you want to enforce validation, with a single call, write a method (on a manager likely) that encapsulates your update logic (and runs the validation before save). Then always use that in your code. (That's long been a recommended pattern.) But don't skip the validation layer on your incoming data.I would be -1 to `validate` kwarg to `save()` — that's every user ever wondering should I use it? every time. (Same for a setting.)Rather — is this a docs issue? — we should re-emphasise the importance of the validation layer.Then if folks want a convenience API to do both tasks, they're free to write that for their models. (This is what Uri has done for Speedy Net. It's not a bad pattern.)
Mariusz - fair enough, I will consider my point made and apologies if it came off too strong. FWIW it's not just my opinion, it's shared by every developer (dozens) I've had this conversation with up until now. It's a stark contrast that makes me wonder how aware the core developers / old timers are of the broader user base's experience.
The reason I don't want to use serializers or forms in celery tasks is because validation should happen every time a model attribute is changed. This pattern would mean more imports and boilerplate scattered around my codebase any time I want to update a status attribute on a model.
I think you (and Django at large) are conflating Validation and conversion/serialization/santization/input filtering, I think of them as separate concepts.
And so I am still very strongly against trying to push a model-layer-validation approach in Django, even optionally.
Surely we can agree that something should happen here? The status quo is confusing, a footgun and a gotcha. If it's not Model's concern, then get it out of Model.
I'd like to chime in with this:
There was a point in time when we ran into this issue and solved it with our own Model descendant.
IMHO, I'm completely with Aaron on this: all the guts are there,
just not being used. It took me quite a while to wrap my brain
around the idea that validation would be specified in models, but
only used in forms. And then some more looking at why all the
support functions are in models, but not being used. It just
didn't compute why I would have validation when using Django one
way, but not when I wanted something a little different.
While all the arguments against providing this function are valid and good, they neglect that an implementation satisfying n00bs like me would really not carry any penalties: it's just an if in the model.save checking against a global setting. No code creep, no additional tests to write (but I'm pretty sure some of the existing ones might fail, django or end-app). It would remove some confusion, but grandmasters like yourselves could still turn it off and do it the way you believe is "the correct one".
Also, just to be clear: the above solution (turning this on)
yielded TONS of bugs when we did it for our projects. We vastly
improved unit testing following this implementation, so it was a
total win for us.
LP,
Jure
--
You received this message because you are subscribed to the Google Groups "Django developers (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-develop...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-developers/CAL13Cg8ZvG6%3DtCNEEKV-4rQURzZ_GFSuPRypkoOOqGULFC9pZw%40mail.gmail.com.