Make tag name a variable in form templates

81 views
Skip to first unread message

1337 Shadow Hacker

unread,
Jul 23, 2020, 7:24:37 AM7/23/20
to Django developers (Contributions to Django itself)
Hello

Currently, we can set attributes on widgets during runtime but the input tag name is hardcoded:


Which means that you currently have to copy the input.html template for every web component.

Is it possible to make the tag name a variable to enable using custom HTML elements without having to copy a template like we do with attrs ?

Thank you in advance

Adam Johnson

unread,
Jul 23, 2020, 11:51:07 AM7/23/20
to django-d...@googlegroups.com
I'm not sure I have an opinion on adding such a variable. It seems reasonable but I haven't seen much use of web components yet. I'm also not sure if e.g. the 'type' attribute is relevant if using a custom web component.

But afaict you can change the tag already by overriding render() to replace it, like:

class MyWidget(SomeWidget):
    def render(self, *args, **kwargs):
        # Swap <input> for <my-element>
        return super().render(self, *args, **kwargs).replace('<input', '<my-element', count=1)



--
You received this message because you are subscribed to the Google Groups "Django developers (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-develop...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-developers/-KA4DZPYgBR0IIfAEM7A4B22tZEgUZOhD5ihFHfxUrLd8xCl9scLrI-iOTm7CsKvvya6CrIWm2nZksqrvZDqcaZ2uMxhSeMcojzUCuOuQ0Q%3D%40protonmail.com.


--
Adam

1337 Shadow Hacker

unread,
Jul 23, 2020, 12:06:11 PM7/23/20
to django-d...@googlegroups.com
The type attribute might not be relevant to most custom elements, but they don't matter: if they are not supported then they will not be used.

Thank you for your interesting suggestion, do you think it is better to create a widget class per custom element instead of just switching the template_name variable or just setting the tag name like any attr ?


Adam Johnson

unread,
Jul 23, 2020, 12:53:33 PM7/23/20
to django-d...@googlegroups.com
do you think it is better to create a widget class per custom element instead of just switching the template_name variable or just setting the tag name like any attr ?

I'd imagine so. This way you can make required attributes their own arguments to __init__, and any other customization you might need. It will also make the form class a little clearer.

On Thu, 23 Jul 2020 at 17:05, '1337 Shadow Hacker' via Django developers (Contributions to Django itself) <django-d...@googlegroups.com> wrote:
The type attribute might not be relevant to most custom elements, but they don't matter: if they are not supported then they will not be used.

Thank you for your interesting suggestion, do you think it is better to create a widget class per custom element instead of just switching the template_name variable or just setting the tag name like any attr ?


--
You received this message because you are subscribed to the Google Groups "Django developers (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-develop...@googlegroups.com.


--
Adam

1337 Shadow Hacker

unread,
Jul 23, 2020, 2:12:10 PM7/23/20
to django-d...@googlegroups.com



Sent with ProtonMail Secure Email.

‐‐‐‐‐‐‐ Original Message ‐‐‐‐‐‐‐
Le jeudi, juillet 23, 2020 6:53 PM, Adam Johnson <m...@adamj.eu> a écrit :

do you think it is better to create a widget class per custom element instead of just switching the template_name variable or just setting the tag name like any attr ?

I'd imagine so. This way you can make required attributes their own arguments to __init__, and any other customization you might need. It will also make the form class a little clearer

So, you'd be against custom elements that just work after changing the tag ?

I really thought we should strive for that, and leverage custom elements to remove boilerplate code rather than adding more.

Carlton Gibson

unread,
Jul 23, 2020, 2:33:26 PM7/23/20
to django-d...@googlegroups.com
I’m not sure I’m quite following your issue. 

At least to begin, can’t you just provide a custom base template, that accepts whatever parameters you want? 

Maybe there’s a case for adjusting the existing templates, but I’d imagine making that decision based on code in play. (“Look, I’ve built this, and see there’s duplication here”)

I’d imagine there comes a point where the widget templates become too generic. Less comprehensible, and so harder to work with. Maybe abstracting out the base element name would go beyond that point. (Which is to say, a separate ‘component.html’ template might be better to use in such a case.) 

But it’s hard to say in the abstract. 

Perhaps if you could outline where you’re at and the issue you’re seeing in more detail it would be easier?

Sorry if I’ve missed somewhere where you’ve already posted this. 

Kind regards

Carlton 

--
You received this message because you are subscribed to the Google Groups "Django developers (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-develop...@googlegroups.com.

1337 Shadow Hacker

unread,
Jul 24, 2020, 8:07:10 AM7/24/20
to django-d...@googlegroups.com
For those who haven't followed, I'll try to re-explain prior to showing example code:

Currently, we can change the attrs declaratively without going through whatever override/boilerplate.

In 2020, we can use custom elements, which means that we also need to change the tag name.

We don't need special constructors because custom elements configures with attrs, which are already available declaratively.

Now for some examples:

class YourForm(forms.ModelForm):
    class Meta:
        model = YourModel
        widgets = dict(
             birth_date=forms.TextInput(attrs={'type': 'date', 'max': max_date})
        )

Victory ! We now have a native date field with a one-liner ! But what if we want to change to a duet date picker ? You need to change the tag name from "input" to "duet-tag-picker":

forms.TextInput(attrs={'type': 'date', 'max': max_date}, tag='duet-date-picker')

It seems the reason for being able to set attrs this way but not the tag name too is because this was designed prior to the custom element W3C standard that's now implemented in every browser.

Carlton Gibson

unread,
Jul 24, 2020, 8:17:18 AM7/24/20
to django-d...@googlegroups.com


> On 24 Jul 2020, at 14:06, '1337 Shadow Hacker' via Django developers (Contributions to Django itself) <django-d...@googlegroups.com> wrote:
>
> Now for some examples:
>
> class YourForm(forms.ModelForm):
> class Meta:
> model = YourModel
> widgets = dict(
> birth_date=forms.TextInput(attrs={'type': 'date', 'max': max_date})
> )

Right, but you can provide a different template here, components.html say, that took the `element` name.

> Victory ! We now have a native date field with a one-liner ! But what if we want to change to a duet date picker ? You need to change the tag name from "input" to "duet-tag-picker":
>
> forms.TextInput(attrs={'type': 'date', 'max': max_date}, tag='duet-date-picker')
>
> It seems the reason for being able to set attrs this way but not the tag name too is because this was designed prior to the custom element W3C standard that's now implemented in every browser.

Maybe. Maybe just that `input` is pretty generic in form land — it’s not 100% clear we need increase manageability by adding a template that allows constructing arbitrary HTML elements. (Note the __maybe__…)

I’d use a custom template to begin. Then when you’re at the point of preparing a PR we can look at whether adjusting the templates makes sense. (Hopefully that seems reasonable to you.)

Kind Regards,

Carlton

Tim Graham

unread,
Jul 24, 2020, 9:07:39 AM7/24/20
to Django developers (Contributions to Django itself)
For me, a custom widget (that could use its own template) looks cleaner. Something like birth_date=DatePicker() seems more readable and doesn't require repeating "tag='duet-date-picker'"" each time. If you prefer your one-line version, you could override the input.html template and make the tag name a variable. I wouldn't advocate for that change in Django's input.html template.

1337 Shadow Hacker

unread,
Jul 24, 2020, 1:18:27 PM7/24/20
to django-d...@googlegroups.com
If I understand correctly:

- changing attrs declaratively is "clean enough"
- changing the tag input declaratively is "not clean enough, a custom widget and template must be done"

This seems contradictory to me.

Should I subclass every widget to add a custom template that allows changing the tag name ?

Tim Graham

unread,
Jul 24, 2020, 2:44:19 PM7/24/20
to Django developers (Contributions to Django itself)
A datepicker is rather different from a plain TextInput widget so I think it's good design to use a separate widget. If Django provided datepicker functionality, I'm fairly sure it would be provided as a separate widget rather than instructing users to use something like forms.TextInput(tag='duet-date-picker'). Consider widgets like NumberInput,  EmailInput, URLInput. We use separate widgets rather than something like forms.TextInput(input_type='number').

1337 Shadow Hacker

unread,
Jul 24, 2020, 2:47:37 PM7/24/20
to django-d...@googlegroups.com
You're absolutely right, except that I'm not trying to contribute a datepicker in Django, i'm not trying to make a reusable datepicker, I'm just trying to change the tag name as easily as I can change the tag attributes because it's now a valid W3C standard.

Tim Graham

unread,
Jul 24, 2020, 4:10:19 PM7/24/20
to Django developers (Contributions to Django itself)
My point is that if Django used variables for tag names in its widget templates, it would suggest developers write code that's inconsistent with Django's design philosophy. As was pointed out with things like the 'type' attribute, these templates aren't meant to be generic templates for web components.

1337 Shadow Hacker

unread,
Jul 24, 2020, 4:20:18 PM7/24/20
to django-d...@googlegroups.com
There is no consistent philosophy that lets us change tag attributes but not tag names once it's valid HTML.

These templates were not made for custom elements because they didn't exist, but it turns out supporting the custom element W3C standard is super easy: just let users set the tag name like you already let them set the tag attributes.

My point is that if Django used variables for tag names in its widget templates, it would suggest developers can build HTML that's consistent with W3C standards, which any web framework should support OOTB, and if that's not their philosophy then either W3C standards have to change either the web framework has to change.

1337 Shadow Hacker

unread,
Jul 24, 2020, 4:38:52 PM7/24/20
to django-d...@googlegroups.com
Wait a minute you, are you suggesting that we should have a Python API to generate HTML tags (like, Ryzom, Iommi, and many others) and build on that instead of templates for widgets ?

I wouldn't have asked for so much, but I really love this idea, as someone who is deeply bored by templates, which are a very poor way of graphical interfaces, as demonstrated by the GoF: the Decorator pattern are best suited for that, and my theory is that this alone is the reason many people prefer component based development so much, anyway, HTML is a tag based language so it's actually Decorator/GoF compatible, which is not the case of templates.

Templates were made to maintain a silo between frontend devs and backend devs, that's exactly why they offer such a poor feature set (like, not being able to make a function call ! fixed by jinja2 at least). That philosophy has been refutated not only by fullstack devs which I believe many of us are (I've been dealing websites for 20 years now), but mainly by the DEVOPS philosophy which I believe we're all aware of by now: it aims at breaking the silos open.

Did I get a bit carried away, revealing my secret plans to keep Django relevant for power hackers in 2020 ? Well, sorry about that.

Anyway, GO DJANGO ! Let W3C fix our JavaScript problem :)
Reply all
Reply to author
Forward
0 new messages