V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
simadad
V2EX  ›  Python

`django` 如何使 `include` 标签引用的子页面中的 `block` 生效?

  •  
  •   simadad · 2017-09-15 10:15:34 +08:00 · 3024 次点击
    这是一个创建于 2661 天前的主题,其中的信息可能已经有所发展或是发生改变。

    文档结构:

    1. base.html
      • {% include tools.html %}
    2. tools.html
      • {% block ... %}
      • {% block ... %}
    3. page.html
      • {% extends base.html %}

    其中 ——

    • tools.html 中含有一些 {% block %} 标签;
    • tools.html{% include %} 标签引入到了 base.html 中;
    • base.html{% extends %} 标签引入到了 page.html 中;

    想要实现的效果:

    page.html 中引用 tools.html 中的标签,进行改写。

    遇到的问题:

    page.html 能引用 tools.html 中的普通 html 代码,但是无法对 {% block %} 标签进行改写。

    查到的资料:

    Stack Overflow 上这个问题的第二个答案引用了一段 django 文档中的话:

    The include tag should be considered as an implementation of "render this subtemplate and include the HTML", not as "parse this subtemplate and include its contents as if it were part of the parent". This means that there is no shared state between included templates -- each include is a completely independent rendering process.

    大意是说 tool.html 在被 {% include %} 引入进 base.html 时就已经被渲染成 html 文本了?

    那这样的话,有没有比较方便的替代方案?


    补充说明:

    tools.html 中的内容除了 base.html,还有其它地方会用到,所以就被单独写在一个文件里; 但是在其它地方引用的时候会有一点点细微的改动,所以又在其中加入了 {% block %} 标签。 有没有一种比较“优雅”的方式既能保障 tools.html 能被复用,又能比较方便地在复用时进行微调?

    第 1 条附言  ·  2017-09-15 17:07:34 +08:00

    找到一个替代方案

    如何对被 {% include %} 标签引入的文件中的 {% block %} 覆盖重写,仍然没有找到答案。不过,我找到了一个可以实现类似效果的替代方案——

    tools.html 中有改动的部分设定为参数变量,并使用 {% include %} 标签放置于 base.html 中的 {% block %} 标签内,即可在 page.html{% block %} 中的 {% include %} 进行重写,根据不同的页面设置不同的变量,同样能达到微调的作用。

    我在segmentfault上对这个替代方案有更详细的代码说明。

    5 条回复    2018-06-30 16:04:14 +08:00
    ltux
        1
    ltux  
       2017-09-15 11:21:18 +08:00
    templates 的继承关系应该是下面这样的:
    ltux
        2
    ltux  
       2017-09-15 11:23:44 +08:00
    对,django 就是这样。
    base.html 和 "其他地方" 逻辑上是没有关系的,所以你是不应该这么用的。
    你应该从 tools.html 往下继承。
    a87150
        3
    a87150  
       2017-09-15 11:49:29 +08:00
    你这个逻辑有毛病,base 就是基础,应该是 tools 继承 base 再往下继承
    simadad
        4
    simadad  
    OP
       2017-09-15 14:30:09 +08:00
    @ltux [#2]( https://www.v2ex.com/t/390871#r_4754099)

    @a87150 [#3]( https://www.v2ex.com/t/390871#r_4754260)

    大意了,我为了突出问题,没有提到其他自认为不相干的文件,造成了歧义。
    1. 问题中提到的 `base.html` 是“**三级继承**” 中的第二级,已经继承过更底层的基础页面;
    2. `page.html` 是继承自 `base.html` 的第三级页面,已经是直接面向用户展示的模版了;
    3. `tools.html` 是一个会被多次复用的小元件,但是需要根据不同页面的而小有调整;
    4. 类似 `tools.html` 这样的小元件有多个,而 `page.html` 显然无法同时继承多个模版。

    -----
    目前已经尝试过使用自定义标签直接将 `tools.html` 作为文本,引入到 `base.html`,但是 `HTML` 标签在引入时会被转义,导致最终的展示结果中全是源代码,也许需要在引入时“取消自动转义”?这个方法是否可行还在查资料;

    另外,好像注册“包含标签” `Inclusion tags` 可以为 `tools.html` 设定参数,根据不同的参数在不同页面上显示不同的效果,但是使用这个方法需又把模板、模型、视图混在一起,和 `django` **MTV ** 的架构理念不太相符。
    MingoWong
        5
    MingoWong  
       2018-06-30 16:04:14 +08:00
    题主这个问题解决了没?我现在也遇到这种问题,我的场景是这样的,写一个想复用的 datatable 模板,在某个页面里面重复 include 进去用(这个页面展示的表格都是差不多的,但是也有一点小差异,所以想少写代码,用复用模板),同时想要更改 datatable 内部的某些 block,找了好久没找到怎么弄.
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   925 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 22ms · UTC 21:46 · PVG 05:46 · LAX 13:46 · JFK 16:46
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.