Django 2.0:跨应用向嵌套模板传递视图数据
你遇到的核心问题是:contact视图没有对应URL,没法通过常规的视图渲染流程把上下文传给被home.html包含的contact_form.html。下面给你几个实用的解决方案,按推荐程度排序:
方案1:在home视图中直接生成contact相关上下文
这是最简单直接的方式——既然contact_form是嵌入在home页面里的,那就把原本放在contact视图里的上下文生成逻辑,整合到home视图中,再把需要的变量传给home模板,让contact_form.html直接复用这些变量。
假设你的contact视图原本是这样的:
# contact/views.py from django.shortcuts import render from .forms import ContactForm def contact(request): form = ContactForm() context = { 'form': form, 'page_title': '联系我们' } return render(request, 'contact/contact_form.html', context)
现在把逻辑迁移到home视图里:
# home/views.py from django.shortcuts import render from contact.forms import ContactForm # 导入contact的表单 def home(request): # 生成contact需要的上下文 contact_context = { 'form': ContactForm(), 'page_title': '联系我们' } # 合并home自身的上下文和contact的上下文 context = { 'home_title': '首页', **contact_context # 展开contact的变量,让模板可以直接访问 } return render(request, 'home/home.html', context)
然后在home.html里正常包含contact_form.html即可:
<!-- home/home.html --> <h1>{{ home_title }}</h1> <!-- 嵌入contact表单 --> {% include 'contact/contact_form.html' %}
contact_form.html里直接使用变量:
<!-- contact/contact_form.html --> <h2>{{ page_title }}</h2> <form method="post"> {% csrf_token %} {{ form.as_p }} <button type="submit">提交</button> </form>
方案2:使用Django自定义包含标签(Inclusion Tag)
如果contact的上下文逻辑比较复杂,不想和home视图耦合,那可以用Django的包含标签——这是专门用来在模板中复用带上下文的模板片段的工具。
步骤如下:
- 在contact app里创建
templatetags目录,内部新建contact_tags.py和空的__init__.py,目录结构如下:
contact/ ├── templatetags/ │ ├── __init__.py │ └── contact_tags.py ├── forms.py ├── views.py ...
- 在
contact_tags.py里定义包含标签:
# contact/templatetags/contact_tags.py from django import template from contact.forms import ContactForm register = template.Library() @register.inclusion_tag('contact/contact_form.html') def render_contact_form(): # 在这里生成需要传递给contact_form的上下文 form = ContactForm() return { 'form': form, 'page_title': '联系我们' }
- 在home.html里加载标签并调用:
<!-- home/home.html --> {% load contact_tags %} <h1>首页</h1> <!-- 调用自定义标签,自动渲染contact_form并传入上下文 --> {% render_contact_form %}
这个方案把contact的逻辑完全封装在自身app里,不需要修改home视图,代码耦合度很低。
方案3:使用全局上下文处理器(Context Processor)
如果这个contact的上下文需要在多个页面复用,而不只是home页面,那可以用上下文处理器让它全局可用(如果只是home页面用,前面两个方案更轻便)。
创建contact的上下文处理器:
# contact/context_processors.py from .forms import ContactForm def contact_context(request): return { 'contact_form': ContactForm(), 'contact_title': '联系我们' }
然后在项目的settings.py里注册这个处理器:
# settings.py TEMPLATES = [ { ... 'OPTIONS': { 'context_processors': [ ... 'contact.context_processors.contact_context', ], }, }, ]
之后在任何模板(包括contact_form.html)里,都可以直接使用{{ contact_form }}和{{ contact_title }},home.html里直接包含contact_form.html即可。
内容的提问来源于stack exchange,提问作者ralfillo

