Hi Russ,

On Jul 13, 12:11 pm, Russell Keith-Magee <russ...@keith-magee.com>
wrote:
> I have exactly 0 mad skillz as a front end guy, but I know that rich,
> pretty ajax widgets et al are necessary for a good user experience. My
> goal, as a backend guy with limited frontend skills, was to find a way
> to get the people who *did* have frontend skills to be able to package
> their widgets in such a way that I could reuse them.

Indeed, I share that goal.

> Now, the Media framework has been largely a flop in this regard
> (although we may be able to use bits of it in a support role in this
> new form work). However, my desire for a widget library is unquenched
> :-)

>From my perspective as a programmer, I think the Media framework is
brilliant. It just has one gigantic Achilles heel: it requires
touching Python code.

Honestly, I think if we're serious about wanting a vibrant ecosystem
of Django-enabled frontend widgets, design goal #1 should be that
creating a widget requires touching zero Python code. And I think
that's possible to achieve.

> My concern about doing this entirely in templates is that it makes the
> process of sharing a widget library a little more difficult. If it's
> just code, then it just needs to be in the PYTHONPATH. If there are
> templates too, then the templates need to be somewhere that they can
> be accessed.

So I think this is very much a programmer's perspective, almost
humorously so :-) "Just code" may seem easy to you, but from the
perspective of at least one experienced Django-template designer I've
talked to, being able to do it entirely in templates makes the idea of
sharing a widget library conceivable, as opposed to almost impossibly
intimidating if its "just code."

The app_directories template loader is installed by default. Getting
templates "somewhere they can be accessed" means creating a directory
on the PYTHONPATH with an empty models.py, an empty __init__.py, and a
"templates/" subdirectory, then putting that in INSTALLED_APPS. That's
it. How is that harder than following exactly the same steps for an
app that includes Python code? From the perspective of a non-
programmer, it's much easier.

> There's also more to a widget in this context than just the template
> -- for example, there's nominating the javascript triggers that the
> widget requires.

Yep, I had a lengthy conversation with Idan in IRC yesterday about how
to approach this. I touched on it in my proposal above briefly (it can
still just be handled with templates), but didn't discuss details like
the fact that a given widget's "JS/media" template should only be
included once on a page, regardless of how many times that widget was
used on the page, even in multiple forms. Which means that the
"render_form_js" filter probably actually needs to be a tag, so it can
accept an arbitrary number of form objects and render the widget JS
once for every widget in every form.

> I'm not saying that these problems can't be overcome -- just that it's
> a complexity that I want to make sure is covered.

Indeed. I think they can be overcome, but I fully agree that the
template-based proposal needs more fleshing-out to make sure it covers
all these use cases adequately.

> The filter syntax doesn't hit the 'render the form completely standard
> except for this one change on this one field' use case. However,
> there's nothing about the 'template' aspects of your proposal that
> need to be bound to filters; they could be equally accomodated in a
> template tag.

I agree that tag vs filter is an orthogonal question, and I'm not
opposed to converting them to tags. I agree that it may be necessary
in order to add an extra optional argument or two to handle some use
cases.

The default-except-for-this-one-field use case is actually quite
doable under the proposal as written; you'd just create a derivative
form-rendering template that inherits your default one, and just
override a small block of it to add a bit of conditional logic to
render a certain field differently, otherwise deferring to
block.super. That's DRY and reasonably easy, but I if render_form were
converted to a tag it might be possible to add some optional arguments
to it to make it even easier.

The other improvement I would probably want to make to the API as I
first proposed it would be a way to point a given form-render or field-
render at a given directory of widget-templates, with the individual
template still picked out by widget-name.

> My manifestation of this problem is slightly different -- it's the
> issue of how to ship a widget library that can be used anywhere. I
> suppose one argument here is that you just need to advertise your
> chrome with doctype support notes.
>
> Alternatively, since this is a template language, you could always
> introduce an {% if %} block and render conditionally on doctype...

Exactly. I can imagine a number of different ways a reusable widget
library might approach this problem: simply advertise support for a
certain doctype (don't discount the value of supporting this low-
barrier-to-entry option, even if it isn't ideally reusable), or use
template conditionals, or provide separate widget templates for
separate doctypes... I find it preferable to make the full power of
the template language available, and then let template authors use the
tools they know to iterate towards best practices in this area, rather
than hardcoding into Django particular ideas of which doctypes are
relevant and what changes have to be made in templates to support
them. It's not just a matter of closing slashes, also which attributes
are valid (of which there may be more added later that we don't even
know about now)... I think hardcoding current assumptions about
doctypes is just asking for maintenance headaches. I'd much rather
leave that concern where it belongs, fully in the hands of template
authors.

> > - I'm skeptical that the "chrome" abstraction buys very much in
> >  exchange for the overhead of the new concept and the syntactical and
> >  registration problems. As mentioned above, in practice I don't think
> >  layering different chromes on top of each other will work very
> >  often; they'll frequently have to be manually integrated into a new
> >  unified chrome anyway.
>
> This depends a little on the level at which chrome is implemented.
> Very low level "modify attribute" and "add class" chrome could easily
> be layered, and would address the common request of "how do I add
> class X to my widget". More complex chrome (like the skeleton for a
> calendar widget) would require more markup, and probably wouldn't be
> mixed with other complex chromes, but it might still be mixed with a
> simple chrome to add a class or an attribute (or a collection of
> attributes and classes packaged into a single chrome).

Of course, if template authors can override and edit the widget HTML
directly, they will never need to ask how to add class X to their
widget. Whereas if it's exposed via its own Django-specific
abstraction, we can be sure we'll still be seeing that question for
years to come. Finally having an answer ("well, you write some Python
code and some HTML and package it up as this thing called a 'chrome',
then you apply it using this new template tag API we just invented")
is a distant second-best to making the question unnecessary.

> >  I'm also concerned that it's still insufficiently flexible; the core
> >  input tag markup will still be hardcoded in the widget, thus
> >  requiring special-cases for anything in it that you might want to
> >  tweak (doctype, extra classes or attributes). This is the big one
> >  for me, as it means our core problem with the current system (markup
> >  hardcoded in Python code) would not be fully fixed.
>
> >  In contrast, being able to directly edit widget templates for your
> >  specific cases is simpler, more intuitive for designers, and fully
> >  flexible.
>
> Classes and attributes on the base widget are something that could be
> modified with chrome. If you look at the API for widget.render() right
> now, it's pretty flexible -- the issue is that there's no programatic
> way to get at that API from a template. Chrome is the way into that
> existing API, as well as providing a way to wrap decorating HTML and
> Javascript around the base widget.
>
> What exactly is your use case for something that designers want to
> customize in the raw widget that widget.render() doesn't expose?

Only one off the top of my head: modifying the actual rendered input
type with no Python-level changes. If we'd had full template-level
widget customization three or four months ago, my designer could have
swapped in an "email" input type for a "text" input type where
appropriate, fully at the template level, as soon as browser support
for it appeared, with no need for a new Python form widget or any
other Python-level changes. If you ask him, he will tell you in no
uncertain terms that this is something he ought to be able to do as a
front-end engineer. In fact, I just did ask him. His response: "Form
inputs are HTML. HTML is my job. In most areas, Django makes it really
easy for me to do my job. What's the motivation for making it hard
here?"

The key issue is familiarity and ease-of-use. For template authors,
not programmers. Template authors know perfectly well how to add
classes and attributes to HTML elements. Why should they have to use a
special API to do the same thing for form input elements? Again: if
the goal is for Django template authors to create an ecosystem of
reusable widgets, the system needs to be geared around the tools they
are comfortable with, not the ones programmers are comfortable with.
That means templates. And not Python code.

cheers,

Carl

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To post to this group, send email to django-develop...@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.

Reply via email to