Controlling form/widgets output

2009-01-21 Thread catsclaw

Hi all --

   I've started to poke around in customizing the generated form code
and providing my own widget instances, but the current Django form
code is written in such a way that it makes things nearly impossible.
   Here's just one example: when fields are written out to HTML, they
get asked "what attributes does this kind of widget need?".  Adding a
widget therefore requires rewriting the field classes you want the
widget to be used with, rather than letting the widget interrogate the
field classes.  That's not great design, and it means any changes to
form rendering becomes a major pain.
   Is there any work being done to clean up the way Django creates
forms?  I saw there was something being done with DOCTYPE
declarations, but it didn't look like that was making very extensive
changes.

-- Chris

--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To post to this group, send email to django-developers@googlegroups.com
To unsubscribe from this group, send email to 
django-developers+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/django-developers?hl=en
-~--~~~~--~~--~--~---



Re: Controlling form/widgets output

2009-01-21 Thread catsclaw

On Jan 21, 5:37 pm, Russell Keith-Magee 
wrote:
> >   Here's just one example: when fields are written out to HTML, they
> > get asked "what attributes does this kind of widget need?".
>
> Unless I'm misunderstanding your intent with this statement - No, they
> aren't. A form contains fields, which describe the type of data that
> is being collected and the validation procedures for said data. Each
> field provides a widget, which describes a HTML element that allows
> that data to be collected. When the form is rendered, it binds some
> data to a field instance in a BoundField, and renders the BoundField
> using the widget for the field.

   Well, it seems to me that makes for an *extremely* tight coupling
between the model and the view.  And it's a little difficult for me to
understand what value there is in such a tight coupling--if I've got a
DateField, why can't I have it represented in an HTML page by a
javascript calendar pop-up, or a text box, or three select boxes
(month, day, and year).
   Plus, any time you collect a password you need to display it in a
form using a password input, not the stock text input.  And I might
very well have two separate form fields which should be displayed as a
single unit.  There's a need to have the display decoupled from the
form logic.  Django just doesn't provide much help in doing that.

> The field isn't asked anything
> during the rendering process beyond "what is your widget?".

   Not true.  There's a "widget_attrs" method on the base Field class
which passes a widget and expects to be passed back a dictionary of
attributes to be added to the widget.  In other words, if I create a
widget which renders a CharField and I'd like to validate the maximum
length, I either *must* inherit from TextInput or PasswordInput, edit
the CharField class, or write a different CharField class that's aware
of my new widget.

> >   Is there any work being done to clean up the way Django creates
> > forms?  I saw there was something being done with DOCTYPE
> > declarations, but it didn't look like that was making very extensive
> > changes.
>
> In short, no. We completed a major refactor of the forms framework
> just before v1.0 landed, and we're not really looking to make another
> major change.
>
> However - our commitment is to backwards compatibility, not to no
> change at all. If you have a specific problem that can't be solved,
> feel free to make a specific suggestion on how to improve things.

   If I were writing it, I'd make the Form class responsible for
defining the order of the fields, the labels, the validation logic and
errors.  The Fields would be part of that.  I'd make a FormRenderer
class which was responsible for drawing a form in different formats
(as a list, as a table, etc ...) and Widgets would act as a bridge
between a Field (or group of fields) and the FormRenderer.

-- Chris
--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To post to this group, send email to django-developers@googlegroups.com
To unsubscribe from this group, send email to 
django-developers+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/django-developers?hl=en
-~--~~~~--~~--~--~---



Re: Controlling form/widgets output

2009-01-21 Thread catsclaw

On Jan 21, 7:20 pm, Malcolm Tredinnick 
wrote:
> In the larger scheme, I think this is one of those areas where people's
> initial intuition differs. Django's form classes generally push
> downwards, with the greater intelligence lying at the higher levels
> (forms know the most, then form field classes have more localised
> knowledge and the widgets have the least knowledge and are simply given
> the information that they should present).

   Well, I can see that; it just seems to me that a form (and fields)
should be responsible for managing data on the server side, while a
widget is responsible for managing data on the client side.  It has to
be, since the Fields aren't running there.

> Again, specific issues would be easier to address here, rather than
> general complaints. We have a lot of accumulated experience to suggest
> the current design isn't a total disaster and I'm yet to find anything
> that isn't possible in a fairly neat fashion with the current dependency
> direction. So what sort of things are you trying to do where you can't
> think of a way to implement them at the moment?

   I'm trying to replace some of form elements on my site with Dojo
widgets.  In some cases I can handle it by just modifying attributes.
But my foray into all this began because I needed to have the widgets
being rendered in a form aware of some properties set on the form
itself--so I could say something like "if you're rendering an INPUT
element, add a 'class=form-input' attribute to the rendered html".
   I initially assumed I could just subclass Form, and add my custom
Widget parameter to each Field.  Then my Form could check when
rendering a Widget whether it was a custom widget or not, and call a
special rendering method if it was.  But the Form rendering logic
doesn't make that easy at all.
   I ended first iterating over all the fields in the form and calling
a method which tells it what to do when it gets rendered, every time
it gets rendered.  Then I call the normal rendering functions, which
work as expected.  But I'm not very happy with that, since it relies
quite a lot on some of the internal details of how Forms work.

-- Chris
--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To post to this group, send email to django-developers@googlegroups.com
To unsubscribe from this group, send email to 
django-developers+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/django-developers?hl=en
-~--~~~~--~~--~--~---



Re: Controlling form/widgets output

2009-01-22 Thread catsclaw

On Jan 22, 12:12 am, Jacob Kaplan-Moss 
wrote:
> On Thu, Jan 22, 2009 at 4:57 PM, catsclaw  wrote:
> >   Well, it seems to me that makes for an *extremely* tight coupling
> > between the model and the view.
>
> I'm sorry to be so blunt, but your perception is misguided. Forms have
> no dependancy upon models, nor do models on forms, nor must views use
> forms, models, or anything, really.

   I could have been clearer.  I'm not talking about Django Models
here; I'm talking about models, views, and controllers from the Model-
View-Controller design pattern.  Django widgets would correspond to
views, while Django forms would correspond to models.  In the current
architecture, this division is very muddled; I suggested reducing the
interdependency and adding a FormRenderer class; that would allow the
display elements (widgets) to be handled by a display controller (a
form renderer) while the model elements (fields) were handled by a
model controller (the form).

> > And it's a little difficult for me to
> > understand what value there is in such a tight coupling--if I've got a
> > DateField, why can't I have it represented in an HTML page by a
> > javascript calendar pop-up, or a text box, or three select boxes
> > (month, day, and year).
>
> It's difficult to understand because you've assumed it's impossible;
> it's not. A quick google search for "django datefield select" ...

   No, no.  You're missing my point.  I was responding to Russell, who
said "A form contains fields ... Each
field provides a widget, which describes a HTML element that allows
that data to be collected."  That description--that forms contain many
fields, and each field corresponds to a widget--isn't sufficient to
explain the relationship between forms, fields, and widgets.  And it's
a very limiting conception of what the form functionality ought to do
for Django as well.

> >   Plus, any time you collect a password you need to display it in a
> > form using a password input, not the stock text input.
>
> Again, this is in fact not only possible, but easy::
>
>     class MyForm(forms.Form):
>         password = forms.CharField(widget=forms.PasswordInput)

   Yes, I know this.  That's why I used it as an example.
   This is a case where the field gets asked, during the rendering
process, "I'm drawing a PasswordInput, are there any extra attributes
I should add?" and the field adds the input length to the HTML.  I'm
rather aghast that Fields are expected to know about HTML at all, let
alone be aware of all the available widgets so they can modify them.
   A better design is to have the fields open to interrogation by
widgets.  That way, a widget can ask if there's a limit on the number
of characters in this field.  That way new widgets and new fields work
together, without having to know about each other ahead of time.

> Why don't we start over here: what is the problem? What did you try do
> do? What did you expect to happen? What actually happened?

   Very well.  I'm trying to write a subclass of Form that knows about
Dojo forms, and will render them appropriately.  To do this, I assumed
I would subclass Form (as DojoForm) and then create a widget for each
Dojo form element I wanted to use.  The DojoForm would have a number
of settings relating to the form as a whole, which would alter the way
each DojoWidget rendered itself.
   When a DojoForm gets passed to a template, I could then call a
method in the head of the document that would know what statements to
place in the Javascript, and a different method in the body of the
document which would render the actual form proper.
   What's the best way of doing this?

-- Chris
--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To post to this group, send email to django-developers@googlegroups.com
To unsubscribe from this group, send email to 
django-developers+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/django-developers?hl=en
-~--~~~~--~~--~--~---



Re: Controlling form/widgets output

2009-01-22 Thread catsclaw

On Jan 22, 12:12 am, Jacob Kaplan-Moss 
wrote:
> Why don't we start over here: what is the problem? What did you try do
> do? What did you expect to happen? What actually happened?

   Here's another problem I'm stuck at.  I'm trying to determine,
within a widget, whether I'm being asked to draw a field that is
required, so I can add JavaScript validation on the form submit.  Is
this possible?

-- Chris
--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To post to this group, send email to django-developers@googlegroups.com
To unsubscribe from this group, send email to 
django-developers+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/django-developers?hl=en
-~--~~~~--~~--~--~---



Re: Controlling form/widgets output

2009-01-23 Thread catsclaw

On Jan 22, 11:53 pm, Russell Keith-Magee 
wrote:
> On Fri, Jan 23, 2009 at 5:02 AM, catsclaw  wrote:
> >   I could have been clearer.  I'm not talking about Django Models
> > here; I'm talking about models, views, and controllers from the Model-
> > View-Controller design pattern.  Django widgets would correspond to
> > views, while Django forms would correspond to models.  In the current
> > architecture, this division is very muddled; I suggested reducing the
> > interdependency and adding a FormRenderer class; that would allow the
> > display elements (widgets) to be handled by a display controller (a
> > form renderer) while the model elements (fields) were handled by a
> > model controller (the form).
>
> Again, either I've misunderstood you, or you don't understand how MVC
> works. Your usage of terms like "model controller" and "display
> controller" certainly serve to confuse matters nicely.

Yeah, I shouldn't talk in shorthand.  And my conception of how
this probably ought to work, in a perfect universe, is not only
evolving as I talk about it, but is kind of secondary to the point I'm
trying to make, which is that Django's form classes don't separate the
roles cleanly.
My understanding of MVC is colored from my work with Java, which
used a modified version for their UI framework.  There, the View and
Controller are coupled, but divorced from the Model.

> The Form (model) holds a block of form data.
>
> The Widget (view) describes how to render form elements.
>
> The Field (controller) provides a way to extract data from the user
> interface (i.e., process raw blocks of text from a HTTP POST) and
> convert them into data suitable for storage in the model.

   But it doesn't work like that in practice.  The Form contains raw
HTML in its implementation (in the as_p method, for example) and
contains hardcoded links (through the BoundField class) to widgets to
use for a TextInput or Textarea.  A Field contains rules for
validating itself, while the Form has rules (although not many in the
base class) for validating groups of fields.  Fields also contain HTML
to inject into widgets.

> > And it's
> > a very limiting conception of what the form functionality ought to do
> > for Django as well.
>
> I fail to see why - but this might be a matter of misunderstanding of
> scope. Django's forms framework makes claims as a HTTP data
> manipulation tool with some minor sideline capabilities as a HTML
> layout tool. For any non-trivial, post-prototype application, I would
> expect the web designer to have much more control over form layout
> than Django's basic form renderer.

Sure, but that's the point.  If I had a trivial application, I
wouldn't *need* a framework to help.  The web designer should have
control over form layout.  But as it is, I can't very easily provide
that as a programmer.  And saying "draw this field over here" through
{{ form.field_name }} doesn't let me muddle about with the attributes
set on that field as a web designer.

> Coming up with perfect automated and customizable form layout has not
> historically been a core concern of Django - simply because it is
> impossible to well in an automated way. As a result, there hasn't been
> much focus placed on layout of _forms_.
>
> If this is the feature you're looking for (and it sounds like it might
> be) then sure - there is room for improvement. However - again - this
> could be accommodated without a wholesale teardown of the forms
> framework. What you're calling for is a refactor of
> Form._html_output() to allow for easier customization of form output.

   I never called for a wholesale teardown of the forms framework.
All I asked was "Is there any work being done to clean up the way
Django creates forms?"  In all the digging around I've done, I'd make
the following suggestions:

   1) Define some "standard" attributes for fields (like "max_length",
"max_value", "required") and document them.  Similarly, document the
python type each field stores its value internally as, and what types
its clean() method will accept.  Maybe this exists somewhere, but I've
been looking directly at the code, and it's not there.
   2) Delete (or heavily deprecate) the Field.widget_attrs method.
Widgets are expected to interrogate their associated Fields for this
information.
   3) Refactor the Form class into a Form class and a FormRenderer
class.  The FormRenderer takes a Form and provides an HTML layout.
The Form doesn't know any HTML, but is otherwise responsible for
everything it currently is.
   4) Change widgets (or, for backward compatibility, add an
"advanced" rende