跳转到主要内容

为Wagtail提供AMP网页故事支持

项目描述

wagtail-webstories

此软件包为Wagtail添加了对AMP网页故事的支持。可以在原始URL位置链接或嵌入其他地方创建的故事,或将故事作为Wagtail页面导入,包括可选地将图片和视频导入Wagtail媒体库。

wagtail-webstories与Wagtail 4.1及以上版本兼容。

安装

使用pip安装

pip install wagtail-webstories

添加到INSTALLED_APPS

INSTALLED_APPS = [
    # ...
    'wagtail_webstories',
    # ...
]

运行迁移

./manage.py migrate

嵌入和链接外部故事

要将网页故事嵌入到基于StreamField的常规(非AMP)页面中,请将wagtail_webstories.blocks.ExternalStoryEmbedBlock块类型包含在您的StreamField定义中

from wagtail_webstories.blocks import ExternalStoryEmbedBlock

class BlogPage(Page):
    body = StreamField([
        ('heading', blocks.CharBlock()),
        ('paragraph', blocks.RichTextBlock()),
        ('story_embed', ExternalStoryEmbedBlock()),
    ])

此块允许页面作者提供AMP网络故事的URL,该URL将在前端模板(使用{% include_block %})上渲染为<amp-story-player>元素;您的模板应包含渲染此内容的必要脚本,以及一个CSS规则来指定适当的尺寸

    <script async src="https://cdn.ampproject.org/amp-story-player-v0.js"></script>
    <link href="https://cdn.ampproject.org/amp-story-player-v0.css" rel="stylesheet" type="text/css">
    <style>
        amp-story-player { width: 360px; height: 600px; }
    </style>

要包含指向故事的链接而不是嵌入它,可以使用wagtail_webstories.blocks.ExternalStoryBlock代替ExternalStoryEmbedBlock。默认模板wagtail_webstories/blocks/external_story_poster_link.html输出故事的“卡片”渲染,使用故事的封面图片,需要使用以下CSS

    .webstory-poster {
        display: block; width: 300px; height: 400px; border-radius: 15px; background-size: cover; position: relative;
    }
    .webstory-poster .webstory-info {
        position: absolute; bottom: 0; width: 100%; background-color: #ccc; color: black; border-bottom-left-radius: 15px; border-bottom-right-radius: 15px;
    }
    .webstory-poster .title {
        font-size: 1.5em; padding: 10px;
    }
    .webstory-poster .publisher {
        padding: 0 10px 20px 10px;
    }
    .webstory-poster .publisher img {
        vertical-align: middle;
    }

在没有StreamField的情况下嵌入和链接外部故事

外部故事通过模型wagtail_webstories.models.ExternalStory处理。要为给定的URL获取ExternalStory实例,使用:ExternalStory.get_for_url(story_url)。故事元数据在ExternalStory模型中缓存,以避免每次请求都需要重新获取故事 - 可用的元数据字段有urltitlepublisherpublisher_logo_srcposter_portrait_srcposter_square_srcposter_landscape_src

StreamField块模板wagtail_webstories/blocks/external_story_embed_block.htmlwagtail_webstories/blocks/external_story_poster_link.html可用于渲染ExternalStory对象,通过将变量story传递给它

# models.py
class BlogPostWithStoryPage(Page):
    story_url = model.URLField(max_length=2048)

    def get_context(self, request):
        context = super().get_context(request)
        context['story_obj'] = ExternalStory.get_for_url(self.story_url)
        return context
{# blog_post_with_story_page.html #}

{% include "wagtail_webstories/blocks/external_story_embed_block.html" with story=story_obj %}

导入

要允许将故事作为Wagtail页面导入,定义一个扩展wagtail_webstories.models.BaseWebStoryPage的模型

from wagtail_webstories.models import BaseWebStoryPage

class StoryPage(BaseWebStoryPage):
    pass

或者,如果您的项目有一个所有页面类型都必须继承的现有基础页面类(这将防止在基础类中使用BaseWebStoryPage),则扩展wagtail_webstories.models.WebStoryPageMixin并定义content_panelspromote_panels以包含其面板定义

from wagtail_webstories.models import WebStoryPageMixin

class StoryPage(WebStoryPageMixin, BasePage):
    content_panels = BasePage.content_panels + WebStoryPageMixin.web_story_content_panels
    promote_panels = BasePage.promote_panels + WebStoryPageMixin.web_story_promote_panels

现在创建一个相应的模板,该模板扩展wagtail_webstories/base_web_story_page.html

{% extends "wagtail_webstories/base_web_story_page.html" %}

定义一个设置WAGTAIL_WEBSTORIES_IMPORT_MODEL,指向要使用的页面模型

WAGTAIL_WEBSTORIES_IMPORT_MODEL = 'myapp.StoryPage'

这将现在在Wagtail管理菜单中添加一个“Web故事”项,允许您通过URL导入故事。

HTML清理

默认情况下,在导入和保存时,所有不允许的AMP网络故事规范的HTML元素和属性将被删除。要禁用此功能,将WAGTAIL_WEBSTORIES_CLEAN_HTML设置为False

WAGTAIL_WEBSTORIES_CLEAN_HTML = False

图像导入

默认情况下,导入的故事中的图像引用保留在其原始URL上。BaseWebStoryPage提供了一个方法import_images()来获取所有引用的图像并将它们导入Wagtail图像库,如果它们已经存在则去重。建议您从post_save信号处理程序中调用此方法

# myapp/signals.py

from django.db.models.signals import post_save
from django.dispatch import receiver

from .models import StoryPage


@receiver(post_save, sender=StoryPage)
def import_story_images(sender, instance, **kwargs):
    changed = instance.import_images()
    if changed:
        instance.save()


# myapp/apps.py

from django.apps import AppConfig


class MyappConfig(AppConfig):
    name = 'myapp'

    def ready(self):
        import myapp.signals  # noqa


# myapp/__init__.py

default_app_config = 'myapp.apps.MyappConfig'

由于导入图像可能是一个耗时的过程,您可能希望将import_images的调用卸载到Celery或类似的后台任务中,以避免这阻止了Web服务器线程。

要自定义新图像的创建(例如,将导入的图像分配给特定的集合,或在自定义图像模型上填充额外的元数据字段),则覆盖故事页面模型中的_create_image方法

class StoryPage(BaseWebStoryPage):

    def _create_image(self, file, title=None):
        image = super()._create_image(file, title=title)
        image.copyright = "All rights reserved"
        return image

视频导入

如果您已安装wagtailmedia,则可以类似地通过调用import_videos()将视频导入本地媒体库。上面的信号处理程序变为

# myapp/signals.py

@receiver(post_save, sender=StoryPage)
def import_story_images(sender, instance, **kwargs):
    images_changed = instance.import_images()
    videos_changed = instance.import_videos()
    if images_changed or videos_changed:
        instance.save()

链接和嵌入导入的故事

要将导入的Web故事嵌入或链接到常规(非AMP)基于StreamField的页面,请在StreamField定义中包含wagtail_webstories.blocks.StoryEmbedBlockwagtail_webstories.blocks.StoryChooserBlock块类型。这些与ExternalStoryEmbedBlock和ExternalStoryBlock类似,但为页面作者提供了一个页面选择器界面,而不是URL字段。

from wagtail_webstories.blocks import StoryEmbedBlock

class BlogPage(Page):
    body = StreamField([
        ('heading', blocks.CharBlock()),
        ('paragraph', blocks.RichTextBlock()),
        ('local_story_embed', StoryEmbedBlock(target_model=StoryPage)),
    ])

target_model参数是可选的 - 默认情况下,任何继承自BaseWebStoryPage的页面类型都可以选择。与ExternalStoryEmbedBlock和ExternalStoryBlock一样,您的页面模板必须包含适当的JavaScript或CSS包含,用于渲染块。

模板 wagtail_webstories/blocks/story_poster_link.htmlwagtail_webstories/blocks/story_embed_block.html 预期一个名为 page 的变量,该变量包含故事页面实例,因此这些模板也可以在 StreamField 之外使用。

# models.py
class StoryIndexPage(Page):
    def get_context(self, request):
        context = super().get_context(request)
        context['stories'] = StoryPage.objects.child_of(self).live().order_by('-first_published_at')
        return context
{# story_index_page.html #}
{% for story in stories %}
    {% include "wagtail_webstories/blocks/story_poster_link.html" with page=story %}
{% endfor %}

项目详情


下载文件

下载适合您平台的文件。如果您不确定该选择哪个,请了解有关 安装包 的更多信息。

源分发

wagtail-webstories-0.1.1.tar.gz (19.1 kB 查看哈希值)

上传时间

构建分发

wagtail_webstories-0.1.1-py3-none-any.whl (20.4 kB 查看哈希值)

上传时间 Python 3

由以下机构支持