指南:自定义输出

{% seo_head %} 一次调用即可渲染全部内容。如果需要更细粒度的控制,例如把各个区块分别放到指定位置,或者修改 HTML 结构,有两种机制可用:细粒度模板标签和模板覆盖。


细粒度模板标签

不使用 {% seo_head %},改用各个独立的标签,把每个区块精确地放到你想要的位置:

{% load seo_suite %}
<head>
  <meta charset="utf-8">
  {% seo_title %}
  {% seo_meta %}
  {% seo_canonical %}
  {% seo_hreflang %}
  {% seo_opengraph %}
  {% seo_twitter %}
  {% seo_jsonld %}
  {% seo_extra_head %}
</head>

每个标签读取的都是由上下文处理器或 SeoViewMixin 设置的同一个 seo 上下文变量。在没有 SEO 上下文的页面上调用这些标签也是安全的:它们不会渲染任何内容。

标签 渲染内容
{% seo_title %} <title> 元素
{% seo_meta %} meta description、meta keywords、meta robots
{% seo_canonical %} <link rel="canonical">
{% seo_hreflang %} <link rel="alternate" hreflang> 元素
{% seo_opengraph %} <meta property="og:*"> 元素
{% seo_twitter %} <meta name="twitter:*"> 元素
{% seo_jsonld %} <script type="application/ld+json"> 区块
{% seo_extra_head %} 来自已注册渲染器和 seo_head_rendering 信号的额外片段

在 body 中渲染 h1

h1 字段不会被任何 head 标签渲染(它属于 <body>,而不是 <head>)。通过上下文变量访问它:

<h1>{{ seo.h1|default:seo.title }}</h1>

覆盖 HTML 模板

所有局部模板都存放在 templates/seo_suite/ 下。要覆盖某个模板,把你自己的版本放到 INSTALLED_APPS 中排在 seo_suite 之前的任意应用里,或者放到基于 DIRS 的模板目录中。

各模板的名称及其接收的上下文变量:

模板 上下文变量
seo_suite/head.html seo、jsonld_blocks(序列化字符串列表)、extra_fragments
seo_suite/_title.html seo
seo_suite/_meta.html seo
seo_suite/_canonical.html seo
seo_suite/_hreflang.html seo
seo_suite/_opengraph.html seo
seo_suite/_twitter.html seo
seo_suite/_jsonld.html jsonld_blocks
seo_suite/_extra_head.html extra_fragments

示例:为标题添加自定义包装

在项目中创建 templates/seo_suite/_title.html:

{# myproject/templates/seo_suite/_title.html #}
{% if seo.full_title %}
<title>{{ seo.full_title }}</title>
<meta property="og:title" content="{{ seo.full_title }}">
{% endif %}

seo 对象是一个 FinalizedSeoMetadata 实例,全部可用属性见 SeoMetadata 属性。

示例:为 JSON-LD script 标签添加 nonce

{# myproject/templates/seo_suite/_jsonld.html #}
{% for block in jsonld_blocks %}
<script type="application/ld+json" nonce="{{ request.csp_nonce }}">{{ block }}</script>
{% endfor %}

通过信号添加额外的 head 内容

每次渲染 {% seo_head %} 或 {% seo_extra_head %} 时,都会触发 seo_head_rendering 信号。接收器可以返回一个 HTML 字符串(或字符串列表),它们会被追加到 <head> 中:

# myapp/apps.py
from django.apps import AppConfig


class MyAppConfig(AppConfig):
    name = "myapp"

    def ready(self):
        from seo_suite.signals import seo_head_rendering
        seo_head_rendering.connect(my_head_fragment)


def my_head_fragment(sender, request, metadata, **kwargs):
    if metadata and metadata.canonical_url:
        return f'<link rel="preconnect" href="https://fonts.gstatic.com">'
    return None

接收器可以返回单个字符串、字符串列表或 None。所有非空字符串都会被收集起来,由 {% seo_extra_head %} 渲染。


在模板中访问 seo 对象

无论使用 {% seo_head %} 还是独立标签,只要模板启用了 seo_suite.context.seo 上下文处理器,就可以通过 {{ seo }} 访问完整的 FinalizedSeoMetadata 对象。常用属性:

{{ seo.full_title }}          {# title + title_suffix #}
{{ seo.title }}               {# title only #}
{{ seo.h1 }}                  {# page heading #}
{{ seo.meta_description }}    {# meta description string #}
{{ seo.canonical_url }}       {# absolute canonical URL #}
{{ seo.robots }}              {# robots directive #}
{{ seo.og }}                  {# dict of og:* values #}
{{ seo.twitter }}             {# dict of twitter:* values #}