指南:第三方模型(seoobject)¶
当需要添加 SEO 的模型来自第三方包(例如 django-oscar 的 Product 模型、某个 CMS 包的 Post 模型,或者任何无法添加 mixin 的模型)时,可以使用 seoobject contrib 应用。它借助 Django 的通用关系(generic relations),把 SEO 数据存放在一张独立的关联表中,供编辑人员管理。
何时使用 seoobject¶
以下情况适合使用 seoobject:
- 模型位于第三方包中,你无法修改。
- 你希望在不修改模型的前提下,让编辑人员在 Admin 中逐对象编辑 SEO。
- 你希望采用同样的 Admin 可编辑方式,但自己的模型已经用了
SeoModelFieldsMixin。这种情况下,请直接使用内联字段。
对于你自己拥有的模型,优先选择 SeoModelMixin(自动生成,不增加任何字段)或 SeoModelFieldsMixin(供编辑人员编辑的字段)。seoobject 会在每次解析允许列表中的对象时额外执行一次 ContentTypes 查询。
安装¶
把两个应用都加入 INSTALLED_APPS:
INSTALLED_APPS = [
"django.contrib.contenttypes", # usually already present
"seo_suite",
"seo_suite.contrib.seoobject",
]
执行迁移:
把模型加入允许列表¶
seoobject 提供者只处理你明确列入允许列表的模型。这样可以避免在每次对象解析时都执行 ContentTypes 查询;未列入的模型会直接跳过,不访问数据库。
# settings.py
SEO_SUITE = {
"OBJECT_MODELS": [
"catalogue.product", # app_label.model_name, lowercase
"blog.post",
],
}
格式为 "app_label.model_name"(不区分大小写)。
在 Django Admin 中管理 SEO¶
应用安装完成并把模型加入允许列表后,编辑人员就可以在 Django Admin 的 SEO Suite — Object rules → SEO object rules 中创建和编辑 SeoObject 记录。
每条记录包含:
| 字段 | 用途 |
|---|---|
| Content type | 这条记录适用于哪个模型 |
| Object ID | 具体对象的主键 |
| Site ID | 可选:仅限某个站点 |
| Language | 可选:仅限某种语言 |
| Title | 覆盖页面标题 |
| Description | 覆盖 meta description |
| Keywords | 覆盖 meta keywords |
| Robots | 覆盖 robots 指令 |
| Canonical | 覆盖 canonical URL |
| OG image | 覆盖社交分享图片 |
| Extra JSON-LD | 附加的 JSON-LD 对象(累加,不替换) |
字段留空即沿用更低优先级的默认值。
解析过程¶
解析器处理允许列表中某个对象的请求时,会在 SeoObject 表中查询与该对象的 content type 和主键匹配的记录。匹配的精确度规则如下:
site_id和language都匹配的记录优先。- 其次是
site_id匹配但未指定语言的记录。 site_id和language都为空的记录适用于所有站点和所有语言。
最终选中的记录作为对象层(优先级 40)合并。如果对象本身也定义了 get_seo_metadata()(即使用了 SeoModelMixin),其输出也会合并到同一层。由于 SeoObject 记录在 mixin 调用之后才应用,因此它的值优先。
Note
如果对象不在 OBJECT_MODELS 中,就不会查询 SeoObject。模型自身的 get_seo_metadata()(如果有)仍会照常调用。
示例:django-oscar 的 Product¶
# yourapp/views.py
from django.views.generic import DetailView
from seo_suite.mixins import SeoViewMixin
from oscar.apps.catalogue.models import Product
class ProductDetailView(SeoViewMixin, DetailView):
model = Product
template_name = "catalogue/product_detail.html"
视图把 Product 实例作为上下文对象传入。解析器检查允许列表,找到 catalogue.product,查询 SeoObject,并合并匹配的记录。如果没有记录,则回退到全局默认值。