ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

Wagtail 推荐搜索结果(search_promotions)实战指南:从查询统计、编辑精选到搜索结果页展示

Wagtail 推荐搜索结果(search_promotions)实战指南:从查询统计、编辑精选到搜索结果页展示 Wagtail 推荐搜索结果search_promotions实战指南从查询统计、编辑精选到搜索结果页展示【免费下载链接】wagtailA Django content management system focused on flexibility and user experience项目地址: https://gitcode.com/GitHub_Trending/wa/wagtail本文以 Wagtail 官方参考文档searchpromotions模块说明为主体系统讲解wagtail.contrib.search_promotions这一可选组件的完整用法如何安装启用、如何在后台为热门搜索词配置“推荐搜索结果Promoted search results”、如何在站点搜索结果页模板中通过模板标签取出并渲染精选内容以及如何记录搜索词命中日志并通过管理命令清理过期数据。读完本文你将能够独立完成该模块的安装、后台配置、前端展示与日志维护四个环节并理解其底层Query/QueryDailyHits/SearchPromotion三个模型的协作机制。1. 模块定位让搜索结果页包含“人工精选”内容searchpromotions模块提供了一套模型与后台用户界面用于管理“推荐搜索结果”并将其展示在搜索结果页上。其核心价值在于允许编辑者显式地把特定内容关联到某个搜索词这样搜索结果页除了搜索引擎返回的自然结果外还可以呈现经过人工策划的精选内容页面或外部链接。从仓库结构看见 wagtail/contrib/search_promotions 目录该模块由以下几部分组成模型层models.py 定义了Query搜索词记录、QueryDailyHits每日命中计数、SearchPromotion推荐条目三个模型后台视图views/settings.py增删改查与 views/reports.py搜索词报告表单forms.py模板标签templatetags/wagtailsearchpromotions_tags.py管理命令management/commands/searchpromotions_garbage_collect.py。2. 安装searchpromotions模块默认不启用。要安装它需要将wagtail.contrib.search_promotions加入项目 Django settings 文件中的INSTALLED_APPSINSTALLED_APPS [ ... wagtail.contrib.search_promotions, ]该应用包含数据库迁移见 migrations 目录从0001_initial.py到0008_query_verbose_name.py共 8 个迁移其中00030006还完成了从旧版wagtailsearch内嵌Query模型到新模型的切换因此安装后务必运行migrate命令。3. 后台管理为热门搜索词配置推荐内容安装完成后后台Settings设置菜单中会出现一个新的菜单项“Promoted search results”。这正是通过 wagtail_hooks.py 中register_settings_menu_item钩子注册的图标为pick、排序权重 900hooks.register(register_settings_menu_item) def register_search_picks_menu_item(): return SearchPicksMenuItem( _(Promoted search results), reverse(wagtailsearchpromotions:index), namepromoted-search-results, icon_namepick, order900, )该菜单项的显示受权限控制只有拥有wagtailsearchpromotions应用下add_searchpromotion、change_searchpromotion或delete_searchpromotion任一权限的用户才能看到见 wagtail_hooks.py 中的SearchPicksMenuItem.is_shown。同时模块通过register_permission_policy(SearchPromotion)注册了权限策略并通过register_permissions钩子把上述三个权限暴露给权限管理界面。3.1 管理界面能做什么后台管理界面围绕Query模型组织路由见 admin_urls.py列表index、新建add、编辑edit、删除delete。列表页IndexView见 views/settings.py展示三列Search term(s)搜索词Promoted results该词下已配置的推荐条目Views累计命中次数源码中通过annotate(viewsCoalesce(Sum(daily_hits__hits), 0))聚合得出并用子查询而非 JOIN 过滤没有推荐条目的Query以避免 JOIN 产生重复行导致求和出错——这一点在get_base_queryset的注释中有明确说明。新建/编辑页由一个主表单QueryForm加一个内联表单集SearchPromotionsFormSet组成。两者的关键校验规则值得注意QueryForm的帮助文本明确提示需要输入完整匹配的搜索串推荐结果仅在精确匹配时展示不支持通配符见 forms.py。这与模板标签内部的取数逻辑一致下文会看到它调用Query.get()做精确get_or_create。SearchPromotionForm要求每条推荐必须且只能二选一推荐一个站内页面或填写一个外部链接若填写外部链接 URL则external_link_text链接显示文字也是必填项。表单使用AdminPageChooser作为页面选择控件见 forms.py。表单集要求至少保留一条非删除的推荐否则报错 “Please specify at least one recommendation for this search term.”见 forms.py。所有新建、修改、删除操作都会写入 Wagtail 审计日志log(search_pick, wagtail.create)/wagtail.edit/wagtail.delete见 views/settings.py。3.2 SearchPromotion 模型的字段结构从 models.py 可以看到SearchPromotion的完整字段定义class SearchPromotion(models.Model): query models.ForeignKey( Query, db_indexTrue, related_nameeditors_picks, on_deletemodels.CASCADE ) page models.ForeignKey(...Page..., nullTrue, blankTrue) external_link_url models.URLField(...) external_link_text models.CharField(max_length200, blankTrue, nullTrue) description models.TextField(..., blankTrue) sort_order models.IntegerField(nullTrue, blankTrue, editableFalse)要点query外键的related_nameeditors_picks表明该模块内部仍沿用 Wagtail 早期版本中“Editors picks”的命名——Query.get(...).editors_picks.all()即某个搜索词下全部推荐条目的取法page与外部链接字段external_link_url/external_link_text同时存在配合表单的互斥校验实现“站内页面或外部链接二选一”description对页面和外部链接都适用用于在搜索结果页展示描述文字sort_order由后台表单集按顺序自动写入save_searchpicks中form.instance.sort_order i模型Meta.ordering (sort_order,)保证展示顺序稳定。4. 在搜索结果页中展示推荐内容官方文档给出的取数方式是{% get_search_promotions %}模板标签来自wagtailsearchpromotions_tags标签库。完整的页面模板示例如下继承自官方文档{% load wagtailcore_tags wagtailsearchpromotions_tags %} ... {% get_search_promotions search_query as search_promotions %} ul {% for search_promotion in search_promotions %} {% if search_promotion.page %} li a href{% pageurl search_promotion.page %} h2{{ search_promotion.page.title }}/h2 p{{ search_promotion.description }}/p /a /li {% else %} li a href{{ search_promotion.external_link_url }} h2{{ search_promotion.external_link_text }}/h2 p{{ search_promotion.description }}/p /a /li {% endif %} {% endfor %} /ul4.1 标签的底层实现该模板标签的实现只有寥寥数行见 wagtailsearchpromotions_tags.pyregister.simple_tag def get_search_promotions(search_query): if search_query: return Query.get(search_query).editors_picks.all() else: return SearchPromotion.objects.none()从源码结构可以看出两点精确匹配Query.get(search_query)内部是get_or_create(query_stringnormalise_query_string(query_string))即按归一化后的完整搜索串做精确查找查不到则返回空列表——这与后台表单“不支持通配符”的说明完全对应零查询开销的降级未传入查询串时直接返回SearchPromotion.objects.none()不会触发数据库查询。另外模型层还提供了两个聚合便捷属性供模板或视图直接使用SearchPromotion.title在存在page时返回页面标题、否则返回external_link_textSearchPromotion.link则分别返回页面对象或外部链接 URL见 models.py模板中也可以据此简化分支判断。5. 搜索词日志Query 与 QueryDailyHitssearchpromotions模块除了管理精选内容还记录每一条搜索词及其每日命中次数对应两个模型.. class:: wagtail.contrib.search_promotions.models.Query .. method:: get(query_string) :classmethod: 检索一条已存储的搜索词若不存在则自动创建。 .. method:: add_hit(dateNone) 为该搜索词记录一次当日命中为新日期创建记录或对已有记录累加。 默认使用当前日期也可通过可选的 date 参数指定。5.1 模型实现细节models.py 中Query的关键实现class Query(models.Model): query_string models.CharField(max_lengthMAX_QUERY_STRING_LENGTH, uniqueTrue) def save(self, *args, **kwargs): # 保存前归一化搜索串 self.query_string normalise_query_string(self.query_string) super().save(*args, **kwargs) def add_hit(self, dateNone): if date is None: date timezone.now().date() daily_hits, created QueryDailyHits.objects.get_or_create( queryself, datedate ) daily_hits.hits models.F(hits) 1 daily_hits.save() property def hits(self): hits self.daily_hits.aggregate(models.Sum(hits))[hits__sum] return hits if hits else 0 classmethod def get(cls, query_string): return cls.objects.get_or_create( query_stringnormalise_query_string(query_string) )[0]可以看到query_string是唯一字段且每次保存/创建前都会经过normalise_query_string归一化该函数与MAX_QUERY_STRING_LENGTH均由wagtail.search.utils提供从其内容看是对底层modelsearch包的再导出见 utils.py因此 “ Django ” 与 “django” 之类的差异会被归并到同一记录add_hit()用get_or_createF表达式实现并发安全的按日计数QueryDailyHits通过unique_together ((query, date),)约束保证同一搜索词同一天只有一条记录见 models.pyQuery.hits属性对daily_hits求和得到该搜索词的累计命中数正是后台列表 “Views” 列的数据来源此外还有Query.garbage_collect()删除既无命中记录、又无推荐条目的Query与Query.get_most_popular(date_sinceNone)按命中总量排序的热门词查询供后台词选择器和搜索词报告使用。5.2 在搜索视图中记录命中官方文档给出了一段可直接使用的 Django 视图示例每次搜索都通过Query.get()取出或创建对应记录并调用add_hit()from django.template.response import TemplateResponse from wagtail.models import Page from wagtail.contrib.search_promotions.models import Query def search(request): search_query request.GET.get(query, None) if search_query: search_results Page.objects.live().search(search_query) query Query.get(search_query) # 记录一次命中 query.add_hit() else: search_results Page.objects.none() return TemplateResponse( request, search/search.html, { search_query: search_query, search_results: search_results, }, )这段视图与第 4 节的模板配合后形成完整闭环视图侧写入命中日志模板侧按同一search_query精确取出推荐条目并渲染。命中数据随后台积累还会反哺到“Promoted search results”界面的新建流程中——其词选择器chooser视图见 views/settings.py默认按Query.get_most_popular()展示热门词并支持模糊检索方便编辑者优先为高频搜索词配置推荐内容。5.3 附赠搜索词报告仅管理员除设置菜单项外wagtail_hooks.py 还通过register_reports_menu_item钩子注册了一个Reports 菜单下的 “Search terms”报告页AdminOnlyMenuItem即仅超级管理员可见见 views/reports.py 中的dispatch检查。该报告基于Query.get_most_popular()按-_hits默认降序展示各搜索词与累计命中数支持按搜索词全文检索、按日期范围daily_hits__date的起止区间过滤并可将结果导出为 CSV/TSV/XLSX。这是运维与内容团队评估“哪些搜索词值得配置推荐结果”的直接依据。6. 清理过期日志searchpromotions_garbage_collect在高流量站点上搜索词与每日命中日志会不断膨胀。官方文档提供了管理命令用于清理./manage.py searchpromotions_garbage_collect该命令会清掉所有超过一周或WAGTAILSEARCH_HITS_MAX_AGE设置指定的天数的搜索词日志。其实现见 searchpromotions_garbage_collect.py分两步执行class Command(BaseCommand): def handle(self, **options): # 清理每日命中记录 self.stdout.write(Cleaning daily hits records…) models.QueryDailyHits.garbage_collect() self.stdout.write(Done) # 清理搜索词记录 self.stdout.write(Cleaning query records…) models.Query.garbage_collect() self.stdout.write(Done)对应两个模型类方法的行为边界QueryDailyHits.garbage_collect(daysNone)删除date早于今天 - N 天的命中记录其中 N 默认取getattr(settings, WAGTAILSEARCH_HITS_MAX_AGE, 7)即默认保留 7 天见 models.pyQuery.garbage_collect()删除既没有daily_hits、也没有editors_picks的Query记录。这意味着已配置推荐内容的搜索词即使命中日志过期也不会被删除其配置得以长期保留。官方设置参考文档对WAGTAILSEARCH_HITS_MAX_AGE的说明见 docs/reference/settings.mdWAGTAILSEARCH_HITS_MAX_AGE 14“Set the number of days (default 7) that search query logs are kept for; these are used to identify popular search terms for promoted search results. Queries older than this will be removed by thesearchpromotions_garbage_collectcommand.” 即该设置控制搜索词日志的保留天数默认 7 天这些日志用于识别热门搜索词以支撑推荐搜索结果功能。需要调整保留期时在 settings 中显式设置该值即可无需改动任何代码。建议将searchpromotions_garbage_collect纳入定期任务如 cron 每周一次执行与命中日志的滚动保留策略保持一致。7. 小结关键文件索引内容仓库路径官方模块文档docs/reference/contrib/searchpromotions.md三个核心模型Query / QueryDailyHits / SearchPromotionwagtail/contrib/search_promotions/models.py模板标签get_search_promotionswagtail/contrib/search_promotions/templatetags/wagtailsearchpromotions_tags.py后台菜单、权限与 URL 注册wagtail/contrib/search_promotions/wagtail_hooks.py增删改查视图与词选择器wagtail/contrib/search_promotions/views/settings.py搜索词报告视图wagtail/contrib/search_promotions/views/reports.py表单与校验规则wagtail/contrib/search_promotions/forms.py路由wagtail/contrib/search_promotions/admin_urls.py垃圾回收命令wagtail/contrib/search_promotions/management/commands/searchpromotions_garbage_collect.py迁移文件wagtail/contrib/search_promotions/migrationsWAGTAILSEARCH_HITS_MAX_AGE设置说明docs/reference/settings.md按“安装 → 后台配置 → 视图记录命中 → 模板展示 → 定期清理”这条链路落地即可让 Wagtail 站点的搜索结果页在保留搜索引擎自然结果的同时稳定呈现编辑团队策划的精选内容。【免费下载链接】wagtailA Django content management system focused on flexibility and user experience项目地址: https://gitcode.com/GitHub_Trending/wa/wagtail创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表