Flutter+django-rest-frameworkでWebアプリを実装

前回の記事：

https://qiita.com/hima2/items/aaa29cc7546d7e99f5f1

バックエンドをdjango-rest-frameworkで実装するとどうなるの？という話。
前回と同じく初心者向け。

# django-rest-frameworkとは
FastAPIと同じく、pythonで実装できるWebAPIのフレームワーク。
pythonのフレームワークの中でポピュラーなDjangoをベースとしている。
FastAPIと比較したときのメリット・デメリットは主に以下の通り。

メリット
・ Djangoとの相性が良い。
・ コミュニティが大きいため、詰まることが少ない。
・ FastAPIと比較すると実装されている機能が多く、新たに自分で実装すべき部分が少ない。

デメリット
・初期の学習コストが高い。
・実装されている機能が多すぎて把握しきれない。

WebAPIとかよくわからん、という人にはdjango-rest-frameworkから入るほうがおすすめ。

# バックエンド実装
フロントエンドは前回( https://qiita.com/hima2/items/aaa29cc7546d7e99f5f1 )を参照。
ライブラリのインストールから。
```
pip install django djangorestframework
```
次にDjangoのプロジェクトを作成する。プロジェクトとは、データベースの設定、オプションなどのインスタンスの設定の集合体。ここでは、mysiteというプロジェクトを作成する。
```
django-admin startproject mysite
```
プロジェクトを作成すると以下のようなフォルダが自動的に作成される。
```
mysite
    manage.py
    mysite
        __init__.py
        settings.py
        urls.py
        asgi.py
        wsgi.py
```
それぞれの.pyの詳細はこちら( https://docs.djangoproject.com/ja/4.2/intro/tutorial01/ )を参照。
ひとまずサーバーが立ち上がることを確認する。上のほうのmysiteフォルダに移動し、以下のコマンドを実行する。
```
python manage.py runserver 8080
```
manage.pyはDjangoを管理する上で様々な役割を果たすが、ここでは"runserver"、つまりサーバーを立ち上げている。
ブラウザを起動し、http://127.0.0.1:8080 にアクセスすると、以下の画面に遷移する。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3470374/7117d9f8-e3d6-43f3-f3a5-dd8d1e11a7e9.png" width="500">

同じくmysiteフォルダで以下のコマンドを実行する。
```
python manage.py startapp myapp
```
ここでは、"myapp"というアプリケーションのひな型を作成する。
すると、mysite配下にmyappというフォルダが作成されているのが分かる。

myapp配下に移動し、views.pyというファイルを作成し、以下をコピペ
```views.py
from rest_framework.views import APIView
from rest_framework.response import Response

class HelloWorld(APIView):
    def get(self, request):
        return Response({"greeting": "Hello"})
```
この部分は、FastAPIで書いた
```sample_api.py
@app.get("/")
def read_root():
    return {"greeting": "Hello"}
```
と同じ意味と考えてもらってOK。
ただし、urlの設定はFastAPIよりちょっとややこしい。
同じくmyapp配下のurls.pyを開いて、以下をコピペ
```myapp/urls.py
from django.urls import path
from .views import *

urlpatterns = [path("greeting", HelloWorld.as_view())]
```
次に、**mysite**配下のurls.pyを以下のように変更する。
```mysite/urls.py
from django.contrib import admin
from django.urls import path, include

urlpatterns = [path("admin/", admin.site.urls), path("api/", include("myapp.urls"))]
```
何をやっているか、というと
mysite/urls.py のほうは 「http\://127.0.0.1:8080/api をたたくとmyappのurlsに飛ばしますよー」
myapp/urls.py のほうは「http\://127.0.0.1:8080/api/greeting をたたくとHelloWorldクラスを呼び出しますよー」
という設定をしている。
別のコマンドプロンプトを用意してまたcurlコマンドでapiをたたいてみる。
```
curl http://127.0.0.1:8080/api/greeting
```
すると、
```
{"greeting":"Hello"}
```
と表示される。表示されない人はurlを間違えていないか、runserverをちゃんと起動しているかを確認。
# 動作確認
urlがちょっとだけ変わったので、フロントエンドを前回( https://qiita.com/hima2/items/aaa29cc7546d7e99f5f1 )からちょっとだけ変える
```diff_dart
- Uri url = Uri.parse("http://127.0.0.1:8080/");
+ Uri url = Uri.parse("http://127.0.0.1:8080/api/greeting");
```
そしてFlutterアプリを再起動してボタンを押すと、またコンソールに
```
error
```
と出てくる。実は(というか当たり前だが)、django-rest-frameworkでも同じようにCORSの設定をしなければいけない。
# CORSの設定
CORSを導入するためにライブラリをインストール。
```
pip install django-cors-headers
```
mysite/settings.pyを以下のように編集する。
```settings.py
INSTALLED_APPS = [
...,
'corsheaders', #追加
]
MIDDLEWARE = [
...,
'corsheaders.middleware.CorsMiddleware', # 追加
]
CORS_ORIGIN_WHITELIST = [
'http://localhost:8000'
]
```
これを上書き保存し、Flutterに戻りボタンを押すと、
無事コンソールに
```
{"greeting:"Hello"}
```
と出力される。

# 最後に
FastAPIと比較するとややこしく感じるが前述したとおりdjango-rest-frameworkにも良いところはある。
Djangoについてはいくらでも教材が転がっているので、ぜひじっくりと学んでほしい。
あと、CORSのurlがhttp\://127.0.0.1~だとうまくいかないことがある理由がよくわからないので、ご存じの方は教えてください。

# 参考
Djangoの環境設定

https://docs.djangoproject.com/ja/4.2/intro/tutorial01/

DjangoのCORS導入

https://kosuke-space.com/django-rest-framework-cors