Hi Simon,
On Mon, 2007-08-13 at 18:00 -0700, sime wrote:
> Hello all, I have some suggestions for newforms, which I've condensed
> into point form, excuse me if they seem a little blunt they are just
> meant to be concise --
>
> 1. Magic cleaned_data - So we can get/set values out of order and
> before the clean() run, having themselves clean implicitly as
> required.
Can you give an example of what you mean here? I can't visualise what's
going on.
As an aside, implicit cleaning (which means normalisation as well, for
forms) is often very fragile, because picking the right moment to clean
and normalise is not always possible. It might work well for fields in
isolation, but once you have any dependencies, it breaks because you can
only set one attribute or value at a time and so the dependency breaks.
Also not particularly efficient in those cases (lots of cleaning or
whatever when it's not required).
> 2. A pre_clean() hook - So we can still manipulate data, fields, and
> required settings etc before validation. Common use case is requiring
> or un-requiring fields A,B,C based on value of field X.
You already have full access to the form data. You can do whatever you
like before initialising the Form subclass (or afterwards).
> 3. Easy access to form/field errors - After validation, when I go to
> process() or save() my form, I need to be able to set form and
> sometimes field level errors - but there is no elegant way of doing
> this. Hacking with _errors, __all__, ErrorDict is ugly. Using another
> error reporting system is ugly and unnecessary, too.
Ugly is subjective and I can't see that it's particularly valid in this
case. Ugly, how?
On the technical level, you already have access to the errors. There's
the errors attribute on the Form class and the non_field_errors()
method. The ErrorDict class is a useful abstraction in that it knows how
to print itself (and shortly I'll commit a fix so that it can be
customised a bit more in that respect). But it's just a dictionary, too,
so you get back a dictionary of field names mapping to a ValidationError
class (which contains a list of the errors).
Again, an example of the improvement you propose might help, but it's
hard to imagine something that is more streamlined that retrieving all
the errors via one attribute access and getting back a dictionary of
errors.
> 4. Pass value to field clean_ method as parameter - Eg
> clean_field(self, value) - why bother users with the extra line of
> code? Obviously they are going to want the value, aren't they?
It's been discussed before why we haven't made this change. Bringing it
up again without at least addressing the previous arguments against
isn't going to work. It hasn't been considered worthy of the backwards
incompatible breakage, although I'm not putting serious money on that
not changing.
> 5. (Somewhat pedantic) Rename data[] to raw_data[] and cleaned_data[]
> to data[] - Has anyone seen how unnecessarily ugly this can get?
Again, this subjective "ugly" description. You haven't really improved
things significantly here, you've just changed the names. You might
prefer to think of raw and not-raw. Other people think of data and data
that's been changed (cleaned). We can't please everybody in a lot of
things like this and it's not worth trying to do so, because, at the end
of the day, it genuinely doesn't matter.
As a practical matter, breaking all existing newforms code isn't worth
it for this change.
> If these are all deemed to be ill-fated ideas, then to cover at least
> some of the above, I'd be grateful if anyone can please suggest --
>
> 1. How do I toggle field required settings for fields A,B,C dependent
> on the value of field X ?
First question would be whether you really need to toggle it on the
class. Multi-field validation is part of the form's clean() method, so
in there you would check whether field X is present and, if so, check
for the presence of values for A, B and C. The latter can be looked up
in self.cleaned_data(), since they will have already been cleaned and
normalised in isolation, so you can check for empty values quite easily
at that point.
The alternative (pre-cleaning) would require looking up X's value in the
unnormalised data (so being able to handle all of the possible empty
value representations). Then, if it's not "empty", running through
form.fields (it's a sequence) to find A, B and C and changing the
'required' attribute on their Field instances. That would also be
possible, but it looks less robust than doing it in the form's clean()
method.
> 2. How do I dynamically copy data from fields A,B,C to fields X,Y,Z
> before validation ?
data = request.POST.copy()
for first, second in zip(('A', 'B', 'C'), ('X', 'Y', 'Z')):
data[second] = data[first]
form = MyForm(data)
# etc...
Might need some tweaking based on the fact that data is a MultiDict, but
that should be close.
> 3. What is the recommended way of setting non_field_errors outside the
> clean methods?
Since you're modifying the internals of the Form subclass, you are going
to be adjusting form._errors['__all__']. If that key already exists, you
will need to append to form._errors['__all__'].messages so as not to
nuke any existing errors.
Appreciate that this isn't really a common usage, since you would
typically attach the validation to the Form subclass (so accessing
self._errors feels more natural, as you're working with your own class's
attributes, in a sense). If I had to do this more than once, I'd write a
little helper method to append an error to the __all__ key.
As a meta-item, although this response looks fairly negative on your
suggestions, I don't think you've really explained why they are
necessary or what they improve. Just saying something is "ugly" doesn't
help us evaluate the unspecified alternative. So if you have some
concrete suggestions on what you would like to see as replacements, that
might help your case a bit more. Do keep in mind that some things (like
data or raw_data) really are just going to be personal preferences and
since a few thousand people aren't all going to have the same intuition
and preferences, sometimes things are going to be spelt differently to
your choice. That's life. Other things, like making common tasks easier,
are worth considering, but a couple of the use-cases you mention above
(particularly your 3rd question) don't immediately strike me as common,
or necessarily good, maintainable programming practice. Fortunately,
it's all possible, as demonstrated, and every programmer carries around
a library of utility functions to make their own particular approaches
easier. If something's impossible, we will usually consider fixing that
(make the common things easy, the uncommon things possible).
Regards,
Malcolm
Regards,
Malcolm
--
Why can't you be a non-conformist like everyone else?
http://www.pointy-stick.com/blog/
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"Django developers" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at
http://groups.google.com/group/django-developers?hl=en
-~----------~----~----~----~------~----~------~--~---