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.