在 Django 中,如何使用模板和 DB 对象中使用的动态 URL 实现样板 HTML 变量?

Posted

技术标签:

【中文标题】在 Django 中,如何使用模板和 DB 对象中使用的动态 URL 实现样板 HTML 变量?【英文标题】:In Django, how to implement boilerplate HTML variables with Dynamic URLs used in templates and DB objects? 【发布时间】:2020-01-08 21:28:34 【问题描述】:

在 Django 中,在我的数据库中,我创建了包含样板 html 和动态 URL 的字符串变量,但我无法让它们在我的模板中工作。

我使用的是 render_as_template (https://github.com/danielrozenberg/django-render-as-template/blob/master/render_as_template/templatetags/render_as_template.py),所以动态 URL 可以工作。我尝试了自定义模板标签,但是当我将它们与 render_as_template 一起使用时,它无法加载。

然后我尝试了自定义上下文处理器。我在上下文处理器中创建了两个函数,一个用于超链接,一个用于工具提示。我让工具提示处理器工作,但我只能通过查询集中自动生成的字典中的编号在模板中引用它们。

我对超链接处理器做了同样的事情,然后尝试修改它以使用字符串键而不是整数,但它不会加载所有字段。我一定是错过了什么。

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>

在template.html中,发生以下情况:

    呈现,但动态 URL 失败。 根本不呈现变量。否则页面加载正常。 呈现,但动态 URL 失败。 根本不呈现变量。否则页面加载正常。 根本不呈现变量。否则页面加载正常。 仅呈现“售后支持”]>”,而不是来自 DB 的完整超链接字段。 抛出此错误:
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>']>
    工作正常。

% render_as_template Boilerplate_tooltip.0 % 很好用,但我更愿意通过字符串键引用模板中的变量。毕竟,Django 模板语言的精神是它的模板可以被非程序员读写。有什么想法吗?

【问题讨论】:

你为什么要这样做? 我有一些工具提示和超链接,它们在整个网站中多次出现。如果我必须更新它们中的任何一个,我将不得不检查它们使用的每个实例(每个工具提示 30 多次)。如果可能,我宁愿只更新一次变量。干燥。 en.wikipedia.org/wiki/Don%27t_repeat_yourself 哦,如果有帮助,我也会在数据库字段中使用这些样板变量。无论哪种方式,我都需要使用 % render as template % 或使动态 URL 正常运行的东西。我可以为我的变量尝试模板,而不是上下文处理器或自定义标签。在项目的后期,我将使用 webscraper 从几个外部 URL 中选择一个,所以我认为 DB 非常适合存储当前的最佳 URL。但是,这些将是外部 URL,而不是项目内的动态 URL。 【参考方案1】:

我回去尝试自定义标签,这似乎有效:

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 %

当在数据库字段中包含 % rdo_hyper2 % 或其他自定义标签时,我还必须每次都在该字段的顶部使用 % load custom_tags % 否则它会抛出:

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

希望这不是资源密集型的!

【讨论】:

以上是关于在 Django 中,如何使用模板和 DB 对象中使用的动态 URL 实现样板 HTML 变量?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 django 模板中的一行中显示来自 db 的输出文本

如何过滤和统计 DJANGO 模板中的对象?

告诉 django 使用哪个 db 模板

Django:如何编写查询以使用多列进行排序,通过模板显示

如何在 Django 模板中使用带有外键对象的 get_absolute_url()

Django 字典对象在模板中不显示任何内容,但打印到控制台