Django 事始め

# Django
DjangoでWeb Applicationを構築するまでのチュートリアルにそって実現した基本的な流れをメモして行きます。MacOS Sierra 10.12.6で作業をしておりますので、それ以外の環境の方はご参考にならず申し訳ありません。

Djangoの特徴としては、アプリケーション開発に必要なものが全て含まれたフルスタックであることが上げられると思います。Djangoの構成としては以下になります。

<img width="539" alt="スクリーンショット 2018-05-06 10.11.32.png" src="https://qiita-image-store.s3.amazonaws.com/0/85182/92f214bc-24fa-c133-8514-de82f43050d2.png">

HTTP Requestに対して、URLのパスに対応したViewを呼び出し、ViewがModelからデータを取り出しTemplateで整形したWebページをHTTP Responseで返すのが基本的な構成になります。

ModelのDatabaseとのアクセスにはORM(Object-relational mapping)が利用されており、SQLを記述しなくともデータベースとのやりとりが可能です。

# 環境整備
https://docs.djangoproject.com/ja/1.9/intro/tutorial01/

pipでDjaangoをインストールします。

```bash
$ pip install django
```
インストールされたDjangoのバージョンを確認しておきます。

```bash
$ python -m django --version
2.0.5
```
Djangoはプロジェクトの中に複数のアプリケーションを持つ形になります。まずはプロジェクトを作成します。

```bash
$ django-admin startproject mysite
$ cd mysite

mysite/
    manage.py
    mysite/
        __init__.py
        settings.py
        urls.py
        wsgi.py
```
開発用サーバーを起動して、http://127.0.0.1:8000/ にアクセスしてDjangoのページが表示されれば環境は整備されました。

```bash
$ python manage.py runserver
```
# 最初のアプリケーションの作成
アプリケーションの作成は、manage.pyを用いて行います。

```bash
$ python manage.py startapp polls
polls/
    __init__.py
    admin.py
    apps.py
    migrations/
        __init__.py
    models.py
    tests.py
    views.py
```
最初に記述した絵のURL Routingがurls.pyにあたり、Viewがviews.pyにあたり、Modelがmodels.pyにあたります。
まずViewを記述します。ここでは、modelを使わずに単純に固定の文字列をResponseで返しています。

```python
# mysite/polls/views.py
from django.http import HttpResponse


def index(request):
    return HttpResponse("Hello, world. You're at the polls index.")
```

あとはURL Routingですが、アプリケーションの下のurl.pyとプロジェクトのurl.pyの両方を変更する必要があります。

```python
#mysite/polls/urls.py
from django.conf.urls import url

from . import views

urlpatterns = [
    url(r'^$', views.index, name='index'),
]
```
```python
# mysite/mysite/urls.py
from django.conf.urls import include, url
from django.contrib import admin
from django.urls import path

urlpatterns = [
    url(r'^polls/', include('polls.urls')),
    path('admin/', admin.site.urls),
]
```
あとは先ほどと同様に開発環境用のサーバーを起動して、http://127.0.0.1:8000/polls/ にアクセスすればviews.pyで返却した文字列が表示されます。これで一番シンプルな最初のアプリは完成です。

<img width="373" alt="スクリーンショット 2018-05-06 11.16.51.png" src="https://qiita-image-store.s3.amazonaws.com/0/85182/19cde59c-9114-fee0-db00-b5469e3ada8e.png">

# モデルの作成
モデルを追加して、Viewがモデルから取得したデータを返却するように修正して行きます。
以下のようにmodelを記述します。ORMで記述されることになるため、データーベースにQuestionというテーブルと、Choiceというテーブルが作成される。Questionには、question_textフィールドと、pub_dateフィールドが作成され、Choiceにはquestionフィールドと、choice_textとvoteフィールドが作成される。

```python
# mysite/polls/models.py
from django.db import models

class Question(models.Model):
    question_text = models.CharField(max_length=200)
    pub_date = models.DateTimeField('date published')


class Choice(models.Model):
    question = models.ForeignKey(Question, on_delete=models.CASCADE)
    choice_text = models.CharField(max_length=200)
    votes = models.IntegerField(default=0)
```

Djangoはモデルを記述すると、データベースへのテーブルの作成や、PythonからデータベースにアクセスするAPIを作成してくれますが、そのためにsettings.pyにアプリケーションの登録が必要です。

```python
# mysite/mysite/settings.py
INSTALLED_APPS = [
    'polls.apps.PollsConfig', # <= 追加                                                                                
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]
```
DjangoではデフォルトではSQLiteをデータベースに利用するようになっています。

```python
# mysite/mysite/settings.py
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}
```
MySQLなど利用する場合は、settings.pyの変更が必要です。

以下のコマンドでモデルの変更を反映し、データベースを作成します。

```bash
$ python manage.py makemigrations polls
Migrations for 'polls':
  polls/migrations/0001_initial.py
    - Create model Choice
    - Create model Question
    - Add field question to choice

$ python manage.py migrate
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, polls, sessions
Running migrations:
  Applying contenttypes.0001_initial... OK
  Applying auth.0001_initial... OK
  Applying admin.0001_initial... OK
  Applying admin.0002_logentry_remove_auto_add... OK
  Applying contenttypes.0002_remove_content_type_name... OK
  Applying auth.0002_alter_permission_name_max_length... OK
  Applying auth.0003_alter_user_email_max_length... OK
  Applying auth.0004_alter_user_username_opts... OK
  Applying auth.0005_alter_user_last_login_null... OK
  Applying auth.0006_require_contenttypes_0002... OK
  Applying auth.0007_alter_validators_add_error_messages... OK
  Applying auth.0008_alter_user_username_max_length... OK
  Applying auth.0009_alter_user_last_name_max_length... OK
  Applying polls.0001_initial... OK
  Applying sessions.0001_initial... OK
```

#管理者で初期データの入力
Djangoでは管理者用のページがデフォルトで用意されています。管理者ユーザーを作成して、先ほど作成したデータベースにデフォルトのデータを入力します。

```bash
$ python manage.py createsuperuser
Username : admin
Email address: admin@example.com
Password: 
Password (again): 
Superuser created successfully.
```

pollsアプリのモデルを管理者が変更できるように以下を追加します。

```python
# mysite/polls/admin.py
from django.contrib import admin

from .models import Question

admin.site.register(Question)
```
開発用サーバーを起動して、管理者のページにアクセスし、先ほどのユーザー名、パスワードを入力すると、Questionのテーブルが見えます。
<img width="659" alt="スクリーンショット 2018-05-06 14.28.12.png" src="https://qiita-image-store.s3.amazonaws.com/0/85182/b3261e23-7fe2-17a7-1c34-dca2fc1ab8da.png">

Questionにテストデータ追加します。
<img width="1078" alt="スクリーンショット 2018-05-06 14.30.58.png" src="https://qiita-image-store.s3.amazonaws.com/0/85182/5e985ff8-2a13-7a3a-bbdd-ec69bc4b989c.png">

Djongoのshellで確認しても正しくデータが入っています。

```bash
$ python manage.py shell
Python 3.6.4 (default, Mar  1 2018, 18:36:42) 
[GCC 4.2.1 Compatible Apple LLVM 9.0.0 (clang-900.0.39.2)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from polls.models import Question, Choice
>>> Question.objects.all()
<QuerySet [<Question: Question object (1)>]>
```

#Viewの変更

最後にViewでモデルからデータを取るように変更します。今回はシンプルにModelとの導通を確認したいだけなので、先程登録したデータを取り出してフィールドのデータを単純に表示します。

```python
# mysite/polls/views.py
from django.http import HttpResponse
from .models import Question

def index(request):
    q = Question.objects.get(id=1)
    return HttpResponse(q.question_text)
```
<img width="332" alt="スクリーンショット 2018-05-06 22.49.30.png" src="https://qiita-image-store.s3.amazonaws.com/0/85182/45ff9aed-0c81-8fbc-8096-1a6ae5624178.png">

これで基本的な導通は確認できました。Djangoの基本構造が理解できたので今回はここで終了とします。