我应该如何将 wagtail-lazyimages 与 Wagtail 的 RichTextField 集成?
How should I go about integrating wagtail-lazyimages with Wagtail's RichTextField?
我正在尝试为我的博客 post 图片实现延迟加载,但我正在为我的博客 post 使用 RichTextField,所以我无法指定每个图片标签,例如Wagtail-LazyImages 文档建议我应该这样做。
根据 Wagtail Docs on RichTextField internals,图像可以存储为 <embed embedtype="image" id="10" alt="A pied wagtail" format="left" />
,但在渲染时会转换为 <img alt="A pied wagtail" class="richtext-image left" height="294" src="/media/images/pied-wagtail.width-500_ENyKffb.jpg" width="500">
,这意味着并不是像 LazyImages 那样寻找任何显式标记用法。
这更像是一个概念性问题,因为我只是不确定在流程中的哪个位置挂钩 Wagtail 的 RTF 处理。
我可以利用 register_rich_text_features 挂钩为惰性图像制作一个新的“功能”,然后使用惰性图像 class 吗?
我通过在 image_formats.py
文件中子类化 Format(Changing rich text representation) 解决了这个问题。我覆盖了它的 image_to_html
方法,用占位符替换 'src'
属性并添加 'data-src'
属性。
不要忘记在关闭 </body>
标签之前添加像 lazysizes 这样的延迟加载库。
from django.utils.html import format_html
from django.utils.html import escape
from wagtail.images.formats import Format, register_image_format
from wagtail.images.shortcuts import get_rendition_or_not_found
class LazyImageFormat(Format):
def image_to_html(self, image, alt_text, extra_attributes=None):
if extra_attributes is None:
extra_attributes = {}
rendition = get_rendition_or_not_found(image, self.filter_spec)
#Placeholder scaling based on image height. Needed ONLY if you use this SVG "loading" placeholder.
svg_width = rendition.width//2
svg_height = rendition.height//2
load_scale = rendition.height//100
#Overwriting 'src' and adding 'data-src' attribute. 'src' - can be any placeholder value
extra_attributes['src'] = format_html('''data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 {} {}'%3E%3Ccircle cx='{}' cy='{}' fill='none' stroke='%23393939' stroke-width='{}' r='{}' stroke-dasharray='{} {}' transform='rotate(175 50 50)'%3E%3CanimateTransform attributeName='transform' type='rotate' repeatCount='indefinite' dur='2s' values='0 {} {};360 {} {}' keyTimes='0;1'/%3E%3C/circle%3E%3C/svg%3E''',
rendition.width, rendition.height, svg_width, svg_height, 5*load_scale, 15*load_scale, 70*load_scale, 25*load_scale, svg_width, svg_height, svg_width, svg_height)
extra_attributes['data-src'] = rendition.url
extra_attributes['alt'] = escape(alt_text)
if self.classnames:
extra_attributes['class'] = "%s" % escape(self.classnames)
return rendition.img_tag(extra_attributes)
#register our custom LazyImageFormat and add 'lazyload' class
register_image_format(LazyImageFormat('lazy_fullwidth', 'Centered-1000 lazy', 'richtext-image centered lazyload', 'width-1000'))
register_image_format(LazyImageFormat('lazy_original', 'Original lazy', 'richtext-image centered lazyload', 'original'))
我正在尝试为我的博客 post 图片实现延迟加载,但我正在为我的博客 post 使用 RichTextField,所以我无法指定每个图片标签,例如Wagtail-LazyImages 文档建议我应该这样做。
根据 Wagtail Docs on RichTextField internals,图像可以存储为 <embed embedtype="image" id="10" alt="A pied wagtail" format="left" />
,但在渲染时会转换为 <img alt="A pied wagtail" class="richtext-image left" height="294" src="/media/images/pied-wagtail.width-500_ENyKffb.jpg" width="500">
,这意味着并不是像 LazyImages 那样寻找任何显式标记用法。
这更像是一个概念性问题,因为我只是不确定在流程中的哪个位置挂钩 Wagtail 的 RTF 处理。
我可以利用 register_rich_text_features 挂钩为惰性图像制作一个新的“功能”,然后使用惰性图像 class 吗?
我通过在 image_formats.py
文件中子类化 Format(Changing rich text representation) 解决了这个问题。我覆盖了它的 image_to_html
方法,用占位符替换 'src'
属性并添加 'data-src'
属性。
不要忘记在关闭 </body>
标签之前添加像 lazysizes 这样的延迟加载库。
from django.utils.html import format_html
from django.utils.html import escape
from wagtail.images.formats import Format, register_image_format
from wagtail.images.shortcuts import get_rendition_or_not_found
class LazyImageFormat(Format):
def image_to_html(self, image, alt_text, extra_attributes=None):
if extra_attributes is None:
extra_attributes = {}
rendition = get_rendition_or_not_found(image, self.filter_spec)
#Placeholder scaling based on image height. Needed ONLY if you use this SVG "loading" placeholder.
svg_width = rendition.width//2
svg_height = rendition.height//2
load_scale = rendition.height//100
#Overwriting 'src' and adding 'data-src' attribute. 'src' - can be any placeholder value
extra_attributes['src'] = format_html('''data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 {} {}'%3E%3Ccircle cx='{}' cy='{}' fill='none' stroke='%23393939' stroke-width='{}' r='{}' stroke-dasharray='{} {}' transform='rotate(175 50 50)'%3E%3CanimateTransform attributeName='transform' type='rotate' repeatCount='indefinite' dur='2s' values='0 {} {};360 {} {}' keyTimes='0;1'/%3E%3C/circle%3E%3C/svg%3E''',
rendition.width, rendition.height, svg_width, svg_height, 5*load_scale, 15*load_scale, 70*load_scale, 25*load_scale, svg_width, svg_height, svg_width, svg_height)
extra_attributes['data-src'] = rendition.url
extra_attributes['alt'] = escape(alt_text)
if self.classnames:
extra_attributes['class'] = "%s" % escape(self.classnames)
return rendition.img_tag(extra_attributes)
#register our custom LazyImageFormat and add 'lazyload' class
register_image_format(LazyImageFormat('lazy_fullwidth', 'Centered-1000 lazy', 'richtext-image centered lazyload', 'width-1000'))
register_image_format(LazyImageFormat('lazy_original', 'Original lazy', 'richtext-image centered lazyload', 'original'))