第2回 モデルの作成
Django REST Frameworkのいちばん簡単な処理の流れ
Django REST Frameworkのインストールとプロジェクトの作成、アプリの登録まで済んだら、いよいよコーディングが始まります。
その前に、ここでDjango REST Frameworkの処理の流れについて、簡単に整理しておきます。
上記の図はすごくざっくり簡単にまとめた処理の図です。
いちばん左のクライアントは、ChromeのようなブラウザなどのHTTP Requestを送信する部分になります。
HTTP Requestを受け取ったDjango REST Frameworkのサーバは、まずURLルーティングを行います。urls.pyに定義した内容に従って、リクエストのURLに対応するDjangoアプリのビュー (View) クラスを呼び出します。
呼び出されたViewクラスは、そこにコーディングしたロジックを実行します。DBへのアクセスが必要な場合は、そのアクセス用に設計されたシリアライザ (Serializer) へHTTP Requestで受け取ったパラメータを渡してチェックし、DBの検索や更新など操作を行います。
DBから結果が返ってきたら、それをHTTP Responseとしてクライアントへ返します。
シリアライザはDBを直接操作する代わりに、テーブル定義にあたるモデル (Model) クラスを操作します。モデルクラスにテーブルの各カラム定義を行います。また、DBへのSQLクエリ文作成などより低レイヤな機能がここにあります。
どこから作り始めるか
Django REST Frameworkの最小構成は、先に説明したようにURLルーティング、ビュー (View)、シリアライザ (Serializer)、モデル (Model) のかたちになります。
では、どこから手を付けたら良いでしょうか。
コーディングというか設計そのものの話になりますが、私は個人的にモデルから手を付けるのが良いと考えています。
Django REST Frameworkとは、DjangoでRESTfulなAPIを提供するためのフレームワークという位置づけです。
RESTfulなAPIとは、単にHTTP RequestでAPIを作るという意味ではなく、データを現実世界の物の単位に整理してそれを操作するようなイメージのAPIを目指すことについて言及しています。なので、まず現実世界の物の単位に整理したモデルを設計し、それに対してシリアライザとビューを被せてAPIとしていく順序がしっくりくるのです。
モデル (Model) を作成する
ということで、早速モデルを作成してみましょう。
ここでは、ブログでも掲示板でも良いのですが何かしら記事を投稿して管理するサーバを想定して、投稿記事のモデルを作成してみます。
モデルの設計は実質的にDBのテーブル設計です。
まず通し番号の投稿IDがあり、次にタイトル、作成日時、更新日時、本文のカラムを用意しました。投稿者名も入れたいところですが、ここはリレーションなど少し踏み込んだ技を使いたいので今回は無しとします。
カラム名 | 型 | プライマリキー | NULL | パラメータ | 内容 |
---|---|---|---|---|---|
id | INTEGER | ○ | 非許容 | 自動採番 | 投稿ID |
title | VARCHAR(32) | - | 非許容 | - | タイトル |
created_time | DATETIME | - | 非許容 | 作成時の日時を自動設定 | 作成日時 |
updated_time | DATETIME | - | 非許容 | 更新時の日時を自動設定 | 更新日時 |
body | TEXT | - | 非許容 | デフォルトは空文字 | コンテンツ |
これを、Djangoアプリ配下にある models.py に定義します。
from django.db import models
# Create your models here.
class ContentModel(models.Model):
"""コンテンツモデル"""
class Meta:
db_table = 'content'
id = models.BigAutoField(verbose_name='投稿ID', primary_key=True)
title = models.CharField(verbose_name='タイトル', max_length=32)
created_time = models.DateTimeField(verbose_name='作成日', auto_now_add=True)
updated_time = models.DateTimeField(verbose_name='更新日時', auto_now=True)
body = models.TextField(verbose_name='コンテンツ', default='')
def __str__(self):
return self.title
Djangoのモデル作成は、Djangoの基底クラス models.Model
を継承したオリジナルクラスを作成することで行います。今回は ContentModel
を作りました。
class Meta
には色々な付帯情報を指定できるのですが、今回は実際のDBテーブル名が 'content'
であるということのみを設定しています。
その後に続く5行がテーブルカラムの定義です。
ここに記述していく変数がそのままDBのカラムになっていきます。DBカラムの型は BigAutoField
や CharField
など、Djangoの models
クラスに用意されているものを使用します。詳細は公式ドキュメントを見ていただくとして、このあたりの説明は別の機会にしたいと思います。
最後の def __str__(self):
は何をしているかというと、このクラスインスタンス (レコード) を簡単な文字列として取得したい場合に title
部分を返す、というメソッドを定義しています。
それぞれ、後でその効果が発揮されますので、今はわからなくても読み進めてみてください。
Djangoの管理下に登録する
モデルを作成したので、これをDjangoの管理下に登録します。DBにテーブルが作成されていることを確認できました。
登録は簡単で、Djangoアプリ配下の admin.py
に以下のコードを追加して、作成した ContentModel
クラスを登録するだけです。
from django.contrib import admin
from .models import ContentModel
# Register your models here.
class ContentAdmin(admin.ModelAdmin):
model = ContentModel
admin.site.register(ContentModel, ContentAdmin)
モデルをDBに反映する
モデルを作成してDjangoの管理下に登録したら、それをDBに反映します。
SQL文で言うところの CREATE TABLE
文でテーブルを作成する操作が必要なのですが、Djangoで作成したモデルは以下のコマンドでDBに反映することが可能です。
(.venv)$ python manage.py makemigrations
(.venv)$ python manage.py migrate
Djangoの初期設定時にも実行しましたが、このコマンドの正しい意味は「モデルをDBに反映するコードを作成する」と「実際にDBに反映する」になります。
最初の python manage.py makemigrations
でモデルをDBに反映するコードを作成する訳ですが、そのコードはDjangoアプリの migrations
フォルダに溜まっていき、世代管理がされています。Djangoの初期設定時にDB側にも同様にマイグレーション管理テーブルが作成されて、python manage.py migrate
コマンドでどこまでDBに反映されたかをDjangoとDBの双方で管理しています。
DBを覗いてみる
モデルをDBに反映したので、実際にどうなったかDBを覗いてみたいと思います。
DBへのログインもDjangoのコマンドで簡単に行うことができるのですが、そのためにはDBクライアントのパッケージが必要です。今回はSQLiteなので、ログイン前にSQLite3パッケージをインストールします。以下はUbuntuでSQLite3パッケージをインストールする場合の例です。
$ sudo apt install sqlite3
クライアントパッケージをインストールしたら、以下のコマンドでDBへログインします。
なお、SQLiteプロンプトからのログアウトは .exit
コマンドになります。
(.venv)$ python manage.py dbshell
SQLiteのコマンドでテーブル定義を見てみます。
sqlite> .tables
auth_group content
auth_group_permissions django_admin_log
auth_permission django_content_type
auth_user django_migrations
auth_user_groups django_session
auth_user_user_permissions
.tables
コマンドでテーブル一覧を見てみると、content
テーブルが出来上がっている事が見えました。
そのほかのテーブルはDjangoを初期設定した際に自動追加されたものです。
では次に、content
テーブルの定義を見てみます。
sqlite> .schema content
CREATE TABLE IF NOT EXISTS "content" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "title" varchar(32) NOT NULL, "created_time" datetime NOT NULL, "updated_time" datetime NOT NULL, "body" text NOT NULL);
SQLiteの .schema
コマンドは、テーブルの定義を CREATE TABLE
文の形式で表示します。ContentModel
クラスのモデルで定義した変数がカラムになっている事が確認できます。ただし、created_time
や updated_time
の auto_now
や body
の default=''
指定はDBまで反映されていません。どうやらDjango側でDBへレコードを追加したり更新する際に操作されるようです。
Djangoの管理サイトでモデルを操作してみる
DBにモデルと同等のテーブルが作成されたことを確認できました。
これからシリアライザやビュー、URLルーティングを実装してAPIを作っていくことになるのですが、その前にこの時点でDjangoが提供する管理サイト機能により、モデルを閲覧したりレコードを追加することができます。
モデルを閲覧する
Djangoを起動して管理サイト http://localhost:8000/admin
にアクセスしてみます。
既にDjangoを起動中の場合は、起動中のDjangoがファイルの変更を検知して自動的に再起動しているはずです。
(.venv)$ python manage.py runserver 0:8000
管理サイトへログインすると、CONTENTS
アプリの下に Content Models
が現れます。Content Models
をクリックすると以下のような画面に遷移し、このモデルのレコード追加や更新ができます。今はまだ何もレコードが無いので、まずは右上の ADD CONTENT MODEL
をクリックしてレコードを追加してみましょう。
モデルのレコードを新規追加する
Content modelsの閲覧画面右上にある ADD CONTENT MODEL
をクリックすると、「タイトル」と「コンテンツ」のテキストボックスが表示されます。
これらは models.py
に書いた ContentModel
クラス定義の title
と body
変数にあたる部分です。id
や created_time
、updated_time
がここに表示されていませんが、これらはレコード追加や更新時に自動的に値が入るような設定にしたためです。
適当に内容を入力したら、SAVE
ボタンを押してレコードを追加を完了しましょう。
レコードの追加が成功すると元の画面に戻ります。
さきほどタイトルの欄に入力した「テスト投稿」が、作成したモデルの一覧に表示されています。これは、models.py
のモデル定義の際に def __str__(self):
メソッドで title
を返すようにしたため、タイトルが表示されるようになっています。id
など非表示だった項目はまだ表示されません。これらはDjangoアプリの admin.py
をもう少しカスタマイズすることで表示可能ですが、詳細は別途説明したいと思います。
また、この画面で作成したレコードをクリックすると編集画面に遷移し、投稿内容の編集や削除なども行うことが出来ます。ぜひ試してみてください。
次回予告
今回はモデルの作成を行いました。次回は引き続き、シリアライザ (Serializer) とビュー (View) を作成し、外部からAPIアクセスができるようにしていきます。
コメント