On Sun, Apr 3, 2011 at 11:46 PM, Gregor Müllegger <gre...@muellegger.de> wrote: > Hi, > > 2011/4/2 Russell Keith-Magee <russ...@keith-magee.com>: >> On Fri, Apr 1, 2011 at 11:57 PM, Gregor Müllegger <gre...@muellegger.de> >> wrote: >> Firstly, while it looks fine for a small example, I can see how it >> would rapidly deteriorate if you have lots of fields, or lots of >> custom field requirements for each field. Django's template language >> doesn't allow you to split tags over multiple lines, so what happens >> when my tag runs over 80 characters (this simple example is already a >> 69 characters)? > > (Having the possibility of multiline tags would be nice in many other cases as > well ... but that's another topic :-)
I'm not convinced it would be nice. Template tags are intended to be short and pithy, not space in which you can define your own domain-specific language. My feeling is that if a template tag proposal needs to invoke the "if only tags could span multiple lines" clause, the tag is already doing too much in it's definition. The one exception I will grant to this is comments -- requiring {% comment %} {% endcomment %}, or {# #} on every line is just daft, IMHO. However, it's a daftness that hasn't progressed into enough of an itch to drive me to scratch it myself. It's also unrelated to your proposal :-) > I don't see the use of more than two or three modifiers in a template tag in a > day to day use. Well.. I gave you an example -- a form with 10 fields, and I want to render 8 of them. > However it's of course possible to produce complex statements > that would need to span multiple lines. And it's already possible with the > syntax described in the proposal. > > You can use a {% formblock %} to extract the modifiers out of the form tag: > > {% formblock using layout "uni_form" %} > {% formblock using widget template "calendar" for myform.birthday %} > {% form myform using fields "firstname" "lastname" "birthday" %} > {% endformblock %} > {% endformblock %} > > Some might not like the syntax since you would encourage another level of > indention and another two lines for the closing tags. But you can use the > "configure" statement as described in the media handling section of my > proposal: > > {% form myform configure layout "uni_form" %} > {% form myform configure widget template "calendar" for myform.birthday %} > {% form myform using fields "firstname" "lastname" "birthday" %} I hadn't quite grasped how you were using formblock in your previous example. I now see what you're trying to do, and it makes a lot more sense. However, I'm not completely sold on certain aspects of this syntax. In particular, I have two objections: * it feels like it's trying to cram too much into a single template tag. * it requires a lot of duplication of "form myform configure" or "formblock myform using" Consider a slight variation that uses more tags: {% form myform configure %} {% layout "uni_form" %} {% widget "calendar" for DateField %} {% autocomplete "lastname" from "/users/lastnames" %} {% endform %} Then, when it comes time to render: {% form myform using %} {% field "firstname" %} <p>And some HTML decoration</p> {% field "lastname" %} {% endform %} or, using an iterative approach: {% form myform using %} {% for field in myform %} {% field field %} {% endfor %} {% endform %} or, using default layout: {% form myform %} This approach: * cuts down on the duplication, either in the form of indented form blocks, or in duplicated 'tag opening' content * avoids the need for a DSL embedded in the tag definition * avoids potential grammar ambiguities -- the less grammar there is in a tag, the less likely there will be edge cases in the parsing. >> Secondly, you appear to be using a single template tag for rendering >> both forms *and* fields. Is there a motivation behind this? > > Yes there is :-) The motiviation is, that {% form myform.birthday %} is just a > shorthand for {% form myform using fields "birthday" %}. You can also use it > to iterate over a form (like in your example below) and outputting it field by > field: > > {% for field in myform %} > {% form field %} > {% endfor %} > > I also don't see a need for an extra {% formfield %} tag. I don't see any > cases in which a {% formfield %} would be shorter, more flexible, easier to > use. It might be more readable, but I think it would end up as a stripped down > copy/alias of the form tag. See my previous comments about cramming everything into a single tag. Also, there's an implementation issue here; if the first argument to form can be a field or a form, then your implementation will need to have logic to differentiate the two -- either isinstance checks, or duck-type checks. Either way, it's a problem that is avoided by being explicit: {% form %} operates on forms, {% field %} operates on fields. >> Rendering modifiers >> ~~~~~~~~~~~~~~~~~~~~ >> > But like I already wrote above: I see your concerns with adding yet another > registry that might not be used very often. I would agree on dropping that > feature if you think its better to skip this until users demand it afterwards. I think this might be the better approach. Your proposal is already fairly ambitious, especially if it's going to include a reworking of admin's rendering. And, to that end, reworking admin's rendering should prove a useful testbed for whether it is needed at all. Also -- some food for thought; the reason that a registry is needed here is because you're defining an extension api for a monolithic {% form %} tag. If the rendering strategy used multiple tags, modifiers could also be defined as template tags: {% form myform %} {% mymodifier foo %} {% endform %} Then you don't need a separate registry; a "modifier" just becomes a template tag operating on the API exposed by the form rendering API (presumably a set of known objects in the local context of the form tag). If an end user wants a rendering modifier, they just define their own template tag and use it in a {% form configure %} block. >> Form rows >> ~~~~~~~~~ >> >> If you look at the existing as_* form layout tools, there is a >> distinction between gross form layout, and the layout of an individual >> form row. >> >> {{ form_header }} >> {% for field in form %} >> {{ pre_field }}} >> {{ field }} >> {{ post_field }} >> {% endfor %} >> {{ form_footer }} >> >> Conceptually, the rendering for pre/post field could vary depending on >> the field. How is this handled in your proposal? Is it part of the >> form renderer? Or part of the widget rendering? This overlaps with >> your discussion about error templates -- since errors (and their >> rendering) is one of the major pre/post rendering activities for both >> forms and fields. > > I'm not sure if I get your example right. Is it representing the output of a > "as_*" method? I looked into the django/forms/forms.py code again and I'm > quite sure that there is no header or footer of a form rendered. I also don't > see many usecases of including a header and a footer into the layout (like a > wrapping <table> or <ul> element) since this is very different from form to > form. One might want the wrapping <table> the other wants to put two forms > into one <table> element etc. I wasn't thinking so much about the <table> rendering, as some of the other non-row rendering details. For example, non-form errors currently have a rendering style that is defined in code (although they are programmatically exposed in a way that makes them compatible with templates). This is something that isn't definable on a per-row basis, but it is tied to a form. A second example -- handling of hidden fields. Again, these aren't strictly row-based, but they do impact on the rendering of the form as a whole. > The rest of the example in between would be rendered in the "row.html" > template of the form layout. E.g. the forms/layouts/table/row.html might look > like: > > <tr><th>{{ field.label_tag }}</th> > <td> > {{ field.errors }} > {{ field }} > {{ field.help_text }} > </td></tr> > > So you could define any pre_field and post_field stuff you want. I have also > not found a case in which the current rendering makes decisions based on the > field type. I think the admin does it (e.g. for checkboxes) but also in the > template level? Maybe you can give me a more specific hint on what you mean. Exceptions in radiobutton and checkbox rendering have historically been the thorn in my side whenever I look at Django's form library, so I'm just trying to think outside the box and think of the ways people may want to twist form rendering. I don't really have a specific use case in mind here. >> CSS/Media >> ~~~~~~~~~ >> >> I'm not wild about the idea of having to include the same form content >> twice in order to get CSS and JS included as where it is required. > > What do you mean by including the same form content twice? Do you mean the > duplicate use of the form tag? I thought I had solved this via the "configure" > statement. This will record all the used options so that you don't have to > duplicate the changes made to the form. Understood -- the flaw was in my understanding of your proposal. >> Secondly, it may be possible to play a trick on the template compiler. >> Jonas Obrist suggested this trick to me at Djangocon (US) last year; >> however, I haven't had a chance to dig into it any more. ... > That sounds HUGE and pretty cool. I had something like this in mind but > skipped the idea quickly because I thought that it's not be possible. > Especially with template inheritance. But if thats really possible > (theoretically) ... I will at least try it out since it would solve the media > handling problem in a very elegant way for the user. Its certainly worth a couple of days investigation to see if it's possible or plausible. Two more thoughts that have occurred to me: Firstly, from the point of view of proving the viability of your API, it might be worth collecting a selection of pathological use cases that can be used as a testbed. For example: * A form with 30 widgets * A form with only hidden widgets * A form with multiple date widgets, all using a calendar widget except for the last one * A page that contains two forms In effect, this is a set of conceptual test cases for your API -- in fact, it might even form the basis for your programatic test suite. Secondly: formsets. Are you intending to tackle formsets in this proposal? It's ok if you don't -- omitting formsets would be a good way to limit scope for the purposes of GSoC. However, I suspect the formset use case will ultimately be important for trunk inclusion. Even if you're not intending to tackle formsets, it's probably worth mentioning them in your proposal. In summary: I think you've got a strong proposal here. I've also taken a look at your new proposal timeline, and it looks good to me. There are certainly details to work out, and although they may appear significant on first impression, I think they're mostly cosmetic. A decision about using nested multiple tags or a single tag will certainly affect your implementation, but doesn't fundamentally alter the idea that you're driving at here: customizing the form rendering using templates. As long as your submission acknowledges the fact that there are some API issues still need to be resolved, I think your proposal is in reasonably good shape. Good luck with your final submission! Yours Russ Magee %-) -- 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.