尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Wagtail 2.11.1 版本说明解读:站点根路径缓存失效、循环导入规避与多语言 URL 解析容错

Wagtail 2.11.1 版本说明解读:站点根路径缓存失效、循环导入规避与多语言 URL 解析容错 Wagtail 2.11.1 版本说明解读站点根路径缓存失效、循环导入规避与多语言 URL 解析容错【免费下载链接】wagtailA Django content management system focused on flexibility and user experience项目地址: https://gitcode.com/GitHub_Trending/wa/wagtail本文基于 Wagtail 2.11.1 官方发布说明docs/releases/2.11.1.rst发布日期 2020 年 11 月 6 日逐一解读该维护版本修复的三个 Bug跨版本缓存失效问题、wagtail.admin.auth与自定义 User 模型之间的循环导入问题以及当激活语言不在WAGTAIL_CONTENT_LANGUAGES配置内时页面 URL 解析报错的问题。读完本文你将理解每个修复背后的根因并掌握通过当前仓库源码wagtail/models/sites.py、wagtail/admin/auth.py、wagtail/models/pages.py验证这些机制的方法。版本定位2.11.1 是什么Wagtail 2.11 是一个长期支持LTS版本见 docs/releases/2.11.rst。LTS 版本会在下一个 LTS 发布前通常约 12 个月持续接收针对安全与数据丢失类问题的维护更新。2.11.1 就是发布四天后的第一个维护更新全部内容集中于 Bug 修复没有新功能。因此本版本的价值在于它修补了 2.11 新引入的多语言i18n模型和站点根路径缓存机制中暴露出的三个具体缺陷。发布说明中列出的三项修复如下Ensure that cachedwagtail_site_root_pathsstructures from older Wagtail versions are invalidated (Sævar Öfjörð Magnússon)Avoid circular import between wagtail.admin.auth and custom user models (Matt Westcott)Prevent error on resolving page URLs when a locale outside ofWAGTAIL_CONTENT_LANGUAGESis active (Matt Westcott)下面结合当前仓库源码逐项展开。修复一确保旧版本缓存的 wagtail_site_root_paths 结构被正确失效背景wagtail_site_root_paths 缓存的作用Wagtail 中页面 URL 的反向解析依赖一份站点根路径表它列出每个站点的root_path如/home/、root_url如https://example.com等用于把页面的内部url_path转换成真实 URL。为避免每次解析 URL 都查库这份表被缓存在 Django cache 中缓存键为wagtail_site_root_paths。在当前仓库中该机制位于 wagtail/models/sites.pySiteRootPath namedtuple(SiteRootPath, site_id root_path root_url language_code) SITE_ROOT_PATHS_CACHE_KEY wagtail_site_root_paths # Increase the cache version whenever the structure SiteRootPath tuple changes SITE_ROOT_PATHS_CACHE_VERSION 2Site.get_site_root_paths()wagtail/models/sites.py读取缓存时始终携带versionSITE_ROOT_PATHS_CACHE_VERSION参数。Django 的cache.get/set/delete支持版本号版本号变化后旧版本写入的数据对新版本不可见等同于被自动失效。这次修复解决了什么问题2.11 引入了多语言模型SiteRootPath从早期的三元组site_id, root_path, root_url扩展为带language_code的四元组。如果生产环境使用长生命周期的缓存后端如 Redis、Memcached升级后缓存中可能仍残留旧结构三元组的数据。直接读取旧数据会导致解包错误ValueError: not enough values to unpack一类问题。修复方式正是引入缓存版本号并将常量提升到2result cache.get( SITE_ROOT_PATHS_CACHE_KEY, versionSITE_ROOT_PATHS_CACHE_VERSION )由于旧版本 Wagtail 读写该缓存时不带version参数等效 version 为默认值 1升级到 2.11.1 后以 version2 读取旧数据天然不可见无需手工清理缓存后端。源码注释也明确提示了这一约定Increase the cache version whenever the structure SiteRootPath tuple changes每次SiteRootPath结构变化时递增缓存版本。配套的缓存清理机制除了跨版本失效站点根路径缓存还需在站点或站点根页面变化时主动清理。当前仓库中有多处清理入口Site.clear_site_root_paths_cache()wagtail/models/sites.py执行cache.delete(...)同样携带版本号wagtail/signal_handlers.py 中post_save_site_signal_handler/post_delete_site_handler在Site记录保存/删除时清缓存wagtail/models/pages.py 中Page.save()会检查页面是否为某个站点的根页面is_site_root()是则清缓存——注释特别指出现有站点根页面的新翻译也被视为站点根因此即使是新建记录也要检查。对应回归测试在 wagtail/tests/tests.pytest_cache_clears_when_site_root_moves验证了站点根页面被移动后旧缓存不会让所有子页面 URL 变成 None的问题其 docstring 追溯到历史修复 d6cce69 及 issue #7test_cache_clears_when_site_root_slug_changeswagtail/tests/tests.py覆盖了根页面 slug 变更的场景。这些测试可作为升级后自验证该修复是否生效的依据。对运维的提示升级 2.11.1 后无需手工 flush 缓存但如果你自定义了基于该缓存键的读取逻辑请沿用 version 常量而不是硬编码键名。修复二避免 wagtail.admin.auth 与自定义 User 模型之间的循环导入问题根因Django 项目自定义AUTH_USER_MODEL时django.contrib.auth的模型注册顺序可能与业务应用相互纠缠。若wagtail.admin.auth在模块顶部直接from django.contrib.auth.views import redirect_to_login那么在加载auth模块进而加载自定义 User 模型所在应用的过程中触发反向导入就可能形成循环导入导致ImportError或部分初始化模型。源码中的规避手法当前仓库 wagtail/admin/auth.py 的reject_request函数正是修复后的形态def reject_request(request): if request.headers.get(x-requested-with) XMLHttpRequest: raise PermissionDenied # import redirect_to_login here to avoid circular imports on model files that import # wagtail.admin.auth, specifically where custom user models are involved from django.contrib.auth.views import redirect_to_login as auth_redirect_to_login login_url getattr( settings, WAGTAILADMIN_LOGIN_URL, reverse(wagtailadmin_login) ) return auth_redirect_to_login(request.get_full_path(), login_urllogin_url)关键点redirect_to_login被从模块顶层 import 下沉到函数内部延迟导入导入注释明确写着目的是avoid circular imports ... specifically where custom user models are involved登录跳转地址仍支持WAGTAILADMIN_LOGIN_URL设置项覆盖默认指向wagtailadmin_loginAJAX 请求x-requested-with: XMLHttpRequest则直接抛出PermissionDenied返回 403而非重定向到登录页。这个延迟导入模式是 Django 生态处理AUTH_USER_MODEL自定义场景的常见最佳实践任何在模块加载期就触碰auth模块的第三方导入都可能与尚未完成注册的应用冲突。项目里使用自定义 User 模型的读者在升级后可重点回归验证管理端登录、权限拒绝跳转这两条路径。修复三激活语言不在 WAGTAIL_CONTENT_LANGUAGES 时页面 URL 解析不再报错背景多语言 URL 解析流程启用WAGTAIL_I18N_ENABLED后Page.get_url_parts()在把url_path反向解析为wagtail_serve路由前需要选择一个合适的语言来执行reverse()。当前仓库实现位于 wagtail/models/pages.pyuse_wagtail_i18n getattr(settings, WAGTAIL_I18N_ENABLED, False) if use_wagtail_i18n: # If the active language code is a variant of the pages language, then # use that instead # This is used when LANGUAGES contain more languages than WAGTAIL_CONTENT_LANGUAGES try: if ( get_supported_content_language_variant(translation.get_language()) language_code ): language_code translation.get_language() except LookupError: # active language code is not a recognised content language, so leave # pages language code unchanged pass这次修复解决了什么问题get_supported_content_language_variant由 wagtail/models/pages.py 导入在无法把当前激活语言映射到任何受支持的内容语言时会抛出LookupError。典型触发场景项目LANGUAGES里声明了比WAGTAIL_CONTENT_LANGUAGES更多的界面语言源码注释也点明了这一用途This is used when LANGUAGES contain more languages than WAGTAIL_CONTENT_LANGUAGES或管理员在后台/前台把激活语言切到了一个未纳入内容语言的区域如fr-FR之类带地区后缀的 locale而内容语言只配置了fr且映射失败时或WAGTAIL_CONTENT_LANGUAGES配置为空/异常。2.11.1 之前未捕获的LookupError会让page.url、page.full_url、relative_url等属性访问直接抛 5002.11.1 修复后try/except LookupError捕获该异常并保持页面自身语言编码不变URL 解析得以继续完成。注意这个静默降级是有意为之——页面仍以它自己的language_code解析不会误路由到别的语言版本。配置侧建议如果你的站点启用了 i18n应确保WAGTAIL_CONTENT_LANGUAGES至少覆盖后台会激活的所有界面语言例如[(en, English), (fr, French)]这类写法在仓库测试中多处出现如 wagtail/admin/tests/test_userbar.py。测试用例wagtail/admin/tests/test_userbar.py、wagtail/admin/tests/test_templatetags.py中均以WAGTAIL_CONTENT_LANGUAGES设置项验证了多语言行为可参考其写法为自有项目编写回归测试。升级与验证建议2.11.1 本身不含迁移从 2.11 升级到 2.11.1 只需更新依赖版本。但请注意 docs/releases/2.11.rst 中Upgrade considerations提到的前置条件尤其是 2.11 引入Page.locale字段后任何在迁移中程序化创建页面的项目都需要为首页迁移添加run_before [(wagtailcore, 0053_locale_model)]否则干净数据库上migrate会报IntegrityError: NOT NULL constraint failed: wagtailcore_page.locale_id。针对本文三个修复升级后可做如下验证站点根路径缓存在管理端移动/重命名站点根页面后立即访问该站子页面 URL确认不再出现 URL 为None的异常对应 wagtail/tests/tests.py 的测试场景若使用共享 Redis观察升级后wagtail_site_root_paths首次读取重建缓存即可。循环导入使用自定义AUTH_USER_MODEL的项目重启应用进程确认管理端登录页、403 跳转正常。多语言 URL 解析在启用WAGTAIL_I18N_ENABLED的项目中把一个不在WAGTAIL_CONTENT_LANGUAGES内的语言设为激活语言访问任意启用 i18n 的模板/管理页面确认不再抛出LookupError。小结Wagtail 2.11.1 是一个小而关键的维护版本它通过缓存版本号SITE_ROOT_PATHS_CACHE_VERSION 2解决了wagtail_site_root_paths缓存跨版本失效问题通过把redirect_to_login改为函数内延迟导入消除了自定义 User 模型场景的循环导入隐患并通过捕获LookupError让页面 URL 解析在激活语言超出内容语言配置时优雅降级而非报错。三处修复都可以在 wagtail/models/sites.py、wagtail/admin/auth.py、wagtail/models/pages.py 中找到对应实现相关回归测试集中在 wagtail/tests/tests.py是升级后自验证的现成依据。【免费下载链接】wagtailA Django content management system focused on flexibility and user experience项目地址: https://gitcode.com/GitHub_Trending/wa/wagtail创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表