Wagtailチュートリアル 13 Orderableなページを作ろう

#Wagtailチュートリアル 13
<=[12 DB Browserを使おう](https://qiita.com/tagawahirotaka/items/aa0bbc341ec73ea5fcf5)
=>[14 SNSをうめこもう]
(https://qiita.com/tagawahirotaka/items/3908dc5ffea6e02f6049)
##Orderableなページを作ろう

29,30

```python:home/models.py

from django.db import models #⓪ モデルをインポート

from modelcluster.fields import ParentalKey # 29 インポート

from wagtail.core.models import Page ,Orderable#⓪ページをインポート、29 Orderableを追加
from wagtail.core.fields import RichTextField #⑧ RichTextFieldをインポート
from wagtail.admin.edit_handlers import FieldPanel,MultiFieldPanel,InlinePanel,PageChooserPanel #④ FieldPanelをインポート 11 29 必要なものをインポート
from wagtail.images.edit_handlers import ImageChooserPanel #11 必要なものをインポート
# 27 インポート
from wagtail.admin.edit_handlers import FieldPanel,StreamFieldPanel
from wagtail.core.fields import StreamField
from streams import blocks 


# 29 追加
class HomePageCarouselImages(Orderable):

    page = ParentalKey("home.HomePage", related_name="carousel_images")
    carousel_image = models.ForeignKey(
        "wagtailimages.Image",
        null=True,
        blank=False,
        on_delete=models.SET_NULL,
        related_name="+",
    )

    panels = [
        ImageChooserPanel("carousel_image"),
        ]


class HomePage(Page):#⓪ページを引数に

    templates = "home/home_page.html" #① wagtailtutorial/templates/home/homepage.html

    max_count = 1 #⑥ ADD CHILD PAGEを制限

    banner_title = models.CharField(max_length=100, blank=False, null=True) #③ banner_titleを定義

    banner_subtitle = RichTextField(features=["bold", "italic"]) #⑧banner_subtitleを定義

    banner_image = models.ForeignKey( #⑨banner_imageを定義
        "wagtailimages.Image",
        null=True,
        blank=False,
        on_delete=models.SET_NULL,
        related_name="+"
    )

    banner_cta = models.ForeignKey( #⑩banner_ctaを定義
        "wagtailcore.Page",
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name="+"
   )
   
   # 27 flex/models.py のcontentをコピーして必要なctaだけ残す
    content = StreamField(
        [
            ("cta", blocks.CTABlock()),
        ],
        null=True,
        blank=True,
    )

    content_panels = Page.content_panels + [ #④ 11 admin画面に追加
        MultiFieldPanel([ # 30 変更
            FieldPanel("banner_title"),
            FieldPanel("banner_subtitle"),
            ImageChooserPanel("banner_image"),
            PageChooserPanel("banner_cta"),
        ],heading="Banner Options"),
        MultiFieldPanel([ #30 追加
            InlinePanel("carousel_images",max_num=5,min_num=1,label="Image"),# 29 追加
        ], heading="Carousel Images"),
        StreamFieldPanel("content"), # 27 flex/models.py のcontentをコピー
    ]

    class Meta:

        #verbose_name = "OH HELLO WORLD" ⑦ ADD CHILD PAGEでの表記
        verbose_name = "Home Page"
        verbose_name_plural = "Home Pages"
```

31

```html:wagtailtutrial/templates/home/home_page.html

{# 13 bootstrapを読み込む#}
{% extends "base.html" %}
{% load wagtailcore_tags wagtailimages_tags %}

{% block content %} {#② base.htmlから引っ張り出す#}

{% image self.banner_image fill-900x400 as img %}{# 13 画像を読み込む#}

{# 13 bootstrapからコピペしてmodels.pyで定義したやつを埋める #}
 <div class="jumbotron" style="background-image: url('{{ img.url }}'); background-size: contain; color: #fff !important">
        <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>

{# 31 bootstrapからコピペ#}
<div id="carouselExampleControls" class="carousel slide" data-ride="carousel">
  <div class="carousel-inner">
      {% for loop_cycle in self.carousel_images.all%}
        {% image loop_cycle.carousel_image fill-900x400 as img %}
        <div class="carousel-item {% if forloop.counter == 1 %}active{% endif%}">
            <img src="{{img.url}}" class="d-block w-100" alt="{{img.alt}}">
        </div>
      {% endfor %}
  </div>
  <a class="carousel-control-prev" href="#carouselExampleControls" 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="#carouselExampleControls" role="button" data-slide="next">
    <span class="carousel-control-next-icon" aria-hidden="true"></span>
    <span class="sr-only">Next</span>
  </a>
</div>



{# 28 追加 wagtailtutrial/templates/flex/flex_page.htmlからコピー#}
{% for block in page.content %}
      {% include_block block%} {# 19 streams/block.pyのcontentをループする#}
{% endfor %}

{% endblock %}
```

29
<img width="1440" alt="スクリーンショット 2019-08-28 08.39.32.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/402245/e5c2783c-b31d-06ca-2721-0570308f033b.png">

30
<img width="1440" alt="スクリーンショット 2019-08-28 08.47.36.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/402245/4b07eebb-28f6-8c4c-36bd-f92d65a496eb.png">

31
<img width="1440" alt="スクリーンショット 2019-08-28 09.09.41.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/402245/17e16cc5-e5de-1a4b-558e-3cb1c03b97ce.png">