funkybob / django-sniplates

Template snippet libraries for Django
MIT License
57 stars 18 forks source link

RFC: Arbitrary variables as nested content #55

Closed koterpillar closed 3 years ago

koterpillar commented 7 years ago

Motivation

I have the following widgets (simplified for brevity):

{% block _label %}
  <label for="{{ id_for_label }}">{{ label }}</label>
{% endblock %}

{% block CharField %}
  {% reuse _label %}
  <input id="{{ id_for_label }}" type="text">
{% endblock %}

For a particular use case, I want to generate the following:

<label for="id_my_field">Customized <a href="/somewhere">HTML</a> label</label>
<input id="id_my_field" type="text">

Where /somewhere is a result of reverse('some_view').

The hacky solution is set the label of the form field to the HTML and mark it safe. However, due to circular imports and mark_safe not playing along with reverse_lazy this isn't feasible, and besides, HTML belongs in the templates.

Solution

Sniplates has nested_widget, but it forces the variable name to be content, not label, and doesn't have the automatic attribute extraction of the form_field.

Mild option

{% form_field my_field nested_content_for='label' %}
  Customized {% url 'some_view' %} label
{% end_form_field %}

Upon seeing nested_content_for, form_field parses the inside content and assigns the result to label in the context. widget works the same. nested_widget is deprecated as it is equivalent to {% widget nested_content_for='content' %}.

If nested_content_for is not specified as an argument for form_field or widget, they behave like now.

Crazy option

{% form_field my_field nested %}
{% attribute 'label' %}
  Customized {% url 'some_view' %} label
{% attribute 'something_else' %}
  Multiple parameters can be specified!
{% end_form_field %}

Upon seeing nested as an attribute, form_field (and widget) look for {% attribute ... %} sections and add their result to the context. The advantage over the first option is the ability to specify multiple inline arguments.


I'm not particularly attached to the wording, etc. If you're okay with either option, I can write up a PR.

funkybob commented 7 years ago

Why can't you use {% url %} to get the lookup of the url?

Also, if this is the same problem you were having the other day, why must it be a lazy reverse? Why not do the reverse in the Form init?

koterpillar commented 7 years ago

I can put label in __init__, but that still leaves a chunk of HTML in the Python file. I never said I couldn't use {% url %}, though.

koterpillar commented 3 years ago

I don't remember why I needed this anymore...