Djangoでjsonを扱うRESTfulなAPIを作る



##  Djangoのインストール
- pipを使う場合

```
$ pip install django
```
- Anacondaを導入している場合

```
$ conda install django
```
これで`django-admin`コマンドが使えるようになるはずです
確認してみましょう

```
$ django-admin --version
```

バージョンが帰って来たら成功です

##  プロジェクトの作成
プロジェクトを作成したいディレクトリに移動します

```
$ cd projectfolder
```
以下のコマンドでプロジェクトの雛形が生成されます

```
$ django-admin startproject myproject
```
myprojectは任意のプロジェクト名です
これでmyprojectというフォルダが作成されたはずです

ファイル構成は次のようになっています

```
myproject
├── manage.py
└── myproject
    ├── __init__.py
    ├── settings.py
    ├── urls.py
    └── wsgi.py
```

##  アプリの作成
プロジェクトの中にアプリを作成します

```
$ cd myproject
$ python manage.py startapp myapp
```
myappは任意のアプリ名です

この時点でのファイル構成は次のようになっているはずです

```
myproject
├── manage.py
├── myapp
│   ├── __init__.py
│   ├── admin.py
│   ├── apps.py
│   ├── migrations
│   │   └── __init__.py
│   ├── models.py
│   ├── tests.py
│   └── views.py
└── myproject
    ├── __init__.py
    ├── __pycache__
    │   ├── __init__.cpython-36.pyc
    │   └── settings.cpython-36.pyc
    ├── settings.py
    ├── urls.py
    └── wsgi.py
```

`setting.py`内の INSTALLED_APPという項目に今作成したアプリ名を追加します

```python:setting.py
.....

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
+   'myapp',  #追加行
]

.....
```

##  データモデルの作成
モデルファイルを作成します

```
$ touch myapp/models.py
```
このファイルにはデータベースに蓄積するデータの構造や型を指定します

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

class Author(models.Model):
    name = models.CharField(max_length=128)

class Book(models.Model):
    author = models.ForeignKey(Writer, related_name='books',on_delete=models.CASCADE, null=True, blank=True, default=None)
    title = models.CharField(max_length=512)
    contents = models.TextField()
```


なお、on_deleteを書いてない記事も見受けられますが、
Django2.0以降はmodels.ForeignKey()の引数にon_deleteプロパティが必須のようです
on_deleteを指定しない場合、マイグレーションファイル作成時に以下のようなエラー文が出ます
`TypeError: __init__() missing 1 required positional argument: 'on_delete'`

##  マイグレーション
マイグレーションとは、データモデルの変更内容をデータベースに反映させる為の命令を記述することです

マイグレーションファイルを作成します

```
$ python manage.py makemigrations
```
うまくいかない場合はアプリ名を指定します
> [django model を作成したが、makemigrations で No changes detected になる \| Monotalk](https://www.monotalk.xyz/blog/django-model-%E3%82%92%E4%BD%9C%E6%88%90%E3%81%97%E3%81%9F%E3%81%8Cmakemigrations-%E3%81%A7-no-changes-detected-%E3%81%AB%E3%81%AA%E3%82%8B/)

これでmyapp内にmigrationsディレクトリが生成されました
この時点でファイル構成は以下のようになっています

```
myproject
├── db.sqlite3
├── manage.py
├── myapp
│   ├── __init__.py
│   ├── __pycache__
│   │   ├── __init__.cpython-36.pyc
│   │   ├── admin.cpython-36.pyc
│   │   └── models.cpython-36.pyc
│   ├── admin.py
│   ├── apps.py
│   ├── migrations
│   │   ├── 0001_initial.py
│   │   ├── __init__.py
│   │   └── __pycache__
│   │       └── __init__.cpython-36.pyc
│   ├── models.py
│   ├── tests.py
│   └── views.py
└── myproject
    ├── __init__.py
    ├── __pycache__
    │   ├── __init__.cpython-36.pyc
    │   ├── settings.cpython-36.pyc
    │   └── urls.cpython-36.pyc
    ├── settings.py
    ├── urls.py
    └── wsgi.py
```
マイグレーションを実行します

```
$ python manage.py migrate
```
あとでデータモデルを新しく追加したり、属性を変更したりした場合は再びやりなおす必要があります

この時点でもDjangoのshellを用いてデータを追加することができますが、目的はapiを作ることなのでここでは省きます


## APIの作成
ふたつのファイルを作成します

```
$ touch myproject/urls.py
$ touch myapp/views.py
```


`urls.py`ではurlとviewを対応させます


```urls.py
from django.conf.urls import url
from django.contrib import admin
from myapp import views

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^books$', views.show_books),
]
```

`views.py`では、「何を出力するか」を指定します

```views.py
import json
from django.http import HttpResponse
from django.core import serializers
from myapp.models import Book

def show_books(request):
    return HttpResponse(serializers.serialize("json", Book.objects.all()))
```

今回は`/books`へアクセスするとすべてのbookのデータをjson形式で返します

##  サーバー動作確認
```
$ python manage.py runserver
```
末尾に四桁の数字をつけるとポート番号を指定できます
今回は指定していないのでデフォルトの8000番が使用されます

プラウザで http://localhost:8000/books にアクセスするか、以下のコマンドを実行してみましょう

```
$ curl http://localhost:8000/books
```
まだ何もデータが入っていないので、

```
[]
```
と表示されるはずです

次回の記事↓
[Django REST framework でJSONをGET/POST/PUT/DELETE](https://qiita.com/HIJIKI/items/a88d1ca86788bed3af9e)