I don't think the same argument applies because no one (I hope) is calling form.is_valid() in templates.
#2. There was an inconsistency with the is_staff, is_active, is_superuser attributes and is_anonymous, is_authenticated as methods. I'm not sure what the inconsistency is with forms. Yes, there's an Form.is_bound property and an is_multipart() method but I don't see a need to convert all is_*() methods to properties.
In my mind, the security ramifications were the main reason for the previous change, and I don't see those concerns here. Changing Form.is_valid() to a property seems like it would cause much more disruption across the Django ecosystem than the gain would be worth.
#1. Regarding templates, one of the arguments for the previous change was:
Django 1.8 worsens the situation significantly:{% if request.user.is_authenticated %}does the right thing in a Django template but is a security vulnerability in a Jinja2 template!
#2. There was an inconsistency with the is_staff, is_active, is_superuser attributes and is_anonymous, is_authenticated as methods. I'm not sure what the inconsistency is with forms. Yes, there's an Form.is_bound property and an is_multipart() method but I don't see a need to convert all is_*() methods to properties.
In my mind, the security ramifications were the main reason for the previous change, and I don't see those concerns here. Changing Form.is_valid() to a property seems like it would cause much more disruption across the Django ecosystem than the gain would be worth.
#3 "Errors should never pass silently."Which they do if you write:if form.is_valid:# will always be executed# as it is always true
Replacing functions with properties will create a lot of churn in the people using the mentioned functions.
Another approach might be to wrap these functions in a class with `__call__` and `__bool__` both calling the underlying function. Or `__bool__` raising an error? [1]
I myself am a fan of errors here.
[1] and __nonzero__.
--
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 post to this group, send email to django-d...@googlegroups.com.
Visit this group at https://groups.google.com/group/django-developers.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-developers/e36d0f0a-fee8-4340-9d8a-24402dd55b76%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Hello,On 29 Sep 2016, at 19:57, Sven R. Kunze <srk...@gmail.com> wrote:#3 "Errors should never pass silently."Which they do if you write:if form.is_valid:# will always be executed# as it is always trueThis is perhaps the strongest argument in this discussion but I’m not convinced it’s strong enough to make the change.It’s weaker than the inconsistency that appeared between `{% if request.user.is_authenticated %}` in Django templates and `{% if request.user.is_authenticated() %}` in Jinja2 templates when Django started supporting both natively. The root cause of that inconsistency was Django’s auto-calling of callable in templates. This factor doesn’t exist here.
Writing `if some_callable:` instead of `if some_callable()` will cause the issue described here for any callable whose result makes sense in a boolean context. It’s always possible to build a security vulnerabilities with this behavior, by putting something security sensitive in the `if` or `else` block.Given that virtually anything can be evaluated in a boolean context in Python and in other dynamic languages such as JavaScript, I don’t know how to draw a line between what should be a property and what should be a method. For example, I don’t think we want to make QuerySet.exists a magic CallableBoolean, do we?
Generally speaking, properties are expected to be cheap and methods can be expensive. In my opinion, for lack of a better guideline, we should stick to this one. `is_valid()` falls into the expensive category, and for this reason it should remain a method.
Thinking of an alternative route:
It seems to me that the default `method.__bool__` is undesirable in Jinja2 templates. I do not know Jinja2 well enough, but maybe they could benefit from a patch where `if`-statements give a warning/error when the expression is a callable (with the default `FunctionType.__bool__`?
This would solve the issue not just for the methods you mention, but more in general.
[Or maybe Python itself should have that warning/error?]
Does that make sense?
--
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 post to this group, send email to django-d...@googlegroups.com.
Visit this group at https://groups.google.com/group/django-developers.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-developers/ecd30665-f698-4199-8fc3-d75ca66557d1%40googlegroups.com.
But independently, I still miss the point why {% if form.is_valid %} cannot be a problem in Jinja2?
Thinking of an alternative route:
It seems to me that the default `method.__bool__` is undesirable in Jinja2 templates. I do not know Jinja2 well enough, but maybe they could benefit from a patch where `if`-statements give a warning/error when the expression is a callable (with the default `FunctionType.__bool__`?
This would solve the issue not just for the methods you mention, but more in general.
[Or maybe Python itself should have that warning/error?]
Does that make sense?
On 11 Oct 2016, at 14:07, Sven R. Kunze <srk...@gmail.com> wrote:I took a sample of 4 of my colleagues and asked them what the problem with expressions like {% if form.is_valid %} is. They have no idea. They said "it might not make sense in some cases but when it makes sense, it doesn't look very terrible me”.
So, what's the real problem here?
Hello Sven,On 11 Oct 2016, at 14:07, Sven R. Kunze <srk...@gmail.com> wrote:I took a sample of 4 of my colleagues and asked them what the problem with expressions like {% if form.is_valid %} is. They have no idea. They said "it might not make sense in some cases but when it makes sense, it doesn't look very terrible me”.Can you show a non-contrived example, predating this discussion, of a situation where this pattern make sense?
So, what's the real problem here?The real problem is that templates aren’t the correct place to implement business logic such as form validation.
If I remember correctly, form.is_valid do the actual form validation
and return false in case of error.
On 11 Oct 2016, at 14:52, Sven R. Kunze <srk...@gmail.com> wrote:I did never say "let's do business logic in templates". AFAIK, displaying errors (or preparing for it HTML-structure-wise) requires knowing whether a form is invalid or not.
On 12 Oct 2016, at 12:21, Sven R. Kunze <srk...@gmail.com> wrote:Am Dienstag, 11. Oktober 2016 17:51:20 UTC+2 schrieb Aymeric Augustin:The API for displaying errors is form.errors.If the documentation implies otherwise, please accept my apologies!No problem. I now did read the documentation (https://docs.djangoproject.com/es/1.10/ref/forms/api/) to be 100% sure.It says: "The primary task of a Form object is to validate data. With a bound Form instance, call the is_valid() method to run validation and return a boolean designating whether the data was valid:" and furthermore "You can access errors without having to call is_valid() first. The form’s data will be validated the first time either you call is_valid() or access errors."So, the docs are actually pretty clear about what will happen (how to code works), but not so much about the intended usage.