指南:详情视图

在 DetailView 上混入 SeoViewMixin,默认即可得到从对象派生的元数据, 同时也能在视图层面方便地覆盖特定字段。


默认行为

把 SeoViewMixin 混入 DetailView 后,解析器会同时拿到视图和 self.object。 对象的 get_seo_metadata() 以优先级 40 运行;视图上的任何 seo_* 属性或 get_seo_metadata() 覆盖则以优先级 50 运行。

from django.views.generic import DetailView
from seo_suite.mixins import SeoViewMixin

from .models import Article


class ArticleDetail(SeoViewMixin, DetailView):
    model = Article
    slug_field = "slug"
    slug_url_kwarg = "slug"

这就够了。文章的 title、description、canonical URL,以及 SeoModelMixin 解析出的其他字段都会自动使用。


覆盖单个字段

设置 seo_* 类属性即可覆盖特定字段,无需改动模型:

class ArticleDetail(SeoViewMixin, DetailView):
    model = Article
    slug_field = "slug"
    seo_robots = "noindex"  # drafts, paywalled content, etc.

可用的类属性如下(默认值均为 None,表示“不表态”):

属性 元数据字段
seo_title title
seo_title_suffix title_suffix
seo_h1 h1
seo_description meta_description
seo_keywords meta_keywords
seo_robots robots
seo_canonical canonical_url
seo_og_image og_image

用 get_seo_metadata 动态覆盖

如果取值取决于请求状态,重写 get_seo_metadata:

class ArticleDetail(SeoViewMixin, DetailView):
    model = Article

    def get_seo_metadata(self, context=None):
        from seo_suite.metadata import SeoMetadata

        # Only suppress indexing for unpublished content.
        if not self.object.published:
            return SeoMetadata.partial(robots="noindex,nofollow")
        # Return UNSET for all fields to defer entirely to the object layer.
        return SeoMetadata.partial()

SeoMetadata.partial(**kwargs) 构造的元数据对象只设置指定的字段,其余字段 保持 UNSET,由优先级更低的层提供。


视图标题覆盖对象,canonical 保留

一种常见做法:视图设置带品牌的标题,同时保留对象的 canonical URL:

class ArticleDetail(SeoViewMixin, DetailView):
    model = Article
    seo_title = "Read Our Latest"  # overrides article.title at priority 50
    # canonical_url is not set here, so article.get_absolute_url() survives

视图上的 seo_canonical 为 None(不表态),因此对象由 get_absolute_url() 得到的 canonical_url 会原样使用。


在视图层面添加 JSON-LD

用 seo_schema_profiles 在视图层面启用 schema 配置。当配置取决于请求上下文时 (例如只在首页添加 WebSite 配置),这很有用:

class ArticleDetail(SeoViewMixin, DetailView):
    model = Article
    seo_schema_profiles = ["WebPage"]

模型和视图都声明了配置时,两组 JSON-LD 块都会输出(累加规则)。 参见 JSON-LD 结构化数据。


不配合 DetailView 使用 SeoViewMixin

SeoViewMixin 可以配合任何带有 get_context_data 的基于类的视图使用。 object 属性是可选的;如果存在,会传给解析器。

from django.views.generic.base import View
from django.shortcuts import get_object_or_404
from seo_suite.mixins import SeoViewMixin
from seo_suite.context import attach_seo


class MyCustomView(SeoViewMixin, View):
    seo_title = "Custom Page"

    def get(self, request, pk):
        self.object = get_object_or_404(Article, pk=pk)
        seo = attach_seo(request, view=self, obj=self.object)
        # ... render response ...