Django REST Frameworkの最小構成で動きを理解する (その2)

Django logo Django REST Frameworkの最小構成で動きを理解する

第2回 モデルの作成

Django REST Frameworkのいちばん簡単な処理の流れ

Django REST Frameworkのインストールとプロジェクトの作成、アプリの登録まで済んだら、いよいよコーディングが始まります。
その前に、ここでDjango REST Frameworkの処理の流れについて、簡単に整理しておきます。

flowchart LR; Request((クライアント))--HTTP GET-->Router[URLルーティング\nurls.py]; Router-->View[API毎のロジック\nviews.py]; View-->Serializer[パラメータチェック\nserializers.py]; Serializer-->Model[テーブル定義\nmodels.py]; Model-->DB[(DBテーブル)]

上記の図はすごくざっくり簡単にまとめた処理の図です。
いちばん左のクライアントは、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パラメータ内容
idINTEGER非許容自動採番投稿ID
titleVARCHAR(32)-非許容-タイトル
created_timeDATETIME-非許容作成時の日時を自動設定作成日時
updated_timeDATETIME-非許容更新時の日時を自動設定更新日時
bodyTEXT-非許容デフォルトは空文字コンテンツ
コンテンツテーブルの設計

これを、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カラムの型は BigAutoFieldCharField など、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_timeupdated_timeauto_nowbodydefault='' 指定は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 クラス定義の titlebody 変数にあたる部分です。idcreated_timeupdated_time がここに表示されていませんが、これらはレコード追加や更新時に自動的に値が入るような設定にしたためです。
適当に内容を入力したら、SAVE ボタンを押してレコードを追加を完了しましょう。

レコードの追加が成功すると元の画面に戻ります。

さきほどタイトルの欄に入力した「テスト投稿」が、作成したモデルの一覧に表示されています。これは、models.py のモデル定義の際に def __str__(self): メソッドで title を返すようにしたため、タイトルが表示されるようになっています。
id など非表示だった項目はまだ表示されません。これらはDjangoアプリの admin.py をもう少しカスタマイズすることで表示可能ですが、詳細は別途説明したいと思います。

また、この画面で作成したレコードをクリックすると編集画面に遷移し、投稿内容の編集や削除なども行うことが出来ます。ぜひ試してみてください。

次回予告

今回はモデルの作成を行いました。次回は引き続き、シリアライザ (Serializer) とビュー (View) を作成し、外部からAPIアクセスができるようにしていきます。

コメント

タイトルとURLをコピーしました