django CMS 2.3.4 升级指南:WymEditor 修复、挪威语语言码迁移与多站点 slug 冲突防护详解
2026/9/24 16:54:53 网站建设 项目流程
  • CMS
  • 后端

【免费下载链接】django-cms

The easy-to-use and developer-friendly enterprise CMS powered by Django

项目地址:https://gitcode.com/gh_mirrors/dj/django-cms
点击查看免费下载

本文基于 django CMS 官方 2.3.4 release notes(docs/upgrade/2.3.4.rst)编写,系统梳理该版本在编辑器资源加载、语言代码迁移、时区支持、slug 冲突校验、PlaceholderField 相关名约束及页面修改表单等方面的修复与变更,并结合当前仓库源码验证其底层实现。读者阅读后可完整掌握 2.3.4 升级所需的所有配置变更、行为差异与排查要点。

升级背景与本文目标

django CMS 是一个基于 Django 的企业级内容管理系统。每个 minor/patch 版本都可能带来行为变更或强制性的配置调整,官方在 docs/upgrade/index.rst 中明确建议:

升级前务必仔细阅读 release notes,并且对数据库做备份

2.3.4 属于 2.x 时代的维护版本,其改动虽不涉及数据库迁移,但包含多项影响运行行为、权限校验和 URL 生成的修复。本文将逐条拆解 2.3.4 的变更,并给出对应源码佐证与升级操作建议。


一、WymEditor 关键修复:JavaScript 资源加载失败

变更内容:2.3.4 修复了 WymEditor 的严重问题——此前它无法正确加载自身的 JavaScript 资源("prevented it from load it's JavaScript assets correctly"),导致富文本编辑功能不可用。

影响范围:使用 WymEditor 作为富文本编辑器(Text Plugin 编辑器后端)的站点。

升级建议

  • 升级后需清除浏览器缓存,并在编辑页面中重新验证 Text 插件编辑器能否正常渲染;
  • 若你仍在使用基于 WymEditor 的第三方插件,建议同步检查该插件与 2.3.4 的兼容性。

说明:WymEditor 相关资源加载逻辑在后续版本中已逐步从 django CMS 核心中移出(当前仓库 cms 源码中已无 WymEditor 相关实现,属于历史版本组件),本修复仅对 2.3.4 及之前版本的用户有实际意义。


二、挪威语翻译迁移:nonb

变更内容:挪威语翻译的语言代码从旧的no迁移为nbnb(挪威博克马尔语)自 2003 年起就是挪威语的官方语言代码,no属于已废弃的旧代码。

强制操作(重要):如果站点运行在挪威语环境下,必须修改LANGUAGES设置,否则语言切换会失效:

# settings.py 修改前 LANGUAGES = [ ("no", "Norwegian"), # 其他语言... ] # settings.py 修改后 LANGUAGES = [ ("nb", "Norwegian"), # 其他语言... ]

同时需要确认:

  • LANGUAGE_CODE是否也引用了no,如引用了需同步改为nb
  • 数据库中已保存的language字段值(如 Page、CMSPlugin 的语言记录)若存有旧值no,需评估是否需要数据修正(该版本 release notes 未提供自动迁移,需站点自行处理)。

仓库佐证:当前仓库 cms/locale 目录中同时保留了nbno两个语言目录(cms/locale/nb 与 cms/locale/no),可见nb已成为主要语言目录,no作为历史遗留保留,进一步印证了该语言码迁移方向。


三、新增时区支持(Django 1.4 +USE_TZ=True

变更内容:在 Django 1.4 及以上版本中,当USE_TZ=True时,django CMS 开始使用**时区感知(timezone-aware)**的日期时间对象,此前使用的是 naive datetime。

影响范围:所有依赖页面、插件创建时间的逻辑,以及缓存键生成、前台渲染中的时间显示。

配置方式

# settings.py USE_TZ = True # 开启时区支持 TIME_ZONE = "Europe/Oslo" # 按站点实际时区设置

源码佐证(当前仓库实现)

  • cms/models/contentmodels.py 中creation_date字段使用default=timezone.now作为默认值,timezone.now()USE_TZ=True时返回 aware datetime;
  • cms/models/pluginmodel.py 中插件模型的creation_date同样使用timezone.now
  • cms/cache/page.py 的缓存逻辑会根据settings.USE_TZ分支处理时间,说明时区设置会直接影响缓存键的生成与命中;
  • 测试配置 cms/tests/settings.py 中USE_TZ = bool(os.environ.get("USE_TZ")),表明测试环境可通过环境变量切换时区行为,验证了USE_TZ是 django CMS 可感知的配置项。

升级建议:升级到 2.3.4 后,如果开启USE_TZ=True,应重点回归测试:

  1. 页面创建时间、插件创建时间是否正确显示;
  2. 使用了timezone.now()的自定义字段是否仍正常;
  3. 缓存是否因时间对象类型变化而产生异常。

四、修复 slug 冲突:发布重复 URL 的页面不再静默出错

变更内容:在更早的版本中,发布一个与其他已发布页面具有相同 slug(URL)的页面可能导致错误。2.3.4 起,当要发布的页面与其他已发布页面 URL 相同时,系统会向用户显示错误提示,并要求其修改该页面的 slug 后再发布。

当前仓库源码验证(同层级 slug 唯一性): 当前版本在页面移动/树形操作表单 cms/admin/forms.py 中实现了完整的唯一性校验链:

def _validate_slug_uniqueness(self, parent, language, slug): target_siblings = Page.objects.filter( parent=parent, site=self._site, is_page_type=self.page.is_page_type, ).exclude(pk=self.page.pk) if target_siblings.filter(urls__slug=slug, urls__language=language).exists(): raise ValidationError( _( "You cannot have two pages with the same slug at the same page level. " "Please alter the slug of one of the pages before trying to move again." ) )

这段代码揭示的现代校验规则:

  • slug 唯一性按父页面(parent)+ 站点(site)+ 页面类型(is_page_type)+ 语言(language)维度校验;
  • 校验发生在页面移动(move)场景下(_validate_slug_uniqueness由 cms/admin/forms.py 的移动流程调用,随后还会调用_validate_url_uniqueness校验完整路径唯一性);
  • 冲突时抛出ValidationError,用户界面会看到明确的错误文案并需要修改 slug。

2.3.4 中引入的正是这一冲突从静默出错变为显式报错并提示修改 slug的行为,其核心思想延续至今——即在发布/移动环节强制保证 URL 唯一。

升级建议

  • 升级前检查站点中是否存在历史上遗留的重复 slug 页面,提前修正;
  • 升级后测试发布"slug 与其他已发布页面相同"的页面,确认能正确收到错误提示。

五、PlaceholderField 禁止省略 related_name:权限校验的前提

变更内容cms.models.fields.PlaceholderField不再允许省略related_name(即不允许传入related_name="+"来禁止反向关联)。尝试省略会抛出ValueError。此变更的目的是让 django CMS 能正确检查 Placeholder 字段上的权限

当前仓库源码佐证

cms/models/fields.py 中PlaceholderField的定义:

class PlaceholderField(models.ForeignKey): """ .. warning:: This field is for django CMS versions below 4 only. It may only be used inside migrations. ... """ def __init__(self, slotname, *args, **kwargs): kwargs.update({'null': True}) # always allow Null kwargs.update({'editable': False}) # never allow edits in admin self.slotname = slotname kwargs['to'] = 'cms.Placeholder' kwargs['on_delete'] = models.CASCADE super().__init__(**kwargs)

需要说明的是:在当前仓库(django CMS 4.x/5.x 主线)中,PlaceholderField已被标记为"仅用于 django CMS 4 以下版本、只能在 migrations 中使用",并带有系统检查提示cms.E001(建议改用PlaceholderRelationField)。这一演进正是 2.3.4 权限校验思路的延续——让 Placeholder 与宿主模型之间保持可追踪的反向关系,是 cms/models/placeholdermodel.py 中has_change_permissionhas_add_plugin_permission等权限方法能够定位"该 placeholder 属于哪些模型"的基础。

升级建议(针对 2.3.4 时代的项目)

  • 检索项目中所有使用PlaceholderField且传入了related_name="+"(或related_name=None场景)的模型定义;
  • 为每个PlaceholderField提供明确的related_name(如related_name="post_placeholders");
  • 如使用抽象基类模式,需保证每个子类都有不冲突的 related_name;
  • 若项目沿用至今并升级到 django CMS 4+,应规划迁移至PlaceholderRelationField(见 cms/models/fields.py 的PlaceholderRelationField(GenericRelation)实现)。

六、页面修改表单(change form)的两处修复

2.3.4 修复了页面管理后台修改表单的两个问题:

6.1 无发布权限用户编辑页面报错

问题:当编辑页面的用户没有发布权限时,页面修改表单会抛出错误。

修复:2.3.4 起,无发布权限的用户也能正常打开并编辑页面修改表单(发布操作仍受权限控制)。

升级建议:回归测试"仅具有编辑权限、无发布权限"的用户角色,确认其可以进入页面修改表单并保存草稿。

6.2DEBUG=False时 slug 字段无法正确预填

问题:当DEBUG设置为False时,页面修改表单无法正确预填充 slug 字段。

修复:2.3.4 起,无论在DEBUG=True还是False下,slug 字段都会正确预填。

升级建议

  • DEBUG=False的生产配置下进入页面修改表单,确认 slug 字段已正确显示当前值;
  • 该问题与"表单初始化依赖调试模式相关上下文"的历史实现有关,修复后表单渲染不再受DEBUG开关影响。

七、升级操作清单(Checklist)

结合上述变更,从 2.3.4 之前的版本升级时建议按以下清单操作:

  1. 备份数据库(官方 docs/upgrade/index.rst 强烈建议);
  2. 检查语言设置:如使用挪威语,将LANGUAGESLANGUAGE_CODE中的no改为nb,并核对存量数据中的语言字段;
  3. 检查时区设置:确认USE_TZTIME_ZONE配置符合预期,回归测试时间显示与缓存行为;
  4. 检查 slug 冲突:审查站点内是否存在重复 slug 的已发布页面,升级后验证发布冲突提示是否生效;
  5. 检查 PlaceholderField 定义:为所有PlaceholderField显式提供related_name,移除related_name="+"用法;
  6. 回归测试页面修改表单:覆盖"无发布权限用户编辑"与"DEBUG=False下 slug 预填"两个场景;
  7. 验证 WymEditor:升级后确认富文本编辑器资源正常加载(如仍在使用 WymEditor 作为编辑器后端)。

八、与当前仓库的关系说明

2.3.4 是 django CMS 2.x 时代的维护版本,其大部分修复(WymEditor、nonb语言码)在后续大版本中已被组件演进或语言目录更新所吸收;而slug 唯一性校验Placeholder 权限校验基础这两项设计理念,在现行源码中依然清晰可见:

  • slug 唯一性:当前通过 cms/admin/forms.py 的_validate_slug_uniqueness_validate_url_uniqueness在页面移动/树操作时强制执行;
  • Placeholder 权限:当前通过 cms/models/placeholdermodel.py 的has_change_permission/has_add_plugin_permission等接口实现,且 Placeholder 与宿主模型的关联已演进为 PlaceholderRelationField。

因此,本升级指南不仅适用于仍停留在 2.3.4 时代的存量项目,也可帮助开发者理解 django CMS URL 唯一性与权限校验机制的设计脉络。

  • CMS
  • 后端

【免费下载链接】django-cms

The easy-to-use and developer-friendly enterprise CMS powered by Django

项目地址:https://gitcode.com/gh_mirrors/dj/django-cms
点击查看免费下载
上一篇:终极OBS视频流革命:Spout2插件完整指南
下一篇:如何零成本扩展工作空间:VirtualMonitor虚拟显示器完整指南

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询