Wagtail 教程 3:Bootstrap 4,Font Awesome,页面布局优化

十二月 22, 2018


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


此部分属于通用内容,非 Wagtail 必需内容,是为了完善/优化基于 Wagtail 搭建的博客。

引入 Bootstrap 4

http://getbootstrap.com/
https://code.z01.com/v4/

打开上面网址,下载以下文件并放置到相应项目目录下:

/slowread/static/css/bootstrap.min.css

/slowread/static/js/jquery-3.3.1.slim.min.js
/slowread/static/js/popper.min.js
/slowread/static/js/bootstrap.min.js

修改 /slowread/templates/base.html ,加入以下内容:

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

...

{# Global javascript #}
...
<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>

引入 Font Awesome

https://fontawesome.com/
https://fontawesome.com/how-to-use/on-the-web/setup/hosting-font-awesome-yourself

下载文件,然后拷贝 /webfonts 和 /css/all.css 到 /slowread/static 目录下,结果如下:

/slowread/static/webfonts/fa-*.* 多个文件
/slowread/static/css/all.min.css 一个文件

修改 /slowread/templates/base.html ,加入以下内容:

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

页头

新建 /slowread/templates/header.html ,内容如下:

<!-- 定义导航栏 -->
<nav class="navbar navbar-expand-lg navbar-dark bg-primary">
  <div class="container">

    <!-- 导航栏标识 -->
    <a class="navbar-brand" href="/">慢读 慢生活</a>

    <!-- 导航入口 -->
    <div>
      <ul class="navbar-nav">
        <!-- 条目 -->
        <li class="nav-item">
          <a class="nav-link" href="/blog">博客文章</a>
        </li>
      </ul>
    </div>

  </div>
</nav>

页脚

新建 /slowread/templates/footer.html ,内容如下:

<!-- Footer -->
<footer class="py-3 bg-primary">
    <div class="container">
        <p class="m-0 text-center text-white">Copyright &copy; <a class="m-0 text-center text-white" href="https://slowread.net">SlowRead.net</a> 2018</p>
    </div>
</footer>

base.html

编辑页面模板文件 /slowread/templates/base.html ,内容如下:

{% load static wagtailuserbar %}

<!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 rel="stylesheet" type="text/css" href="{% static 'css/slowread.css' %}">
        <link href="{% static 'css/bootstrap.min.css' %}" rel="stylesheet" type="text/css">
        <link href="{% static 'css/all.min.css' %}" rel="stylesheet" type="text/css">

        {% block extra_css %}
            {# Override this in templates to add extra stylesheets #}
        {% endblock %}
    </head>

    <body class="{% block body_class %}{% endblock %}">
        <!-- 引入导航栏 -->
        {% include 'header.html' %}

        {% wagtailuserbar %}

        <div class="container">
                {% block content %}
                {% endblock %}
        </div>
        <!-- 引入注脚 -->
        {% include "footer.html" %}

        {# 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>

首页布局

编辑 /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]
        context['blogpages'] = blogpages
        return context

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

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

{% extends "base.html" %}

{% load wagtailcore_tags wagtailimages_tags %}

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

{% block content %}
    <h1 class="mt-2">{{ self.title }}</h1>
    {{ page.body|richtext }}

    <hr>

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

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

                <div class="card" style="width: 18em;">

                        {% 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 %}
class BlogIndexPage(Page):
    intro = RichTextField(blank=True)

    def get_context(self, request):
        # Update context to include only published posts, ordered by reverse-chron
        context = super().get_context(request)
        blogpages = self.get_children().live().order_by('-first_published_at')

        paginator = Paginator(blogpages, 3) # Show 3 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)

        # make the variable 'resources' available on the template
        context['blogpages'] = blogpages
        return context

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