Django 汎用ビュー入門1

##野望
汎用ビューを使って楽してテンプレートを表示させたい。

##環境
mac
python3.7.3
anaconda
vagrant 
django2.2.1
 
##やろうと思った事

まずは、
1. 汎用ビューを使って簡単にテンプレートの表示
2. 汎用ビューを使って簡単にモデル情報の表示

をやってみようと思った。


###1. 汎用ビューを使って、ただテンプレートを表示させる

事前にviewtestプロジェクトを作成し、homeというアプリを作成した。


####viewsで汎用ビューを継承したクラスを作成

TemplateViewはテンプレートをただ表示してくれる。

```viewtest/home/views.py
from django.shortcuts import render
from django.views import generic

class IndexView(generic.TemplateView):
    template_name = 'home/index.html'
    # テンプレートの場所を指定する。
```

####urlsに汎用ビューとしてURLと紐づける

```viewtest/home/urls.py
from django.urls import path
from . import views

app_name = 'home'

urlpatterns = [
    path('', views.IndexView.as_view(), name='index'),
    # views.pyのIndexViewクラスを汎用ビューとして扱うと示す。
]

```

####簡単なテンプレHTML

```viewtest/home/templates/home/base.html
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="utf-8">
    <title>view test</title>
</head>
<body>

{% block content %}
{% endblock %}

</div>
</body>
</html>
```

####テンプレを継承しとりあえず表示させるページ

```viewtest/home/templates/home/index.html
{% extends 'home/base.html' %}

{% block content %}
<p>this is index.html</p>
{% endblock %}
```


###テンプレートに引数を渡したい時

汎用ビュー無しだと辞書で引数を渡していたけど、
汎用ビューは既存のメソッドをオーバーライドして引数を渡す。

```viewtest/home/views.py
from django.shortcuts import render
from django.views import generic

class IndexView(generic.TemplateView):
    template_name = 'home/index.html'

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context["poko"] = "this is poko"
        context["tin"] = "this is tin"
        return context
    # このメソッドが引数を渡してくれる。
```

これで、テンプレート内で{{ poko }}とか記載すればで表示出来る。







###2. 汎用ビューを使って簡単にモデル情報の表示

ListViewを継承すればモデルの情報を一覧表示してくれる。
今回は簡単なUser情報を含んだモデルを作成し、表示する。

まずはモデルを作成して〜
事前に管理画面やらシェルでテストユーザーを作成。

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


class User(models.Model):  

    username = models.CharField(
        null=True,
        default='',
        max_length=20)


    SEX_CHOICES = (
        (
            ('male', '男'),
            ('female', '女'),
            ('hentai', '...')
        ))
    # データベース上ではローマ字で登録される。


    sex = models.CharField(
        verbose_name="sex",  
        # 管理画面の表示名。verbose_name_pluralで指定すればsが付かなくなる。
        max_length=6,
        choices=SEX_CHOICES)

    created_at = models.DateTimeField(auto_now_add=True)
    # auto_now_addは作成時の時間を追加


    updated_at = models.DateTimeField(auto_now=True)
    # auto_nowは作成時と更新時の時間を追加


    def __str__(self):
        return self.username
    # User Objectとか表示されずに、usernameが表示される

```


ListViewを継承して〜

```viewtest/home/views.py
...
from .models import User

...
class UsersView(generic.ListView):  #クラス名は~Viewじゃなくてもいいみたい
    model = User
    # モデルを指定

    paginate_by = 3
    # 1ページに3件だけ表示させる

    ordering = ['age']
    # 若い順に並べる ['-age']で降順。
    # get_queryset()をオーバーライドしたり、queryset=とかで指定してもOK

    template_name = 'home/users.html'
    # テンプレートを指定
```

URLと紐付けて〜

```viewtest/home/urls.py
...

urlpatterns = [
    ...
+   path('users/', views.UsersView.as_view(), name='users'),
]
```

表示させるテンプレートを作成し〜終了

```viewtest/home/templates/home/users.html
{% extends 'home/base.html' %}

{% block content %}
<h1>Users</h1>

<ul>
    {% for user in object_list %}
    <!-- viewでmodel指定したものが、object_listで渡ってくる。 !-->

        <li><p>{{ user.username }} - {{ user.sex }} ({{ user.age }})</p></li>

    {% empty %}
    <!-- 空だったら !-->

        <li><p>No Users</p></li>

    {% endfor %}
</ul>
{% endblock %}
```

<br>


#結果

汎用ビュー便利すぎて興奮してきた。


<br>