Wagtail 教程 6:关于/图片轮播/标签

2018年12月29日


# Wagtail # Django # Python
  • Wagtail 是一个用 Python 编写的开源 CMS,基于 Django 框架构建。 它优雅、强大、敏捷,专注于灵活性和用户体验,为开发人员提供一个快速有吸引力的界面,可以直观地创建和组织内容。
  • Wagtail 教程系列 记录了基于 Wagtail 搭建博客站点的整个过程,当前站点 所呈现的即是搭建过程的最新效果。

关于

圆形带阴影图片效果。

<div class="card text-center mb-2">
    <div class="card-body">
        <div>
            <a href="/">
                <img class="shadow p-2 mb-2 bg-white rounded-circle" 
                    style="width:120px; height:120px; border-radius:50%; overflow:hidden;" 
                    src="{% static 'media/slowread-120x120.png' %}" alt="Logo - 站点Log" />
            </a>
        </div>
        <h5 class="card-title"><a href="https://slowread.net">慢读 慢生活</a></h5>
        <p class="card-text">Slow Rhythm of Life.</p>
    </div>
</div>

图片轮播

图片滚动播放基于 bootstrap 4。

修改 /slowread/home/models.py , 增加得到标签为 壁纸 的结果集,按时间倒序,只取最新的三个,内容如下:

class HomePage(Page):
    body = RichTextField(blank=True)

    def get_context(self, request):
        # Update context to include only published posts, ordered by reverse-chron
        context = super().get_context(request)
        page = Page.objects.get(title="文章列表")
        blogpages = page.get_children().live().order_by('-first_published_at')[:3]
        # tags = Tag.objects.all().order_by('name')
        wallpapers = Image.objects.filter(tags__name="壁纸").order_by('-created_at')[:3]
        context['blogpages'] = blogpages
        context['wallpapers'] = wallpapers
        # context['tags'] = tags
        return context

    content_panels = Page.content_panels + [
        FieldPanel('body', classname="full"),
    ]

在 /slowread/home/templates/home/home_page.html 页面中,用 django 模板语法中的 forloop.first,实现第一张图片为活动状态,其他图片为非活动状态,具体内容如下:

{% for wallpaper in wallpapers %}

    {% image wallpaper max-800x600 as wallpaper_800x600 %}
    {% image wallpaper original as wallpaper_original %}

    <div {% if forloop.first %} class="carousel-item active"{% else %} class="carousel-item"{% endif %}>
        <a href="{{ wallpaper_original.url }}">
            <img class="d-block w-100 " src="{{ wallpaper_800x600.url }}">
        </a>
    </div>
{% endfor %}

完整内容如下:

{% extends "base.html" %}

{% load static wagtailcore_tags wagtailimages_tags %}

{% block body_class %}template-homepage{% endblock %}

{% block content %}

    <div class="row mb-2 mt-3">
        <div class="col-lg-8 mb-2">
            <div id="carouselExampleIndicators" class="carousel slide" data-ride="carousel">
                <ol class="carousel-indicators">
                    <li data-target="#carouselExampleIndicators" data-slide-to="0" class="active"></li>
                    <li data-target="#carouselExampleIndicators" data-slide-to="1"></li>
                    <li data-target="#carouselExampleIndicators" data-slide-to="2"></li>
                </ol>
                <div class="carousel-inner rounded">

                    {% for wallpaper in wallpapers %}

                        {% image wallpaper max-800x600 as wallpaper_800x600 %}
                        {% image wallpaper original as wallpaper_original %}
                        {{ first|add:1 }}
                        <div {% if forloop.first %} class="carousel-item active"{% else %} class="carousel-item"{% endif %}>
                            <a href="{{ wallpaper_original.url }}">
                                <img class="d-block w-100 " src="{{ wallpaper_800x600.url }}">
                            </a>
                        </div>
                    {% endfor %}

                </div>
                <a class="carousel-control-prev" href="#carouselExampleIndicators" role="button" data-slide="prev">
                    <span class="carousel-control-prev-icon" aria-hidden="true"></span>
                    <span class="sr-only">Previous</span>
                </a>
                <a class="carousel-control-next" href="#carouselExampleIndicators" role="button" data-slide="next">
                    <span class="carousel-control-next-icon" aria-hidden="true"></span>
                    <span class="sr-only">Next</span>
                </a>
            </div>
        </div>
        <div class="col-lg-4">
            <div class="card text-center mb-2">
                <div class="card-body">
                    <div>
                        <a href="/">
                            <img class="shadow p-2 mb-2 bg-white rounded-circle"
                                style="width:120px; height:120px; border-radius:50%; overflow:hidden;"
                                src="{% static 'media/slowread-120x120.png' %}" alt="Logo - 站点Log" />
                        </a>
                    </div>
                    <h5 class="card-title"><a href="https://slowread.net">慢读 慢生活</a></h5>
                    <p class="card-text">Slow Rhythm of Life.</p>
                </div>
            </div>
            <div class="card text-center mb-2">
                <div class="card-body">
                    <h5 class="card-title">Special title treatment</h5>
                    <p class="card-text">With supporting text below as a natural lead-in to additional content.</p>
                </div>
            </div>
        </div>
    </div>

    <div class="card-deck mb-2">

        {% for post in blogpages %}
            {% with post=post.specific %}

                <div class="card">

                        {% with post.main_image as main_image %}
                            {% if main_image %}
                                {% image main_image fill-320x240 as header_image %}
                                <a href="{% pageurl post %}">
                                    <img src="{{ header_image.url }}"  class="card-img-top" />
                                </a>
                            {% endif %}
                        {% endwith %}

                        <div class="card-body">
                        <h5 class="card-title"><a href="{% pageurl post %}">{{ post.title }}</a></h5>
                        <p class="card-text">
                            {% if post.intro %}
                                {{ post.intro|richtext }}
                            {% else %}
                                {{ post.body|richtext|truncatewords_html:80 }}
                            {% endif %}
                        </p>
                    </div>

                    <div class="card-footer">
                        <small class="text-muted"><a href="{% pageurl post %}" class="btn btn-primary">阅读全文</a></small>
                    </div>
                </div>

            {% endwith %}
        {% endfor %}

    </div>

    <hr>
        <a class="nav-link text-center" href="/blog">更多文章</a>
    <hr>

{% endblock %}

标签

在 Wagtail 实践 2:简单博客实现 中已经实现了标签列表的初步功能,现在增加首页标签链接和标签列表分页功能。

标签链接

编辑 /slowread/home/templates/home/home_page.html ,增加如下内容:

<div class="card text-center mb-2">
    <div class="card-body">
        <a href="{% slugurl 'tags' %}?tag=django" class="mr-2">django</a>
        <a href="{% slugurl 'tags' %}?tag=Linux" class="mr-2">Linux</a>
        <a href="{% slugurl 'tags' %}?tag=Python" class="mr-2">Python</a>
        <a href="{% slugurl 'tags' %}?tag=VPS" class="mr-2">VPS</a>
        <a href="{% slugurl 'tags' %}?tag=Wagtail" class="mr-2">Wagtail</a>
    </div>
</div>

标签检索结果分页

点击某个标签,会进入标签列表页面,如果标签对应的内容比较多,就需要对内容列表进行分页。

编辑 /slowread/blog/models.py ,修改内容如下:

class BlogTagIndexPage(Page):

    def get_context(self, request):

        # Filter by tag
        tag = request.GET.get('tag')
        blogpages = BlogPage.objects.filter(tags__name=tag).order_by('-first_published_at')

        paginator = Paginator(blogpages, 6) # Show 6 resources per page

        page = request.GET.get('page')
        try:
            blogpages = paginator.page(page)
        except PageNotAnInteger:
            # If page is not an integer, deliver first page.
            blogpages = paginator.page(1)
        except EmptyPage:
            # If page is out of range (e.g. 9999), deliver last page of results.
            blogpages = paginator.page(paginator.num_pages)

        # Update template context
        context = super().get_context(request)
        context['tag'] = tag
        context['blogpages'] = blogpages
        return context

编辑 /slowread/blog/templates/blog/blog_tag_index_page.html ,增加如下内容:

<nav aria-label="Page navigation">
    <ul class="pagination justify-content-center">
        {% if blogpages.has_previous %}
            <li class="page-item">
                <a class="page-link" href="?tag={{ tag }}&page={{ blogpages.previous_page_number }}">&laquo;</a>
            </li>
        {% endif %}
        {% for page_num in blogpages.paginator.page_range %}
            <li {% if page_num == blogpages.number %} class="active page-item"{% endif %}>
                <a class="page-link" href="?tag={{ tag }}&page={{ page_num }}">{{ page_num }}</a>
            </li>
        {% endfor %}
        {% if blogpages.has_next %}
            <li class="page-item">
                <a class="page-link" href="?tag={{ tag }}&page={{ blogpages.next_page_number }}">&raquo;</a>
            </li>
        {% endif %}
    </ul>
</nav>

图片标签

之前的标签操作都是针对文章所属的标签,下面针对标签为壁纸的图片进行独立的标签操作。

编辑 /slowread/blog/models.py ,增加壁纸滚动播放页面模型 WallpaperCarouselPage 内容如下:

class WallpaperCarouselPage(Page):

    def get_context(self, request):

        wallpapers = Image.objects.filter(tags__name="壁纸").order_by('-created_at')[:10]

        # Update template context
        context = super().get_context(request)
        context['wallpapers'] = wallpapers
        return context

进入后台管理,在 Home 页面下增加类型为 Wallpaper carousel page 子页面,标题为壁纸,推荐中的缩略名为 wallpaper 。

新建壁纸滚动播放页面模板文件 /slowread/blog/templates/blog/wallpaper_carousel_page.html,内容如下:

{% load static %}

{% load wagtailcore_tags wagtailimages_tags %}

<!DOCTYPE html>
<html lang="zh_cn">
    <head>
        <meta charset="utf-8" />
        <title>
            {% block title %}
                {% if self.seo_title %}{{ self.seo_title }}{% else %}{{ self.title }}{% endif %}
            {% endblock %}
            {% block title_suffix %}
                {% with self.get_site.site_name as site_name %}
                    {% if site_name %}- {{ site_name }}{% endif %}
                {% endwith %}
            {% endblock %}
        </title>
        <meta name="description" content="" />
        <meta name="viewport" content="width=device-width, initial-scale=1" />

        <link rel="icon" type="image/png" sizes="32x32" href="{% static 'media/slowread-32x32.ico' %}">
        <link rel="icon" type="image/png" sizes="16x16" href="{% static 'media/slowread-16x16.ico' %}">

        {# Global stylesheets #}
        <link href="{% static 'css/bootstrap.min.css' %}" rel="stylesheet" type="text/css">
        <link href="{% static 'css/all.min.css' %}" rel="stylesheet" type="text/css">
        <link rel="stylesheet" type="text/css" href="{% static 'css/slowread.css' %}">

    </head>

    <body class="{% block body_class %}{% endblock %}">

        <div class="container-fluid">
            <div class="row">
                <div id="carouselExampleIndicators" class="carousel slide" data-ride="carousel">

                    <div class="carousel-inner">

                        {% for wallpaper in wallpapers %}

                            {% image wallpaper original as wallpaper_original %}

                            <div {% if forloop.first %} class="carousel-item active"{% else %} class="carousel-item"{% endif %}>
                                <img class="d-block w-100" src="{{ wallpaper_original.url }}">
                            </div>
                        {% empty %}
                            No Wallpaper found.
                        {% endfor %}

                    </div>
                    <a class="carousel-control-prev" href="#carouselExampleIndicators" role="button" data-slide="prev">
                        <span class="carousel-control-prev-icon" aria-hidden="true"></span>
                        <span class="sr-only">Previous</span>
                    </a>
                    <a class="carousel-control-next" href="#carouselExampleIndicators" role="button" data-slide="next">
                        <span class="carousel-control-next-icon" aria-hidden="true"></span>
                        <span class="sr-only">Next</span>
                    </a>
                </div>
            </div>
        </div>

    {# Global javascript #}
    <script type="text/javascript" src="{% static 'js/slowread.js' %}"></script>
    <script src="{% static 'js/jquery-3.3.1.slim.min.js' %}" type="text/javascript"></script>
    <script src="{% static 'js/popper.min.js' %}" type="text/javascript"></script>
    <script src="{% static 'js/bootstrap.min.js' %}" type="text/javascript"></script>

    {% block extra_js %}
        {# Override this in templates to add extra javascript #}
    {% endblock %}
    </body>
</html>

由于不需要页头/页脚样式,壁纸轮播页面模板没有基于 base.html 母板页面扩展,而是全新创建一个模板文件。