脳死で覚えるDjango入門

# 前書き

>　***全てのプログラマーは写経から始まる。 by俺***

良質な写経元を提供するためにあります。 

**無駄のないコード**と**無駄のない説明**を用意したつもりです。

**Djangoを忘れかけた時に立ち返られる原点**となれば幸いです。

# 実行環境
- python (3.6.8)
- Django (2.1.7)

# すること
Webアプリ制作練習の王道、Todoアプリを作ります。(データベースにはMySQLを使います。)

# (1) install
pipとか意味わかんないって人は知りません。

・django

```command
$ pip install django
```

・MySQL
mac以外の人は自分で調べてください。(ごめん)

```command
$ brew install mysql
$ pip install pymysql
```

# (2) プロジェクトの生成
自分で名前を決めるところは<>で表記します。

```command
$ django-admin startproject <project_name>
```

今回では、

```command
$ django-admin startproject todo_project
```

とした。

(注)`<project_name>`にハイフンは使えません。

# (3) 確認

```command
$ python manage.py runserver
```

ロケットが出てきましたか?

# (4) アプリの作成
Djangoでは、プロジェクトの中にアプリを作るという考え方を採用している。

```command
python manage.py startapp <app_name>
```

今回では、

```command
python manage.py startapp todo
```

とした。

# (5) アプリの登録
Djangoでは、アプリをプロジェクトに登録する必要がある。

`<project_name>/<project_name>/settings.py`にINSTALLED_APPSというリストがある。

そこに`todo.apps.TodoConfig`を追加する。

```settings.py
INSTALLED_APPS = [
    'todo.apps.TodoConfig',
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]
```

# (6) index.htmlを表示する。
`ローカルホスト名`というURLを叩くとindex.htmlが表示されるようにする。

(`ローカルホスト名`ってのは`http://127.0.0.1:8000/`みたいなやつです。サーバーを立ち上げたときにターミナルに記述されているはずです。)

そのためには以下の手順を踏む。
1. index.htmlを作る
2. viewsを設定
2. アプリのルーティングを設定
3. プロジェクトのルーティングを設定

## 1. index.htmlを作る
`<project_name>/<app_name>/`に`templates`というフォルダを作り、その中に'todo'というフォルダを作り、その中に`index.html`というファイルを作る。

今回では、

- todo_project
  - todo_project
  - db.sqlite3
  - manage.py
  - todo
     - 色々
     - temlates / todo / index.html ←こいつ

こんな感じになる。

中には適当に

```index.html
Hello
```

とか書いておいてください。

## 2. viewsを設定
railsでいうcontrollerの部分。

ルーティングで呼び出すための関数を定義しておく。

`<project_name>/<app_name>/views.py`を下のように編集する。

```views.py
from django.shortcuts import render

# Create your views here.
def index(request):
    return render(request, 'todo/index.html')
```

## 3. アプリのルーティングを設定
`<project_name>/<app_name>`の中に`urls.py`を作成する。

今回では、

- todo_project
  - todo_project
  - db.sqlite3
  - manage.py
  - todo
     - 色々
     - urls.py ←こいつ

それを下のように編集する。

```todo/urls.py
from django.urls import path
from . import views

urlpatterns = [
    path('', views.index, name='index')
]
```

一見、これで`ローカルホスト名`のURLを叩けばviewsの中のindex関数を実行し、index.htmlを表示してくれそう...

でも、Djangoではプロジェクトのルーティングを設定する必要がある。

## 3.プロジェクトのルーティングを設定

`<project_name>/<project_name>`の中に`urls.py`が既に存在している。

今回では、

- todo_project
  - todo_project
     - 色々
     - urls.py ←こいつ
  - db.sqlite3
  - manage.py
  - todo


それを下のように編集する。

```todo_project/urls.py
"""todo_project URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/2.1/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  path('', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  path('', Home.as_view(), name='home')
Including another URLconf
    1. Import the include() function: from django.urls import include, path
    2. Add a URL to urlpatterns:  path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('todo.urls'))
]
```

これで、サーバーを立ち上げるとHelloと出力されるはずです。

# (7) データベースの設定

mysqlを立ち上げる。

```command
$ mysql -u root
```

データベースを作る。

```command
create database <database_name>;
```

今回は、

```command
create database mydb;
```

とした。

次にDjangoに設定をする必要がある。

`<project_name>/<project_name>/settings.py`の`DATABASES`の部分を下のように編集する。

```settings.py
# Database
# https://docs.djangoproject.com/en/2.1/ref/settings/#databases

import pymysql
pymysql.install_as_MySQLdb()

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'mydb',
        'USER': 'root',
        'PASSWORD': '',
        'HOST': '',
        'PORT': ''
    }
}
```


# (8) モデルの作成

ここからはTodoアプリの制作に入りますので、ディレクトリの説明の時、`<project_name>`という抽象的な言い方はせず、`todo_project`と書いていきます。

`todo_project/todo/models.py`を下のように編集する。

```models.py
from django.db import models

# Create your models here.
class Post(models.Model):
    body = models.CharField(max_length=200)
```

# (9) マイグレーションファイルの作成

```command
$ python manage.py makemigrations <app_name>
```

今回では、`<app_name>`は`todo`なので、

```command
$ python manage.py makemigrations todo
```

となる。

すると、`todo_project/todo/migrations`に`0001_initial.py`が作成される。そのファイルには先ほど定義したPostモデルをデータベースに作成するコードが書かれている。

# (10) マーグレーションファイルの実行

```command
$ python manage.py migrate
```

# (11) 管理ページ
Djangoには超絶便利な管理ページが用意されている。

管理画面から先ほど作成したデータベースを確認します。

```command
$ python manage.py createsuperuser
```

このコマンドを実行すると、いくつかの質問が与えられる。

`username`や`password`を自分で登録しましょう。

ローカルサーバーを立ち上げ、

```command
$ python manage.py runserver
```


`ローカルホスト名/admin`というURLを打ち込みましょう。



すると、

<img width="538" alt="スクリーンショット 2019-03-30 22.03.07.png" src="https://qiita-image-store.s3.amazonaws.com/0/221435/fbcb88b9-10bb-ee39-56e2-fc7a06df6797.png">

このように、管理ページが表示されます。

先ほど入力した`username`と`password`を入力しましょう。

すると、

<img width="762" alt="スクリーンショット 2019-03-30 22.06.09.png" src="https://qiita-image-store.s3.amazonaws.com/0/221435/ae44c2f3-fdbc-0700-51e6-e89ccaa358b7.png">

このような管理画面が表示されます。

この画面からデータベースのデータを見たり、追加したりすることができます。

まだ今の状態では、管理画面から先ほどのPostモデルを見ることができません。

見られるようにするために、`todo_project/todo/admin.py`を下のように編集します。

```admin.py
from django.contrib import admin
from .models import Post

# Register your models here.
admin.site.register(Post)
```

これでPostモデルも見られるようになったはずです。

<img width="762" alt="スクリーンショット 2019-03-30 22.09.46.png" src="https://qiita-image-store.s3.amazonaws.com/0/221435/e5acac63-b48c-792b-6a57-57a11e3c105e.png">

# (12) ルーティングの実装

下表のようなルーティングを実装します。

|メソッド|パス名|説明|
|:--|:--|:--|
|GET|/|Todoリスト一覧表示|
|POST|/create|Todo追加|
|POST|/`<int:id>`/delete|Todos削除|

`todo_project/todo/urls.py`を下のように編集する。

```urls.py
from django.urls import path
from . import views

urlpatterns = [
    path('', views.index, name='index')
    path('create', views.create, name='create'),
    path('<int:id>/delete', views.delete, name='delete')
]
```

`views.py`に`create`関数や`delete`関数はまだ未定義ですので、お使いのエディタさんがおこおこするかもしれません。

# (13) Formクラスを実装

`todo_project/todo`に`forms.py`を作成し、下のように編集しましょう。

```forms.py
from django import forms
from .models import Post

class PostForm(forms.ModelForm):
    class Meta:
        model = Post
        fields = ('body', )
```

# (14) viewsを実装

`todo_project/todo/views.py`を下のように編集しましょう。

```views.py
from django.shortcuts import render, get_object_or_404
from django.http import HttpResponse, HttpResponseRedirect
from django.urls import reverse
from .models import Post
from .forms import PostForm

# Create your views here.
def index(request):
    posts = Post.objects.all()
    form = PostForm()
    context = {'posts': posts, 'form': form}
    return render(request, 'todo/index.html', context)

def create(request):
    form = PostForm(request.POST)
    form.save(commit=True)
    return HttpResponseRedirect(reverse('index'))

def delete(request, id=None):
    post = get_object_or_404(Post, pk=id)
    post.delete()
    return HttpResponseRedirect(reverse('index'))
```

これで、ルーティングで呼び出される関数の実装が完了しました。また、index.htmlの中で、テンプレートシステムを使うことで、`context`などの変数を扱うことができます。

# (15) base.htmlの作成と実装

`index.html`と同じディレクトリに`base.html`を用意します。

(`todo_project/todo/templates/todo`の中です。)

`base.html`を下のように編集します。

```base.html
{% load staticfiles %}
<!DOCTYPE html>
<html>
    <head>
        <title>Todo list</title>
    </head>
    <body>
        <div class="container">
            {% block content %}
            {% endblock %}
        </div>
    </body>
</html>
```

# (16) index.htmlの実装

`index.html`を下のように編集する。

```index.html
{% extends 'todo/base.html' %}
{% block content %}
    <h1>Todo List</h1>
    <form action="{% url 'create' %}" method="POST">
        {{ form.body }}
        <input type="submit" value="追加">
        {% csrf_token %}
    </form>
    <h2>Current Todos</h2>
    <table>
        <thead>
            <th>Todos</th><th>&nbsp;</th>
        </thead>
        <tbody>
            {% for post in posts %}
               <tr>
                   <td>
                   <div>
                       {{ post.body }}
                   </div>
                   </td>
                   <td>
                       <form action="{% url 'delete' post.id %}" method="post">
                           {% csrf_token %}
                           <button>Delete</button>
                       </form>
                   </td>
               </tr>
            {% endfor %}
        </tbody>
    </table>
{% endblock %}
```

すると、

<img width="770" alt="スクリーンショット 2019-03-30 23.34.37.png" src="https://qiita-image-store.s3.amazonaws.com/0/221435/c97f7bb6-dc7b-e2ff-10cf-3c1468cec1a4.png">

めでたくTodoリストアプリが完成します。

# 自己紹介

冒頭に書くと邪魔になるので最後にひっそりと自己紹介させてください。

<img src="https://qiita-image-store.s3.amazonaws.com/0/221435/16727490-2b41-4318-cc25-e2601479e77a.jpeg" width=30%>

|名前|綿岡晃輝|
|:--|:--|
|職業|大学院生 (2019年4月から)|
|分野|機械学習, 深層学習, 音声処理|
|Twitter|[@Wataoka_Koki](https://twitter.com/Wataoka_Koki)|

Twitterフォローしてね！