【Django】Build web apps　～4章：Templates・Static filesとサイト設計～

## Templates
～～ヾ(＾∇＾)こんにちは～

以前の記事にDjangoウェブサイトアプリのモデルとデータベースについて勉強できましたね
続いて今日はウェブサイトのテンプレートを学びに行こうと思います

HTMLを動的に生成する必要である為、最も一般的なアプローチはテンプレートに依存しています
テンプレートには目的のHTML出力の静的部分と動的コンテンツの挿入方法を説明する特別な構文が含まれています

テンプレートを使うDjangoプロジェクトは１つ又は複数のテンプレートエンジンで構成できます
Djangoには**Djangoテンプレート言語（DTL）**と一般的な代替**Jinja2**の組み込みバックエンドが付属しています

### テンプレートエンジンのサポート
Djangoで使用されるすべてのテンプレートエンジンの設定を含むリストは**setting.py**にてデフォルトTEMPLATES変数で構成されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581348/1764eaf3-4fab-7296-3771-f419c336eee3.png)

### 簡単にテンプレート使ってみよう
まず、アプリケーション内に**templates**フォルダ（固定名）を作成してここにてテンプレートファイルを準備しておきます

```ruby:templates
myproject
├── myproject
├── myapp
├── manage.py
└── templates
    └── food
        ├── index.py
        └── detail.py
```

#### index.html
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581348/a4482a61-85e8-ba36-d469-5eee2056e607.png)
ここまで静的部分のみがあるテンプレートを作成しました、次はテンプレートを使うviews.pyを修正します
ポイントは**render**メソッドです
#### views.py

```ruby:food/views.py
from django.shortcuts import render
from django.http import HttpResponse
from .models import Item

# Create your views here.
# index.html
def index(req):
    template_name = "food/index.html";
    context = {}
    return render(req, template_name, context)
```
renderメソッドを読んでDjangoはtemplatesフォルダにtemplate_nameを探して見つかったファイルにcontextをアプローチした後テンプレートを表すという流れの処理です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581348/81ff443b-5b86-5695-4514-a0fe948f7fef.png)

#### Contextをアプローチする方法とは
**context変数の値を編集します**

```ruby:food/views.py
from django.shortcuts import render
from django.http import HttpResponse
from .models import Item

# Create your views here.
# index.html
def index(req):
    template_name = "food/index.html";
    context = {
        'title': 'Index',
        'item_list': Item.objects.all()
    }
    return render(req, template_name, context)
```
**テンプレートを編集します**
Djangoテンプレート言語と利用します、詳しくは[「Django template language」]
(https://docs.djangoproject.com/en/3.0/ref/templates/language/)を参考してね
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581348/8172a0a2-69c4-eb7e-c98b-bf60c3efece0.png)
注意、
目的なページにcontextオブジェクトのキーを呼びます。又は各テンプレートに同じblock名を2つ以上持つとは行きません

```ruby:異常
<!-- block content1 -->
{% block content %}
...
{% endblock %}

<!-- block content2 -->
{% block content %}
...
{% endblock %}
```

```ruby:正常
<!-- block head -->
{% block head %}
...
{% endblock %}

<!-- block content -->
{% block content %}
...
{% endblock %}
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581348/b912a875-71b5-73d0-52fa-d406b7281861.png)

#### detail.html
ほぼ同じルールで*detail.html*ファイルを編集しましょ
動く順番は、index.htmlにて対象なitemを選らんでitemの詳しく情報を持つdetail.htmlが表せます
このでHTMLの知識が必要ですので準備しておいてね
それではやろう

:information_desk_person_tone2:**index.htmlを編集します**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581348/8b240e18-62ca-72de-3aac-1c7523fe20fe.png)
こういう風に同じdetail.htmlファイルを呼びますが異なるdetail.html URLがあり、item_idにようって情報が自動的に変るというテンプレートエンジンの特徴です
URLは `http://localhost:8000/food/[item_id]/`
覚えてますか2章にページを呼び出すのを解説しますたが忘れたら[「2章：ViewsとURL Patterns」](https://qiita.com/huong/items/22ef5de404a6f823602b#%E5%8B%95%E3%81%8D%E3%81%AE%E8%AA%AC%E6%98%8E)を参考してね

:information_desk_person_tone2:**urls.pyを編集します**

```ruby:food/urls.py
from . import views
from django.urls import path

urlpatterns = [
    # index.html
    path('', views.index, name='index'),
    # 
    path('item/', views.item, name='item'),
    # detail.html
    path('<int:item_id>/', views.detail, name='detail')
]
```

:information_desk_person_tone2:**views.pyを編集します**

```ruby:food/views.py
from django.shortcuts import render
from django.http import HttpResponse
from .models import Item

# detail.html
def detail(req, item_id):
    template_name = "food/detail.html"
    context = {
        'item': Item.objects.get(pk=item_id)
    }
    return render(req, template_name, context)
```

:information_desk_person_tone2:**detail.htmlを編集します**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581348/c49822e7-d171-23d5-4c41-a121c0089a0a.png)

結果を見よう
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581348/1c18d73c-948d-4d33-13ae-aeb6f5f57749.png)


### URLsにあるNameとApp_name

#### Nameを使います
```ruby:food/urls.py
urlpatterns = [
    # detail.html
    path('<int:item_id>/', views.detail, name='detail')
]
```
**index.html**を修正します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581348/78c31677-c26f-3eda-9f2f-8a66ae3deb7e.png)
`{% url 'name' variable %}`

#### App_nameを使います
```ruby:food/urls.py
app_name = 'food'
urlpatterns = [
    # detail.html
    path('<int:item_id>/', views.detail, name='detail')
]
```
**index.html**を修正します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581348/0ee11f49-12da-7499-114b-311a928494d2.png)
`{% url 'app_name:name' variable %}`

## Staticファイル
### Staticファイルとは
Webサイトは通常にimage、js、cssなどの追加ファイルを提供する必要があります。Djangoでは、これらのファイルを「静的ファイル」と呼びます

**Staticファイルの管理を支援するを確認します**
*settings.py*ファイルにあるINSTALLED_APPS変数の値は`django.contrib.staticfiles`があります
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581348/cc4a7d1c-f6c5-c796-f66b-13c9ee6034d0.png)

**StaticファイルへディレクトリーURLを確認します**
*settings.py*ファイルにあるSTATIC_URL変数の値は`/static/`があります
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581348/b5f356ba-3197-398b-9b74-1f3fccb1ff52.png)
つまり、静的ファイルは`static`フォルダに置くべきです

### Staticファイルの利用方法
以下のようにstaticファイルを準備しておきましょ

```ruby:static
myproject
├── myproject
├── myapp
├── manage.py
├── templates
└── static
    └── myapp
        └── css
            └── body.css
```

```ruby:body.css
body {
    background-color: rgb(198, 233, 235);
}
```

**Staticファイルを呼び出します**
テンプレートに指定するstaticファイルのULRを作成します
`{% static "static fileのULR" %}`

```ruby:テンプレート
{% load static %}
<link rel="stylesheet" href="{% static "/food/css/body.css" %}"/>
```

**結果を確認します**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581348/b8ea30cd-a7e4-6473-b757-2fc1fcc88115.png)
staticファイルを利用するテンプレートが作成されましたよね
最も分かれば[Managing static filesサイト](https://docs.djangoproject.com/en/2.2/howto/static-files/)をご参考下さい

## サイトをデザインします
### ページの構成
簡単なページにはを3つに分割されています

```ruby:page.html
page.html
├── head
├── body
└── footer
```
で、共通部分を別のページを置いて各ページにそのページを購入するというイメージです

```ruby:templates
templates
└── food
    ├── base.html  # (head・footer部分があり)
    └── page.html  # (body部分のみ)
```
実際はどういう風に構成しますか、以下のように御覧ください

**共通ページの仕組み**

```ruby:base.html
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<!-- ヘッダーのコンテンツはここに記述します -->
</head>

{% block body %}
{% endblock %}

<footer>
<!-- フッターのコンテンツはここに記述します -->
</footer>
</html>
```

**各ページの仕組み**

```ruby:page.html
{% extends 'food/base.html' %}
<body>
    {% block body %}
    <!-- ボディのコンテンツはここに記述します -->
    {% endblock %}
</body>
```
`{% extends 'template fileのURL' %}`

では、試してみよう～
### Bootstrapを使おう
サイトは綺麗で早く作れるため、フロントエンドフレームワークを使いましょ～
この記事は**Bootstrap**フレームワークを使って行ないます
[Bootstrapをダウンロードするページ](https://getbootstrap.com/docs/4.4/getting-started/download/)にて*BootstrapCDN*のダウンロードはCSSとJSダウンロードリンクをコピーします

```ruby:BootstrapCDN
<link rel="stylesheet" 
href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" 
integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" 
crossorigin="anonymous">
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" 
integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" 
crossorigin="anonymous"></script>
```
コピーしたリンクは**base**テンプレートファイルにペーストします
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581348/9af0880a-db9c-73ce-3feb-41ca34f2e897.png)
これから[Bootstrapさん](https://getbootstrap.com/docs/4.4/components/alerts/)を提供するCSSとJSファイルを利用できます

### Base.htmlを作成
headタグにて[Navコンポネント](https://getbootstrap.com/docs/4.4/components/navs/)を作成します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581348/cd32ce54-f0a5-53e2-b8d0-dbe664a51016.png)
### 各ページを編集します
**index.html**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581348/d26d3deb-4ad0-e0a0-dd4e-b6e91e1370f1.png)

**detail.html**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581348/f9a7d2fe-c228-19bd-b2ab-85ee119f64b6.png)

**結果を確認します**
indexページ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581348/3de504db-1e30-a724-f9db-25ece744204b.png)

detailページ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581348/15ba620b-e047-1b70-8a36-d8f09dcfbb1a.png)

## お疲れ様です
此処まで御覧いただきまして有難うございます

**参考サイト**
[・Django template language]
(https://docs.djangoproject.com/en/3.0/ref/templates/language/)
[・Django support for template engines](https://docs.djangoproject.com/en/3.0/topics/templates/#engine)
[・Jinja2](https://palletsprojects.com/p/jinja/)

**関連記事**
[・【Django】Build web apps　～3章：Modelsとデータベース～](https://qiita.com/huong/items/8a722bc8894f2a8c28d1)
[・【Django】Build web apps　～5章：Forms～](https://qiita.com/huong/items/)
[・【Django】Build web apps　～使ったコマンド～](https://qiita.com/huong/items/cfcb338db55957925e39)