Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

wagtailで簡単なブログシステムを作る〜Learn Wagtail ①

More than 1 year has passed since last update.

Learn Wagtail ~ YouTubeで学習していきます。
英語が絶望的に出来ないので、字幕の自動翻訳で日本語を選択します。(なんで日本語1番下やねん。)
ただ、wagtailの参考文献はほぼ英語なのですが、、、

作業環境

Ubuntu 18.04.2 LTS
Panasonic Let's note
Python 3.7.3
Django 2.2.2
wagtail 2.5.1

完成例

Learn_Wagtail_Part4.png

左が一般公開するブログページ、右がWordPressのような管理ページです。

そもそもwagtailって何やねん

wagtailとは、PythonのフレームワークであるDjangoをベースとしたCMSライブラリで、Djangoとの繋がりが分かりやすく、カスタマイズしやすい。ただその分、他のDjangoベースのCMSと比べると、書くコードの量が多くなってしまう。

①How to Install Wagtail CMS using Pipenv in Less Than 6 Minutes

それでは、wagtailのインストールから初めていきます。
wagtailのHPにアクセスして、「Get Wagtail」を選択します。
そしたら、7行のコードが載っています。
pipやpythonの環境が整っていたら、そのまま打ち込めば終わりなのですが、ここでは少し細く進めていきます。

$ pip -V  #python3.5以降であることを確認。自分はpython3.7です。
$ pip install wagtail
$ pip freeze | grep wagtail
 wagtail==2.5.1
 wagtail-review==0.1.1  #こんな感じで表示されればOK
$ wagtail start mysite
$ cd mysite
$ ls
 Dockerfile  home  manage.py  mysite  requirements.txt  search
$ pip install pipenv  #この動画ではpipenvでpip環境を作成していますが、自分の環境にはpipenvがインストールされていなかった
$ pipenv shell  #先頭に (mysite) ➜  mysite のように表示されるはず
$ pip install -r requirements.txt
$ python manage.py migrate  #ローカルデータベースがセットアップされる。
$ python manage.py createsuperuser
$ python manage.py runserver

これで、ローカルサイト(http://127.0.0.1:8000/ )にアクセスできます。
http://127.0.0.1:8000/admin/ にアクセスして、ユーザー名・パスワードを入力すれば、ブログの管理画面に入れます。

wagtail_ブログ管理画面(初期).png


@3行目のコマンドの解説
pip freezeと似たものに、pip listがあります。
この2つを実際に打ってみるとこんな感じ。

$ pip list
Package    Version
---------- -------
future     0.16.0
pip        18.1
setuptools 39.2.0
six        1.11.0
wheel      0.31.1

$ pip freeze
future==0.16.0
six==1.11.0

表示の仕方が少し違いますね。
また、pip freezeではpip自体やsetuptools, wheelといったパッケージ管理のためのパッケージは出力されません。
参考文献〜Python,pip list/freeze でインストール済みパッケージ一覧を確認


@grepコマンドとは
grepはファイル中の文字列を検索するコマンドです。
|(シングルパイプ)はandのこと。
参考文献〜Linuxコマンド集  $ grep


@pipenvで環境構築する理由
Pythonパッケージをシステムから切り離して、同時に複数のプロジェクトを進行させることができるからです。
異なるパッケージや依存関係にあるパッケージを使っていると、そこで衝突してしまいます。それを防ぐ役割もあります。


@CMSとは
Contents Management System の略で、web制作に必要な専門的な知識が無くても、webサイトやコンテンツを構築・管理・更新できるシステムのことです。
HTMLやCSSの知識がなくても、ブログを作成できます。WordPressもその一例です。
これを導入するメリットとしては、コスト削減やスピーディーな情報発信、更新頻度を高められる、統一性のあるWebサイトを作れる、などがあります。
デメリットとしては、デザインの自由度の制限やオープンソースなのでセキュリティ面があります。
参考文献〜CMSとは?メリット・デメリットを理解しよう


②Getting Started With Your First Home Page in Wagtail CMS

それでは、簡単にページを編集していきましょう。

まず、最初の鳥の卵のページを自分なりのページにアレンジしてみます。
鳥の卵のページってのは、これのことですね。
wagtail_welcome_page.png

このページは/home/templates/home/welcome_page.htmlの内容が表示されています。
自分なりにアレンジするために、次のように変更しましょう。

/home/models.py
from django.db import models

from wagtail.core.models import Page

class HomePage(Page):
    """Home page model,"""  #👈New!(無くても今回は表示できる)

    template = "home/home_page.html"  #👈New!(無くても今回は表示できる)
/mysite/templates/home/home_page.html
{% block content %}
    こんちわっす。
{% endblock %}

templates下のhomeディレクトリは無いので、自分で作ります。
そうすれば、以下のように変わります。

homepage_mysite_こんちわっす。.png

次に、新しいフィールドを追加します。
ホームページにバナータイトルを追加しましょう。
バナータイトルとは、ホームページのタイトルを目に入りやすいように鮮やかにしたものですね。
モデルに新しくバナータイトルのフィールドパネルを追加します。


/home/models.py
from django.db import models

from wagtail.core.models import Page
from wagtail.admin.edit_handlers import FieldPanel  #新しくインポート

class HomePage(Page):
    """Home page model,"""

    template = "home/home_page.html"

    banner_title = models.CharField(max_length=100, blank=False, null=True)  #空白にしたら、データベースに空白が入り、何も表示されない。(データベースに入ることは許可はしている)

    content_panels = Page.content_panels + [  #デフォルトのパネル +
        FieldPanel("banner_title")  #このままでは、 NameError: name 'FieldPanel' is not defined ← 新しくFieldPanelをインポート or 定義する必要がある
    ]

このように、バナータイトルを定義し、パネルを追加します。
FieldPanelというパネルはwagtailのモジュールで用意されているので、そっからクラスをインポートするだけです。

しかし、これでページを更新すると、以下のようなエラーが出てきます。


OperationalError at /
no such column: home_homepage.banner_title


「バナータイトルのカラム(列)が無いよ」って言っています。
そのため、以下を実行して追加しましょう。

Ctrl + C  #サーバー停止
$ python manage.py makemigrations
Migrations for 'home':                    
  home/migrations/0003_homepage_banner_tit
    - Add field banner_title to homepage
#Pythonが管理できるように移行できた。
$ python manage.py migrate #Pythonデータベースへの移行完了

そしたら、新しくバナータイトルのパネルが追加されます。


バナータイトル追加.png


そして、htmlを次のように編集します。

/mysite/templates/home/home_page.html
{% block content %}
    {{ self.banner_title }}  {% comment %}models.pyのbanner_titleを引っ張ってくる{% endcomment %}
{% endblock %}

こうすれば、作成したバナータイトルを引っ張ってこれます。


バナータイトル反映.png


さて、次にホームページの下の色んなページを追加していきましょう。
ホームページ管理画面で、+ ADD CHILD PAGEを押してみてください。


ホームページたくさん.png


そしたら、こんな画面が出てくると思います。
ここで、何かおかしいことに気づきましたか?
そう! ホームページの子ページに、またホームページを追加しようとしています。
訳ワカメですね。
なんで、編集します。


/home/models.py
...
class HomePage(Page):
    """Home page model,"""

    template = "home/home_page.html"
    max_count = 1  #1つのホームページしか作れないようにする 👈New!
...

こうすれば、1つの階層でホームページを1つしか作れないようにできます。


@slugとは
それぞれのページのIDをURLに追加する文字列の事。
https://wordpress-dic.com/seo/wordpress-slugというURLでは、
パーマリンク:「seo/wordpress-slug」
スラッグ:「seo」と「wordpress-slug」の2つ
となります。
検索キーワードが入っており、端的で分かりやすいスラッグが良いスラッグです。(ただ、日本語のスラッグは良くないです。変な文字列に変換されちゃいます。)
参考文献〜WordPressのスラッグの意味とSEO的活用方法


③Wagtail CMS: Adding a banner and banner fields

ここでは、ページにバナーの小見出し画像を追加します。
そのために、モデルを次のように書き換えましょう。


/home/models.py
...
from wagtail.admin.edit_handlers import FieldPanel, PageChooserPanel
from wagtail.images.edit_handlers import ImageChooserPanel  #3つを新しくインポート
...
    banner_title = models.CharField(max_length=100, blank=False, null=True)
  #こっから追加👇
    banner_subtitle = RichTextField(features=["bold","italic"])  #小見出し
    banner_image = models.ForeignKey(  #外部キー,画像
        "wagtailimages.Image",  #結びつける
        null=True,
        blank=False,
        on_delete=models.SET_NULL,  #deleteしたらnullにする
        related_name="+"  #複数のフィールドで同じモデルを参照する
    )

    banner_cta = models.ForeignKey(  #他の自分て作るwagtailページとリンクさせる
        "wagtailcore.Page",  #アプリ名.モデル名
        null=True,
        blank=True,  #書かなくてもOK(オプション)
        on_delete=models.SET_NULL,
        related_name="+"
    )

    content_panels = Page.content_panels + [  #デフォルトのパネル +
        FieldPanel("banner_title"),  #NameError: name 'FieldPanel' is not defined
        FieldPanel("banner_subtitle"),  #モデル名(定義した要素)
        ImageChooserPanel("banner_image"),
        PageChooserPanel("banner_cta")
    ]
...

subtitle(小見出し)、image(画像)を新しく使いたいので、importします。
そして、モデルを変更したので、いつものごとくmakemigrationmigrateはやっといてください。
そうすれば、こんな感じになります。


wagtail画像小見出しcta.png


小見出し・画像・CTAが追加されました!


@CTAとは
Call To Action の略。
HPを訪れたユーザーに、CV(購入や資料請求)につながるアクションを起こしてもらうための要素(テキスト,画像)のことである。


④Templates and Frontend Framework

ここでは、BootstrapやCSSを使って、ページのレイアウトを整えます。
以下のように変更すればOKです。


mysite/templates/base.html
...
        {# Global stylesheets #}
        <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
{% comment %} 上記のURLはBootStrapの公式ページからコピペする {% endcomment %}
        <link rel="stylesheet" type="text/css" href="{% static 'css/mysite.css' %}">
...
{# Global javascript #}
        <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
        <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
{% comment %} 上記の3つのスクリプトはBootstrapの公式ページからコピペする {% endcomment %}
        <script type="text/javascript" src="{% static 'js/mysite.js' %}"></script>  {% comment %} 元々書いてあるこのスクリプトは順番を最後にする {% endcomment %}
        {% block extra_js %}

        {% endblock %}
    </body>
</html>

mysite/templates/home/home_page.html
{% extends 'base.html' %}

{% load wagtailcore_tags wagtailimages_tags %}  {% comment %}self.banner...を使えるようにする {% endcomment %}

{% block content %}  {% comment %} loadやblock,imageはテンプレートタグという {% endcomment %}
    {% comment %} {{ self.banner_title }}  models.pyのbanner_titleを引っ張ってくる {% endcomment %}

    {% image self.banner_image fill-400x400 as img %}   {% comment %}テンプレートタグ 外部キー (キャンバスの)大きさ as 拡張子{% endcomment %}

    <div class="jumbotron" style="background-image: url('{{ img.url }}'); background-size:contain; color:black">
        <h1 class="display-4">{{ self.banner_title }}</h1>
        <div class="lead">{{ self.banner_subtitle | richtext }}<div>
        {% if self.banner_cta %}
            <a class="btn btn-primary btn-lg" href="#" role="button">@todo</a>
        {% endif %}
    </div>
{% endblock %}

そうすれば、こんな風にきれいになります。
Learn_Wagtail_Part4.png

今回は以上です!
次回はデバッグツールバーなどを追加していきます。
⇒準備中

yinawekuky
Python(Django) ,JS(React, Vue, D3, Gatsby)でのWebアプリ開発をやっています。 GAS, SeleniumでのRPA構築も時々やります。 座右の銘:「Happy, Kind, Crazy」
future-i-mark
私たちの事業は、新しいプロダクトやサービスを創造し、様々な業種・業態における課題を解消することを目指しています。 新しい体験・最先端の技術など、社会に変革をもたらすことがミッションです。
https://future-i-mark.co.jp
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away