扩展 django-seo-suite¶
django-seo-suite 提供了稳定的扩展点,第三方包可以借此增加能力(自定义 Provider、额外的 <head> 渲染器、新的 Schema Profile),而无需 fork 代码或做 monkey-patch。
本页面向包作者,简要梳理这些扩展点。如果你的项目只是需要一些自定义行为,通常通过覆写 get_seo_metadata、覆盖模板,或监听 seo_head_rendering 信号就能做到,不必单独写一个包。
扩展发现¶
任何已安装的 Django 应用,只要在顶层带有 seo_extensions.py 模块,该模块就会在启动时被自动导入(通过 AppConfig.ready)。推荐用这种方式注册 Provider、渲染器或 Schema Profile:
# mypackage/seo_extensions.py
from seo_suite.extension import (
Provider,
SeoMetadata,
provider_registry,
PRECEDENCE_PATH,
)
class MyCustomProvider(Provider):
priority = 35 # between PATH (30) and OBJECT (40)
def provide(self, context):
# context has: request, view, object, path, site_id, language
if context.path and context.path.startswith("/promo/"):
return SeoMetadata.partial(robots="noindex")
return None
provider_registry.register(MyCustomProvider())
另一种方式是在包的 pyproject.toml 中,于 seo_suite.extensions 组下发布一个 entry point:
两种机制都是幂等的,在 Django 的 autoreload 下运行也没有问题。
注册表¶
Provider 注册表。 收集每次解析时要查询的 Provider:
from seo_suite.extension import provider_registry, Provider, SeoMetadata
provider_registry.register(my_provider)
provider_registry.unregister("mypackage.providers.MyProvider")
渲染器注册表。 收集在渲染阶段贡献额外 <head> 片段的可调用对象。每个渲染器接收 (request, finalized_metadata),返回字符串或 None:
from seo_suite.extension import renderer_registry
def my_renderer(request, metadata):
if metadata and metadata.og.get("type") == "article":
return '<meta name="article:author" content="...">'
return None
renderer_registry.register("mypackage.my_renderer", my_renderer)
Schema 注册表。 以字符串为键收集 JSON-LD Profile:
from seo_suite.schema.registry import schema_registry, SchemaProfile
class MyProfile(SchemaProfile):
key = "mypkg:CustomType"
def build(self, obj, context):
return {"@context": "https://schema.org", "@type": "CustomType", "name": "..."}
schema_registry.register(MyProfile())
键名请加命名空间(例如 "mypkg:CustomType"),避免与免费版自带的 Profile 冲突。
可替换的类¶
| 设置项 | 控制内容 |
|---|---|
SEO_SUITE["RESOLVER_CLASS"] |
负责收集并合并各 Provider 层的类。继承 seo_suite.resolver.BaseResolver,覆写 collect_layers、build_canonicalizer 或 finalize。 |
SEO_SUITE["JSONLD_SERIALIZER"] |
把 JSON-LD 字典序列化为字符串的可调用对象。 |
信号¶
| 信号 | 触发时机 | 可以做什么 |
|---|---|---|
seo_metadata_resolved |
解析器完成元数据的最终处理之后 | 就地修改 metadata(这是唯一明确支持修改的信号) |
seo_head_rendering |
每次渲染 {% seo_head %} 时 |
返回额外的 <head> HTML 字符串 |
seo_cache_invalidate |
收到清除缓存条目的请求时 | 发送该信号以失效某个特定对象的缓存 |
从 seo_suite.extension 导入:
供 contrib 应用使用的抽象模型¶
如果你的包要添加自己的、基于数据库的 Provider,可以直接复用这些抽象基类:
from seo_suite.contrib.base import AbstractSeoColumns
from seo_suite.contrib.seopath.models import AbstractSeoPath
from seo_suite.contrib.seoobject.models import AbstractSeoObject
SeoColumnsMixin(只包含字段、不带 get_seo_metadata 的 mixin)也可以从 seo_suite.providers.model_mixin 导入。如果你想让某个具体模型拥有标准字段集,又不想继承 SeoModelMixin,就用它。
优先级常量¶
要把 Provider 注册到优先级阶梯的特定位置,请使用这些公开常量:
from seo_suite.extension import (
PRECEDENCE_GLOBAL, # 10
PRECEDENCE_SITE, # 20
PRECEDENCE_PATH, # 30
PRECEDENCE_OBJECT, # 40
PRECEDENCE_VIEW, # 50
)
priority 可以是任意整数。取公开常量之间的值(例如 35),即可插入现有层之间,而基础包无需重新编号。