djangoを利用したAPIを理解する[part2 アプリを作ってモデル周りの整備]

djangoを理解する記事第2回 アプリを作ってモデル周りの整備を進めます。

前回の記事はこちら
[djangoを使ったAPI開発を理解する[part1 目的の整理と環境構築]](https://qiita.com/poolbooyer/items/dac99e9c33f8c5f437ff)

## アプリを作る
まずはアプリを作ります。
まずは前回の復習でアプリケーションってなんだと言うことの確認です。
前回書いたドキュメントの和訳を引っ張ってきます。
> アプリケーションはブログシステムや公的な記録のデータベース、小さな投票アプリのような何かしらを行うwebアプリケーションのことです。

前回の時点で作ったプロジェクトに、その中の機能として使うアプリを作ります。
アプリは以下のコマンドで作れます。
```terminal
python manage.py startapp <アプリ名>
```
今回はブログ記事の機能を作りたいので以下のコマンドを`docker`のコンテナ内で実施します。
```terminal
root@6f4ae531bd2c:/code/myblog# python manage.py startapp entry
```
実行するとディレクトリ内にentryディレクトリが作成されて、雛形が出来上がります。

## entryの作り込み
ここからは[django-rest-frameworkのチュートリアル](https://www.django-rest-framework.org/tutorial/1-serialization/#getting-started)を参考に進めます。
まずは、settingsにアプリケーションとdjango-rest-frameworkを導入していきます。
```diff_python:web/code/myblog/myblog/settings.py
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
+   'rest_framework',
+   'entry',
]
```
entryのモデルを作ります。
```python:web/code/myblog/entry/models.py
from django.db import models

class Entry(models.Model):
    created = models.DateTimeField(auto_now_add=True)
    title = models.CharField(max_length=100, blank=False)
    body = models.TextField()

    class Meta:
        ordering = ['created']
```
このモデルは以下の要素を持ちます。
- created
  - 作成日時
- title
    - 記事のタイトル
- body
    - 記事の内容
一旦ユーザーを複数登録できる様にとかは考えていないのでこんな構成で行きます。
モデルができたら`migration`を実施します。
```terminal
python manage.py makemigrations <モデル名>
```
を実施を実施することで`アプリケーション名/migrations`ディレクトリが作成されて、その中にマイグレーションファイルができます。
```python:001_inital.py
from django.db import migrations, models


class Migration(migrations.Migration):

    initial = True

    dependencies = [
    ]

    operations = [
        migrations.CreateModel(
            name='Entry',
            fields=[
                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('created', models.DateTimeField(auto_now_add=True)),
                ('title', models.CharField(max_length=100)),
                ('body', models.TextField()),
            ],
            options={
                'ordering': ['created'],
            },
        ),
    ]
```
その上で以下のコマンドを流すと、対象のモデルに対して実行される様な流れです。
```terminal
python manage.py migrate <モデル名>
```
## serializerの実装
ここからはdjango-rest-frameworkのドキュメントに則って進めます。
`serializer`はデータのR/Wを取り扱うクラスです。
具体的には以下の様に作ります。
```python:web/code/myblog/entry/serializers.py
from rest_framework import serializers
from entry.models import Entry

class EntrySerializer(serializers.Serializer):
    id = serializers.IntegerField(read_only=True)
    title = serializers.CharField(required=False,　allow_blank=False,　max_length=100)
    body = serializers.CharField()

    def create(self, validated_data):
        return Entry.objects.create(**validated_data)

    def update(self, instance, validated_data):
        instance.title = validated_data('title',instance.title)
        instance.body = validated_data('body', instance.body)
        instance.save() 
        return instance
```
modelでの定義をベースにしてクラスを定義していきます。
`create`はバリデーションを通した結果、作成できる場合は作成、`update`は項目単位で更新する様な処理になっています。
 次回はこれを使ってAPIとして呼び出せる様に作り込んでいきます。
ここまでのソースはこちら
[github](https://github.com/poolbooyer/django-api-sample/tree/v0.1.0)
## 参考
[django-rest-frameworkチュートリアル](https://www.django-rest-framework.org/tutorial/1-serialization/#getting-started)