LoginSignup

This article is a Private article. Only a writer and users who know the URL can access it.
Please change open range to public in publish setting if you want to share this article with other users.

More than 3 years have passed since last update.

Python(Django REST Framework) + Herokuで入荷チェックLINE Botを作ってみました(DRF紹介編)

Last updated at Posted at 2020-09-01

環境構築にから順々に記載しています。
Djangoプロジェクトの作成は5.2.Djangoプロジェクトの作成から、具体的な実装内容等は次回記事になります。

■やったこと

コロナの影響で買えなくなってしまった商品の入荷情報を定期+任意のタイミングでチェックして、その内容を通知するLINE Botを作りました。
(今回の記事はフレームワークの紹介のみです)

■想定している読者

・Python初学者(開発経験あり)
・web APIを作ってみたいという方
・LINE Botを作ってみたいという方(この内容は次回です)

誰にでも"とりあえず"実装できるような記事を目指しています。
何をやっているのかわからないという状況を避けるべく、周りくどい表現や冗長な表現が多用されると思いますが、何卒ご容赦ください。
また、理解が完璧ではないので一部ふわっとした説明になっています。
あくまでも同じことが出来るようになる、ということに重点を置いています。

■開発環境

OS
・Windows 10

Python
・python3.6.4

主なライブラリ
・django
・djangorestframework
・selene

WEBサーバ
・Heroku

DB
・PostgerSQL
・MySQL(ローカルでのみ使用)

エディタ
・visual studio code

その他
・Advanced REST Client

■開発準備

1.Pythonのインストール

Pythonをインストールしていない場合は、こちらなどを参考にインストールします。
一応3.6.4を使いましたが、ローカルで使うには最新版でも問題ありません。

2.仮想環境の作成

コンソール上で、アプリを作成したいディレクトリに移動し、以下のコマンドを実行します。
完了時のメッセージはありません。

cmd
python -m venv venv

正常に実行されると、コマンドを実行したディレクトリにvenvフォルダが作成されます。
venv/Scriptsに移動し、activate.batを実行します。

実行すると、コンソールの表示が以下のように切り替わります。
(venv) C:\(作成したいディレクトリ)\venv\Scripts>
(venv)と表示されていれば成功です。これで無事仮想環境に入ることができました。

※仮想環境とは?という方はこちら

3.ライブラリのインストール

仮想環境に必要なライブラリをインストールしていきます。
以下のコマンドを打てば終わりです。Djangoのインストールにはちょっとだけ時間がかかります。

cmd
pip install django

pip install djangorestframework ※1

pip install selene

※1
django-rest-frameworkではないので注意

memo:
pipはPythonにおけるパッケージマネージャです。
他にもpipenv,Poetry,Pyflowなどといったパッケージマネージャがあり、そちらの方が高機能なようですが、
実際に使うところまではできていないのでご紹介程度に…

4.MySQLの準備

MySQLをローカルにインストールしていない方はこちらなどを参考にインストールしてください。
MySQLを使用せず、sqliteでよいという方はこちらの手順を飛ばしていただいても問題ありません。

5.プロジェクトの枠作り

5.1.DjangoプロジェクトおよびDRFについて

DRFはDjangoプロジェクトの上に成り立っています。
DjangoはMTVモデルに従って作成します。Model・Template・Viewモデルです。
MVCモデルと対応させると"おおよそ"以下の通りです。Viewが知っている役割をしていなかったので、最初は本当に混乱しました…

MVC MTV MTVについての備考
Model Model DBのテーブルと1対1になる。DBと連携する。
View Template HTMLファイル。Viewで処理されたデータを表示する。
Controller View Modelで取得したデータやリクエストで渡されてきたデータの処理を記述する。

そして、今回使用するDRFではTemplateは使用しません。
DRFは以下の構造で成り立っています。(正確な図ではないかもしれませんが、ざっくりこんな感じです。)
image.png

5.2.Djangoプロジェクトの作成

では、djangoプロジェクトを作成していきます。
プロジェクトのルートディレクトリにしたい位置に移動して、以下のコマンドを実行します。

cmd
django-admin startproject sample_project

これでsample_projectという名前のプロジェクトのひな形が作成されます。

作成されたsample_projectのsettings.pyにrest_frameworkを使用することを追記します。

sample_project/settings.py
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'rest_framework', # 追記箇所
]

さらに、sample_project内で以下のコマンドを実行します。

cmd
python manage.py startapp sampleapp

これでsample_projectにsampleappが作成されます。
先ほど同様、settings.pyにsampleappを追記します。

sample_project/settings.py
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'rest_framework',
    'sampleapp', # 追記箇所
]

すぐには必要になりませんが、sample_projectのurls.pyに以下のように追記しましょう。

sample_project/urls.py
urlpatterns = [
    path('admin/', admin.site.urls),
    url(r'^sampleapp/', include(sampleapp_router.urls)), # 追記箇所
]

これは、http://(ホスト名)/sampleapp/ にアクセスされたときにはsampleapp/urls.pyが呼ばれるようにしています。
先ほどの図では省略していましたが、DjangoプロジェクトにはUrls.pyがプロジェクトレベルのものとアプリレベルのもので2つ存在しており、以下のような関係になっています。

image.png

おまけで、LANGUAGE_CODEとTIME_ZONEも以下のように修正します。

sample_project/settings.py
LANGUAGE_CODE = 'ja'
TIME_ZONE = 'Asia/Tokyo'
5.3.ローカルサーバーの起動

仮想環境内で以下のコマンドを実行します。

cmd
python -m manage.py runserver

これで、ローカルサーバーが起動します。以下のURLにアクセスしてみましょう。
http://localhost:8000/

welcomeページが表示されるはずです。

ちなみに、サーバーはコマンドプロンプトでctrl+cをすれば停止します。

ここまでで、プロジェクトの大枠は作ることができました。

5.4.管理者ページについて

djangoプロジェクトには管理者ページが存在します。
このページはdjangoプロジェクトを作成すると自動で提供されますが、今回は特に使用しません。
管理者ページについて気になる方は別途お調べください…

5.5.MySQLを使用する方へ

mysqlclinetのインストールと、settings.pyを修正してください。

cmd
pip install mysqlclient
sample_project/settings.py

# DATABASES = {
#     'default': {
#         'ENGINE': 'django.db.backends.sqlite3',
#         'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
#     }
# }

# 上記のsqliteを使用する設定を以下の内容に修正
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': '(使用するDBのスキーマ名)',
        'USER': '(ユーザ名)',
        'PASSWORD': '(パスワード)',
        'HOST': '(ホスト名)',
        'PORT': '(ポート番号)',
    }
}

6.実装

プロジェクトの大枠を作ることが出来たので、具体的な実装に入っていきます。

6.1.modelの追加

sampleapp/model.pyにDBに追加したいテーブル単位でmodelを記載していきます。
class=テーブルという関係になり、ORM的な働きをします。試しにUserモデルを作成します。

sampleapp/model.py
from django.db import models

class User(models.Model):
    user_id = models.CharField(max_length=128)
    age = models.TextField()
    user_name = models.TextField()
    bithday = models.DateTimeField()
    password = models.CharField(max_length=128)

以下の形で記述されています。
カラム名 = データ型(制約の指定)

※データ型の指定方法については、こちらが詳しいです。

6.2.マイグレート

先ほどmodel.pyに記載した内容で、DBをマイグレートします。(ここではテーブルを新たに作成)
マイグレーションファイルを作成するために、仮想環境内で以下のコマンドを実行します。
ローカルサーバーを動かしている場合は、ctrl+cで一度止めましょう。

cmd
python manage.py makemigrations sampleapp

作成されたファイルの中身を確認するためには以下のコマンドを実行します。

cmd
python manage.py sqlmigrate sampleapp 0001

実際にマイグレートするには以下のいずれかのコマンドです。

cmd
python manage.py migrate sampleapp      : 実行されていないファイル全てを実行する
python manage.py migrate sampleapp 0001 : 実行したいファイルを指定する書き方

これで、models.pyに記載した内容でテーブルが作成されています。
各コマンドの後ろに打っている"0001"は、マイグレーションファイルのシリアル番号です。

テーブルの追加や定義の変更のために新たにマイグレーションファイルを作るごとに新たにファイルが作成されるので、当然ですが毎回必ずマイグレートする必要があります。

6.3.seriaizer定義

ModelやDtoをjson形式にシリアライズしたり、jsonをデシリアライズしたりするのがserializerです。

sampleappディレクトリに、serializer.pyを作成してください。

sampleapp/serializer.py
from rest_framework import serializers

from .models import User

class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User # シリアライズ対象のModelを指定します
        fields = ('user_id', 'age', 'user_name', 'bithday', 'password') # Userクラスに定義したフィールド名を書きます

class UserEncryptSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ('user_id', 'age', 'user_name', 'birthday', 'password')

    def create(self, validated_data):
        user = User(
            user_id = validated_data['user_id'],
            age = validated_data['age'],
            user_name = validated_data['user_name'],
            birthday = validated_data['birthday'],
            password = encrypt(validated_data['password']) # 暗号化している風の処理
        )
        user.save()
        return user

createメソッドはModelSerializerクラスに定義されているメソッドで、オーバーライドしています。
createメソッドに渡したデータ(validated_data)をUserインスタンスにセットして、DBにinsert(save)します。

UserSerializerとUserEncryptSerializerがありますが、どちらのクラスも使い方は同じになります。
各クラスの違いは、createメソッドをオーバーライドしているかどうかだけです。
オーバーライドすることで、シリアライズされたデータを加工してからinsertができます。
例ではパスワードを暗号化している風のことをしています。

これでSerializerはOKです。

memo:
class Metaとありますが、こちらはPythonのMetaクラスとはまた別の概念のようです。

今回はModelSerializerを継承しているため、Modelをシリアライズ(デシリアライズ)するためのクラスになりますが、継承するものによって扱えるデータや扱い方が異なります。

6.5.viewを記述

次に、sampleapp/views.pyにデータの処理を書いていきます。

sampleapp/views.py
import django_filters
from rest_framework import viewsets, filters
from django.core import serializers
from .models import User
from .serializer import UserSerializer, UserEncryptSerializer
import json

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

class AdultUserViewSet(viewsets.ModelViewSet):
    serializer_class = UserSerializer
    queryset = User.objects.filter(age__gte=20)).order_by('-age')[:8]

2つの簡単なViewを作成してみました。
それぞれに共通して書かれているserializer_classquerysetはDRFで予め定義されている変数です。
ModelViewSetを継承したクラスでは必ず記載する必要があります。

serializer_classには使用するSerializerを代入します。

querysetは、DBからどのようにデータを取得するかを取得します。
AdultUserViewSetのquerysetは以下のSQLと同等の内容になっています。

SQL
select * from user where age >= 20 order by age desc

あまり複雑なクエリは書けないようですが、そのような場合はSQLAlchemyというORMライブラリを使用すると良さそうです。
私は今回使用していないので、ご紹介程度です…

ちなみにこれだけのコード量ですが、userテーブルに対するCRUD処理が一通り実装されています。
今回のBotを作るにあたってはそこまで恩恵に預かれませんでしたが、これは本当に手軽ですね…

ここまでくればあと一歩です!

7.URLを設計

先ほどはプロジェクトレベルのurls.pyに手を入れて、http://(ホスト名)/sampleapp/にアクセスされた際にsampleapp/urls.pyが呼び出されるようにしました。

次に、アプリケーションレベルのurls.pyに手を入れます。

sampleapp/urls.py
from rest_framework import routers
import sampleapp.views as view

router = routers.DefaultRouter()
router.register('user', view.UserViewSet)
router.register('user/adult/', view.AdultUserViewSet)

これで、http://(ホスト名)/user/にアクセスされればUserViewSetが呼び出され、http://(ホスト名)/user/adult/にアクセスされればAdultUserViewSetが呼び出されます。

8.レスポンスの確認

curlコマンドやAdvanced REST Clientを使ってCRUD処理が実装されていることを確認しましょう。

こちらの説明は一旦省略しますが、時間があるときに追記するかもしれません。

7.URLを設計までを読んでいれば次回の内容も問題無く読めるとは思います。

9.まとめ

これで、DRFについてのチュートリアルレベルの、かなり嚙み砕いた説明は終わりです。
DRFの概説だけでも結構な量になるため、記事を分割します。
次回は具体的な実装内容と、Herokuへのデプロイ手順、LINE Botの作成手順です。

■参考資料

Django ドキュメント
Django REST Frameworkのチュートリアル
[Django REST Framework] View の使い方をまとめてみた
Django REST Frameworkを使って爆速でAPIを実装する

0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up