django-rest-framework の設定

## とりあえずAPIを使えるようにする

### 初期設定

必要なライブラリのインストール
```
pip3 install django
pip3 install djangorestframework
pip3 install django-filter
```

プロジェクト作成とアプリ作成
```
django-admin startproject portfolio
cd portfolio
python3 manage.py startapp djangorest
tree
├── db.sqlite3
├── djangorest
│   ├── __init__.py
│   ├── admin.py
│   ├── apps.py
│   ├── migrations
│   │   └── __init__.py
│   ├── models.py
│   ├── tests.py
│   └── views.py
└─ manage.py
```

### モデルの定義
- ForeignKeyは「多対一」の関連を持つモデル同士を関連付け
- related_nameは、逆参照（reverse lookup）を行うときに、関連するオブジェクトを取得するための属性名を指定
- toはmodelを指定する（省略可能）
```
from django.db import models

class User(models.Model):
    name = models.CharField(max_length=32)
    mail = models.EmailField()

class Category(models.Model):
    name = models.CharField(max_length=32)

class Entry(models.Model):
    STATUS_DRAFT = "draft"
    STATUS_PUBLIC = "public"
    STATUS_SET = (
            (STATUS_DRAFT, "下書き"),
            (STATUS_PUBLIC, "公開中"),
    )
    title = models.CharField(max_length=128)
    body = models.TextField()
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    status = models.CharField(choices=STATUS_SET, default=STATUS_DRAFT, max_length=8)
    author = models.ForeignKey(to=User, related_name='entries', on_delete=models.CASCADE)
    category = models.ForeignKey(to=Category, related_name='categorys', on_delete=models.CASCADE)
```

### 作成したアプリをsetting.pyへ追加
`vim portfolio_app/settings.py`
```
# Application definition

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'djangorest'
]
```

### modelをDBへ反映
manage.pyのあるディレクトリで下記を実行
- migrationファイルを作る
`python3 manage.py makemigrations`
- migrationファイルを元にDBに反映する
`python3 manage.py migrate`

### 管理画面へ反映させる
下記にmodel情報を追記
`vim portfolio/djangorest/admin.py`
```
from django.contrib import admin
from djangorest.models import User , Category , Entry

admin.site.register(User)
admin.site.register(Category)
admin.site.register(Entry)
# Register your models here.
```

### 反映されているか確認
`python3 manage.py runserver`
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/21667/b688f6d5-f6d2-804c-31a1-b27abf84df12.png)

REST Frameworkをdjangoへ読み込ませる
--
`vim portfolio_app/settings.py`

```
# Application definition

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'djangorest',
    'rest_framework',
]
```

### serializerの作成
`vim djangorest/serializer.py`
```
from rest_framework import serializers
from .models import User, Entry, Category


class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ('name', 'mail')


class EntrySerializer(serializers.ModelSerializer):
    class Meta:
        model = Entry
        fields = ('title', 'body', 'created_at', 'status', 'author', 'category')


class CategorySerializer(serializers.ModelSerializer):
    class Meta:
        model = Category
        fields = ('name')

```

### viewsの設定
`vim djangorest/views.py`

```
from django.shortcuts import render

import django_filters
from rest_framework import viewsets, filters

from .models import User, Entry
from .serializer import UserSerializer, EntrySerializer, CategorySerializer


class UserViewSet(viewsets.ModelViewSet):
    queryset = User.objects.all()
    serializer_class = UserSerializer

class EntryViewSet(viewsets.ModelViewSet):
    queryset = Entry.objects.all()
    serializer_class = EntrySerializer

class CategoryViewSet(viewsets.ModelViewSet):
    queryset = Category.objects.all()
    serializer_class = CategorySerializer
```

### urls.pyの編集
portfolio_app/urls.pyにportfolio_app/djangorest/urls.pyを読み込む設定を追加
`vim portfolio_app/urls.py`
```
from django.contrib import admin
from django.urls import path , include

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


`vim djangorest/urls.py`
```
from rest_framework import routers
from .views import UserViewSet, EntryViewSet, CategoryViewSet


router = routers.DefaultRouter()
router.register(r'users', UserViewSet)
router.register(r'entries', EntryViewSet)
router.register(r'categorys', CategoryViewSet)
```

### 動作確認
`python3 manage.py runserver`
`http://localhost:8000/api/`　にアクセスして下記が表示されればOK
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/21667/a477b481-5219-6b44-ac6b-18a8e8668f6b.png)

- pythonからGETで取得
```
import requests
import json

url = 'http://localhost:8000/api/users/'
res = requests.get(url)
data = json.loads(res.text)
print(data)
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/21667/60b33fda-81ff-7adc-3ce2-50d3cbd336b4.png)


- pythonからPOSTで登録
```
import requests
import json

url = 'http://localhost:8000/api/users/'
payload = {
        "name": "barfoo",
        "mail": "hoge3@gmail.com"
    }
res = requests.post(url,json=payload)
data = json.loads(res.text)
print(data)
```