Django中可重用的HTML组件库

Ind*_*oad 8 html django django-templates

我有一个Django网站,其中有许多页面都有自己独特的内容和标记(而不是一个动态填充数据的单个模板).这些页面的模板源自一个通用的"工具"模板,该模板又来自"基础"模板.每个页面还有一个JS文件,用于为该页面编写脚本.每个页面数据分布在3或4个位置:

  • 模板
  • 页面脚本(可能还有其他特定于页面的静态)
  • 一个中央的"工具注册表",其中包含工具名称,描述和类别之类的内容
  • 对于某些工具,一组模板标签用于执行特定于该页面的某些HTML构造(例如,要在表格中显示的数据).

但是,虽然每个页面都有独特的布局和内容,但我仍然希望能够在页面之间共享常用的参数化HTML"片段".例如,一个页面的输入带有一个下拉按钮,使用Bootstrap,如下所示:

<div class="input-group">
    <span class="input-group-btn">
        <a class="btn btn-default dropdown-toggle" data-toggle="dropdown" href="#">
            Common baudrates
            <span class="caret"></span>
        </a>
        <ul class="dropdown-menu pull-right" id="common-baudrate-list">
            <li><a href='#'>9600</a></li>
            <li><a href='#'>115200</a></li>
        </ul> 
    </span>           
    <input class="form-control" type="text" id="baudrate-input" val="115200">
</div>
Run Code Online (Sandbox Code Playgroud)

我想制作一个可重复使用的参数化函数/模板/标签,它允许我输入这样的结构,例如"组ID","条目列表","左/右按钮位置","默认值".

到目前为止我看到的方法是:

  • 作为一个模板,它具有相当有限的语法,并且很难像这样的条目列表做一些事情: ['Entry 1', 'Entry 2']
  • 作为一个模板,通过视图将数据传递到上下文中(因为我将页面内容传播得更多,所以并不吸引人).
  • 作为模板标记,将HTML构建为一个令人讨厌的大字符串
  • 作为使用像lxml这样的XML库的模板标签,这是一种非常灵活的方法,但是语法冗长,过于复杂,我仍然可以从模板中获取数据!

这些似乎都不像是一个整洁,可重用和松散耦合的方式来处理这个问题(例如,如果我将来更改为Bootstrap 4,我可能需要重新编写这些组件,而我宁愿这样做做一次).拥有这样的组件库也将使未来的页面更容易构建.是否有规范的"正确"方式来做到这一点,甚至是常用的习惯用法?


编辑以显示解决方案实施

使用Wolph下面回答的包含标签,我避免使用这样的笨重结构

{% with [1,2,3] as items %}
    {% my_tag items.split %}
{% endwith %}
Run Code Online (Sandbox Code Playgroud)

如下:

@register.inclusion_tag('components/this_component.html')
def input_with_dropdown(dropdown_title, dropdown_items, default_value, group_id, button_left, *args, **kwargs):

    split_char = kwargs['split_char'] if 'split_char' in kwargs else ' '

    return {
        'dropdown_items': dropdown_items.split(split_char),
        'dropdown_title': dropdown_title,
        'group_id': group_id,
        'default_value' : default_value,
        'button_left': button_left
    }
Run Code Online (Sandbox Code Playgroud)

然后传入这样的变量:

{% input_with_dropdown 'Common baudrates' '9600 48000 115200' 115200 'baudrate-input' 0 %}
Run Code Online (Sandbox Code Playgroud)

Wol*_*lph 10

你看过包含标签了吗?https://docs.djangoproject.com/en/dev/howto/custom-template-tags/#inclusion-tags

我相信这些会完全符合您的要求,您仍然可以指定参数,但您只需传递一个模板即可轻松渲染.

例:

from django import template
register = template.Library()

@register.inclusion_tag('list_results.html')
def list_results(results):
    return {
        'results': results,
        'count': len(results),
    }
Run Code Online (Sandbox Code Playgroud)

list_results.html:

Found {{ count }} results.<br>
<ul>
{% for result in results %}
    <li>{{ result }}</li>
{% endfor %}
</ul>
Run Code Online (Sandbox Code Playgroud)