如何创建自定义Wagtail Hooks实现资源删除后的页面校验?
自定义Wagtail资源删除Hook实现方案
前置说明
Wagtail的图片、文档、媒体资源均基于Django ORM模型实现,无需等待官方对象使用情况上报功能,以下临时方案可直接覆盖资源删除前后触发校验的需求。
方案1:基于Django信号实现删除触发逻辑(最快落地)
直接监听资源模型的删除前信号,嵌入全页面校验逻辑即可:
- 在对应Wagtail应用目录下新建
signals.py,写入以下代码:
from django.db.models.signals import pre_delete from django.dispatch import receiver from wagtail.images.models import Image from wagtail.documents.models import Document # 若使用自定义媒体模型,替换为你定义的模型类即可 from wagtailmedia.models import Media from wagtail.core.models import Page @receiver(pre_delete, sender=Image) @receiver(pre_delete, sender=Document) @receiver(pre_delete, sender=Media) def check_resource_references_before_delete(sender, instance, **kwargs): # 全页面校验逻辑可根据业务需求扩展 live_pages = Page.objects.all().live() referenced_pages = [] for page in live_pages: # 校验StreamField资源引用 if hasattr(page, 'body'): for block in page.body: if block.block_type in ['image', 'document', 'media'] and getattr(block.value, 'id', None) == instance.id: referenced_pages.append(page.title) break # 其他自定义字段的校验逻辑可在此处补充 if referenced_pages: # 可根据需求选择抛出异常阻止删除、记录告警日志、标记待修复页面等操作 raise ValueError(f"当前资源已被以下页面引用,禁止删除:{','.join(referenced_pages)}")
- 在应用的
apps.py中注册信号:
from django.apps import AppConfig class YourAppConfig(AppConfig): default_auto_field = 'django.db.models.BigAutoField' name = '你的应用名称' def ready(self): # 替换为你的应用信号模块导入路径 import your_app_name.signals
方案2:注册标准Wagtail自定义Hook(可复用场景)
如果需要让删除触发逻辑可以像原生Wagtail Hook一样被其他模块复用,可以按以下方式注册自定义Hook:
- 在应用目录下新建
wagtail_hooks.py,写入以下代码:
from wagtail.core import hooks from django.db.models.signals import pre_delete from django.dispatch import receiver from wagtail.images.models import Image from wagtail.documents.models import Document from wagtailmedia.models import Media # 注册自定义Hook类型 hooks.register_temporarily('before_resource_delete', callable) # 监听资源删除信号,触发自定义Hook回调 @receiver(pre_delete, sender=Image) @receiver(pre_delete, sender=Document) @receiver(pre_delete, sender=Media) def trigger_resource_delete_hook(sender, instance, **kwargs): for callback in hooks.get_hooks('before_resource_delete'): callback(instance) # 注册Hook回调逻辑,和原生Hook用法完全一致 @hooks.register('before_resource_delete') def validate_page_resource_reference(resource): # 此处写入全页面校验逻辑即可,和方案1的校验逻辑通用 pass
存量问题修复补充
针对已经出现的资源删除后页面访问异常问题,可在页面渲染逻辑中添加兜底处理:遍历页面所有资源引用字段,遇到资源不存在的情况时返回占位内容,避免页面抛出错误直接无法访问。
内容的提问来源于stack exchange,提问作者Holger P.
相关产品推荐
相关产品推荐

