素人基盤エンジニアがDockerでDjangoを触るシリーズ⑤：View, Template, CSS

# TL;DR
[素人基盤エンジニアがDockerでDjangoを触るシリーズ④：urls.py](https://qiita.com/LittleGreenMen/items/5f3325b94ceef48b7270)の続き。
１から読みたい場合は↓こちら。
[素人基盤エンジニアがDockerでDjangoを触るシリーズ①：DockerでDjangoを作る](https://qiita.com/LittleGreenMen/items/660c27669214da1c9613)
今回も[Django Girls](https://tutorial.djangogirls.org/ja/)のサンプルを作りながらdjangoと戯れる。
viewでは、modelを介して受け取ったデータをTemplateに渡したり、その他処理を行うことができる。
Templateは見た目を整える部分。htmlやCSSなどはこのTemplateにあたる。
まずは、シンプルなViewを作ることでその構造を見ていく。

# view
### ①views.pyを編集する
#### views.py
```python:views.py
from django.shortcuts import render
from django.utils import timezone
from .models import Post

def post_list(request):
    posts = Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date')
    return render(request, 'blog/post_list.html', {'posts': posts})
```

#### よくわかる解説

```python
from django.shortcuts import render
```
shortcuts関数は、DjangoにおけるMTVの各レベルを橋渡しするのに必要な関数やクラスを定義している。今回は、引数として指定したtemplateをレンダしてHttpResponseを返すrenderという関数をインポートしている。

```python
from django.utils import timezone
from .models import Post
```
ユーティリティ関数に含まれている時間に関する機能を提供するtimezoneと、モデルの作成の時に作成したPostのモデルをインポートしている。Viewの立ち位置については第二回の時にも触れたが、モデル関数を利用して実際にデータを取得し、Templateに渡す役割もあるので、利用したいモデルはViewの中でインポートし、Templateのオプションとして引き渡す必要がある。

```python
def post_list(request):
    posts = Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date')
    return render(request, 'blog/post_list.html', {'posts': posts})
```
post_list関数の定義部分。前回のurls.pyを記述した際に、`views.post_list`を指定したのは覚えているだろうか。urls.pyへリクエストが来た際に、パスに応じて指定したviews.pyの中の関数が呼び出されリクエストが転送される。そして、必要な処理を行った後にTemplateをレンダリングしてレスポンスを返すということである。二行目では、Postモデルを使ってpublished_dateが現在の時間よりも前の投稿を取得し、新しい順に並び変えた上で`blog/post_list.html`に渡している。

# Template
### ①html用のディレクトリを作成する
```shell
cd ~/blog/template
mkdir blog
```
アプリケーションのディレクトリであるblogディレクトリの下に、templateというディレクトリがあるので、その下にさらにblogというディレクトリを作成する。
なぜこんなややこしい構造にするのかと思うかもしれないが、大規模なアプリケーションを管理しようとするとhtmlに関しても機能ごとにディレクトリを分けておいたほうがよいらしい。

### ②post_list.htmlを編集する
#### post_list.html
```html:blog/template/blog/post_list.html
{% load static %}
<html>
    <head>
        <title>Django Girls blog</title>
        <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
        <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap-theme.min.css">
        <link rel="stylesheet" href="{% static 'css/blog.css' %}">
    </head>
    <body>
        <div class="page-header">
            <h1><a href="/">Django Girls Blog</a></h1>
        </div>

        <div class="content container">
            <div class="row">
                <div class="col-md-8">
                    {% for post in posts %}
                        <div class="post">
                            <div class="date">
                                <p>published: {{ post.published_date }}</p>
                            </div>
                            <h2><a href="">{{ post.title }}</a></h2>
                            <p>{{ post.text|linebreaksbr }}</p>
                        </div>
                    {% endfor %}
                </div>
            </div>
        </div>
    </body>
</html>
```
HTMLの基本的な部分を解説するのは主旨とずれるので、ここでは重要な部分のみを解説する。

#### よくわかる解説
```html
{% load static %}
```
{% load static %}は後述するCSSファイルのような、静的コンテンツを読み込むための記述。

```html
        <link rel="stylesheet" href="{% static 'css/blog.css' %}">
```
ここで読み込むCSSを指定している。

```html
                    {% for post in posts %}
                        <div class="post">
                            <div class="date">
                                <p>published: {{ post.published_date }}</p>
                            </div>
                            <h2><a href="">{{ post.title }}</a></h2>
                            <p>{{ post.text|linebreaksbr }}</p>
                        </div>
                    {% endfor %}
```
この部分で注目したいのは、{{ post.OBJECT }}でPostモデルの項目を指定している部分。Postモデルを利用して取得した投稿に関しては、前述したviews.pyの中でこのTemplateに渡されているため、このように簡単に呼び出せるということだ。Postモデルで取得した投稿はリストの形になっているため、for文を利用して複数の表示を実現することもできる。

### ③CSS用のディレクトリを作成する
```shell
cd ~/blog/static
mkdir css
```

### ④blog.cssを編集する
```css:blog/static/css/blog.css
.page-header {
    background-color: #C25100;
    margin-top: 0;
    padding: 20px 20px 20px 40px;
}

.page-header h1, .page-header h1 a, .page-header h1 a:visited, .page-header h1 a:active {
    color: #ffffff;
    font-size: 36pt;
    text-decoration: none;
}

.content {
    margin-left: 40px;
}

h1, h2, h3, h4 {
    font-family: 'Lobster', cursive;
}

.date {
    color: #828282;
}

.save {
    float: right;
}

.post-form textarea, .post-form input {
    width: 100%;
}

.top-menu, .top-menu:hover, .top-menu:visited {
    color: #ffffff;
    float: right;
    font-size: 26pt;
    margin-right: 20px;![006.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/369619/5f4c27cb-8697-0236-f655-2ec2beaf3805.png)

}

.post {
    margin-bottom: 70px;
}

.post h2 a, .post h2 a:visited {
    color: #000000;
}
```
CSSの解説についてはさらに本筋ではないので、形を整えるためにはこんなものを書くんだというくらいの認識でコピペいただければと思う。HTML, CSSに関してはそれ専用の本などで勉強されることをお勧めする。

# ブログ表示用サイトの起動
### docker-compose up
ここまでで、(表示をするのみだが)webサイトが完成しているはずである。
dockercompose.yamlが配置されているディレクトリまで移動して、`docker-compose up`を使って実際に起動してみよう。

```shell
docker-compose up
```
http://[IPADDRESS]:8000/にアクセスしてみる。

![006.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/369619/0a5e8f03-70bb-0b1b-2cf2-ce6b1c943270.png)

表示された！
ちなみにThis is test postという投稿は、第三回で説明したadminページを利用して投稿したもの。ユーザがポストを行うには、投稿フォームを備えたページを作成する必要がある。フォームを作成するにあたって、Djangoはformsという便利な機能を提供している。その話はまた次回。

まずは一区切りといった感じだろうか。。

つづく