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

[Learn Wagtail ~ YouTube](https://www.youtube.com/playlist?list=PLMQHMcNi6ocsS8Bfnuy_IDgJ4bHRRrvub)で学習していきます。
英語が絶望的に出来ないので、字幕の自動翻訳で日本語を選択します。(なんで日本語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](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298112/b51ad735-15c0-17b0-39fc-7f3775f61f36.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](https://wagtail.io/)にアクセスして、「Get Wagtail」を選択します。
そしたら、7行のコードが載っています。
pipやpythonの環境が整っていたら、そのまま打ち込めば終わりなのですが、ここでは少し細く進めていきます。

```zsh
$ 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](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298112/f42ed56c-0674-b245-6a90-52fd59c3423c.png)

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

```zsh
$ 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 でインストール済みパッケージ一覧を確認](https://note.nkmk.me/python-pip-list-freeze/)

---

＠grepコマンドとは
grepはファイル中の文字列を検索するコマンドです。
```|```(シングルパイプ)はandのこと。
＊[参考文献〜Linuxコマンド集　 $ grep](https://eng-entrance.com/linux-command-grep)

---

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

---

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

---

#②Getting Started With Your First Home Page in Wagtail CMS
それでは、簡単にページを編集していきましょう。

まず、最初の鳥の卵のページを自分なりのページにアレンジしてみます。
鳥の卵のページってのは、これのことですね。
![wagtail_welcome_page.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298112/18d6aafc-ade3-637c-6077-d6140fd92d2e.png)

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

```python:/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!(無くても今回は表示できる)
```

```django:/mysite/templates/home/home_page.html
{% block content %}
    こんちわっす。
{% endblock %}
```

---

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

![homepage_mysite_こんちわっす。.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298112/eeb59777-9006-9836-ac26-4ae543371780.png)

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

---

```python:/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

---

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

```zsh
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](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298112/58b73d4f-be99-cd0d-3274-a7b644e4d14c.png)

---

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

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

---

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

---

![バナータイトル反映.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298112/9fd85063-0c43-fa8a-fcb1-401883a11d49.png)

---

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

---

![ホームページたくさん.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298112/2317caa4-3f8e-0467-548b-3666bb788e04.png)

---

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

---

```python:/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的活用方法](https://wordpress-dic.com/wordpress-slug#i)

---

#③Wagtail CMS: Adding a banner and banner fields
ここでは、ページにバナーの**小見出し**と**画像**を追加します。
そのために、モデルを次のように書き換えましょう。

---

```python:/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します。
そして、モデルを変更したので、いつものごとく```makemigration```と```migrate```はやっといてください。
そうすれば、こんな感じになります。

---

![wagtail画像小見出しcta.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298112/8aa6a260-e435-6114-b63d-d9e23c9d6a2c.png)

---

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

---

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

---

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

---

```django: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>
```

---

```python: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](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298112/b51ad735-15c0-17b0-39fc-7f3775f61f36.png)

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