2

In Django, in my DB I've created string variables containing boilerplate HTML with dynamic URLs, and I can't quite get them to work in my templates.

I'm using render_as_template (https://github.com/danielrozenberg/django-render-as-template/blob/master/render_as_template/templatetags/render_as_template.py) so the dynamic URLs work. I tried custom template tags, but when I use those with render_as_template, it fails to load.

I then tried a custom context processor. I created two functions in the context processor, one for hyperlinks, and one for tooltips. I got the tooltips processor to work, but I can only reference them in the template via their number in the auto-generated dict from the queryset.

I did the same with the hyperlink processor, then tried modifying it to use string keys instead of integers, but it doesn't load all of the field. I must be missing something.

custom_tags.py
from django import template
register = template.Library()

@register.simple_tag
def rdo_hyper():
    value = Boilerplate.objects.filter(name='RDO').values_list('hyperlink',flat=True)
    return value[0]
# It's only going to return one field.
# Expected output: <a href="{% url 'guides:rdo' %}" target=”_blank” rel=”noopener noreferrer”>Foobar</a>


# tried a non-DB version, just in case
@register.simple_tag
def rdo_hyper2():
    value = "<a href=\"{% url \'guides:rdo\' %}\" target=\”_blank\” rel=\”noopener noreferrer\”>Foobar</a>"
    return value
# Expected output: <a href="{% url 'guides:rdo' %}" target=”_blank” rel=”noopener noreferrer”>Foobar</a>
custom_context.py
from myapp.apps.wizard.models import Boilerplate

def boilerplate_hyperlink_processor(request):
    boilerplate_hyper = {
        "foo": Boilerplate.objects.filter(name='Aftermarket').values_list('hyperlink',flat=True),
        "bar": Boilerplate.objects.filter(name='Sights').values_list('hyperlink',flat=True)
    }
    return {'boilerplate_hyper': boilerplate_hyper}
# Expected output of boilerplate_hyper.foo: 
#<a href="{% url 'guides:aftermarket' %}" target=”_blank” rel=”noopener noreferrer”>Aftermarket Support</a>
#
# Expected output of boilerplate_hyper.bar: 
# <a href="{% url 'guides:sights' %}" target=”_blank” rel=”noopener noreferrer”>Sights</a>


def boilerplate_tooltip_processor(request):
    boilerplate_tooltip = Boilerplate.objects.values_list('tooltip',flat=True)
    return {'boilerplate_tooltip': boilerplate_tooltip}
# Expected output of boilerplate_tooltip.0: 
#<sup><a href="{% url 'guides:sights' %}" target=”_blank” rel=”noopener noreferrer” data-html="true" class="fas fa-info-circle pr-2" aria-hidden="true" data-toggle="tooltip" data-placement="top" title="Insert helpful tooltip info here.<br/><strong>Click</strong> for more info."></a></sup>
template.html
{% load static %}
{% load custom_tags %}
{% rdo_hyper as rdo_hyper %}
{% rdo_hyper2 as rdo_hyper2 %}
{% load render_as_template %}
...
<html>

{% autoescape off %}

1. {% rdo_hyper %} 
2. {{ rdo_hyper }} 
3. {% rdo_hyper2 %} 
4. {{ rdo_hyper2 }} 
5. {% render_as_template rdo_hyper %} 
6. {{ boilerplate_hyper.foo }} 
7. {% render_as_template boilerplate_hyper.foo %} 
8. {% render_as_template boilerplate_tooltip.0 %}

{% endautoescape %}

{# The hyperlink value is: 
<a href="{% url 'guides:aftermarket' %}" target=”_blank” rel=”noopener noreferrer”>
Aftermarket Support</a> #}

</html>

In template.html, the following occurs:

  1. Renders, but the dynamic URL fails.
  2. Doesn't render the variable at all. Otherwise page loads fine.
  3. Renders, but the dynamic URL fails.
  4. Doesn't render the variable at all. Otherwise page loads fine.
  5. Doesn't render the variable at all. Otherwise page loads fine.
  6. Only renders "Aftermarket Support']>" instead of the full hyperlink field from the DB.
  7. Throws this error:
TemplateSyntaxError:  
In template <unknown source>, error at line 1.
Could not parse the remainder: '\'guides:aftermarket\'' from '\'guides:aftermarket\''
1   <QuerySet ['<a href="{% url \'guides:aftermarket\' %}" target=”_blank” rel=”noopener noreferrer”>Aftermarket Support</a>']>
  1. Works fine.

It's great that {% render_as_template boilerplate_tooltip.0 %} works, but I would much rather reference variables in templates through a string key. After all, the ethos of Django's templating language is that its templates can be read and written by non-programmers. Any ideas?

brized
  • 51
  • 8
  • Why are you doing this? – Iain Shelvington Sep 06 '19 at 01:46
  • I have certain tooltips and hyperlinks that are featured several times throughout the site. If I have to update any of them, I'll have to go through every instance of where they're used (30+ times per tooltip). I'd rather just update once on a variable when possible. DRY. https://en.wikipedia.org/wiki/Don%27t_repeat_yourself – brized Sep 06 '19 at 02:07
  • Oh, also I'll be using these boilerplate variables from within database fields, if it helps. Either way, I need to use {% render as template %} or something that gets dynamic URLs to function properly. I can try out templates for my variables instead of a context processor or custom tags. Later in the project I'll be using a webscraper to choose one of a few external URLs, so I thought a DB would be a good fit for storing the current optimal URL. However those will be external URLs, not dynamic URLs from within the project. – brized Sep 06 '19 at 02:42

1 Answers1

1

I went back to trying custom tags and this seems to work:

custom_tags.py
@register.simple_tag(takes_context=True)
def rdo_hyper2(context):
    value = "<a href=\"{% url \'guides:rdo\' %}\" target=\”_blank\” rel=\”noopener noreferrer\”>Foobar</a>"
    rendered = context.template.engine.from_string(value).render(context)
    return rendered
template.html
{% load custom_tags %}
...
{% rdo_hyper2 %}

When including {% rdo_hyper2 %} or other custom tags inside a DB field, I also have to use {% load custom_tags %} at the top of that field every time or else it throws:

Invalid block tag on line 12: 'rdo_hyper2'. Did you forget to register or load this tag?

Hopefully that's not resource intensive!

brized
  • 51
  • 8