Django + REST Framework + GAE (+ Cloud Storage + Firebase Authentication )を始めるときに読む資料

Pythonを使ってミニマルにAPIの開発をするなら、`Django + REST Framework + GAE` がとても便利です。この構成で始めるときに役立つ資料をまとめました。

Pythonもこれからという場合は、以下も参考にしてください。

[Pythonを始めるときに読む資料 - Qiita](https://qiita.com/d_forest/items/eaeb25278bec1833c7ed)

# Django

[Djangoの紹介](https://developer.mozilla.org/ja/docs/Learn/Server-side/Django/Introduction)

## 公式ドキュメント

Djangoは公式ドキュメントが非常に充実しているので、迷ったらまずは公式ドキュメントを読むのがおすすめです。

[Django 2.2 日本語ドキュメント](https://docs.djangoproject.com/ja/2.2/)

場合によっては内部のコードを読んだほうが理解が早い場合もあります。認証モデル周りは、書き方の参考にもなります。

[django/django](https://github.com/django/django)

## TIPS

[Django ベスト・プラクティス - Qiita](https://qiita.com/F_clef/items/687e79691d3aa961cbd7)

[Djangoプロジェクト構造のカスタマイズ（分割と構造化） - Qiita](https://qiita.com/aion/items/ca375efac5b90deed382)

## Django + REST Framework のチュートリアル

REST Frameworkで何が便利になるのかがよくわかります。

[Django REST Frameworkを使って爆速でAPIを実装する - Qiita](https://qiita.com/kimihiro_n/items/86e0a9e619720e57ecd8)


# REST Framework

## 公式ドキュメント

REST Frameworkも公式ドキュメントが充実しているので、迷ったらまずは見ましょう。

[Django REST framework](https://www.django-rest-framework.org/)

こちらもコードを読むと書き方の参考になります。

[encode/django-rest-framework](https://github.com/encode/django-rest-framework)

## TIPS

[Django REST framework 知っておくと少し役に立つ　小技まとめ - Qiita](https://qiita.com/ryo-ma/items/a0cc41a002ed82510b2b)

# Djangoのモデル

Djangoは他のフレームワークに比べてモデル周りの規約の理解が必要です。

## Model

[Djangoのモデルにcreated_at,updated_atを実装する](https://webty.jp/staffblog/production/post-622/)

## Manager

[DjangoのCustom ManagerとCustom QuerySetについて - Qiita](https://qiita.com/massa142/items/cc590bf12f354b82ab73)

## Query Set

[DjangoのQuerySetのfilterメソッドの使い方まとめ | CodeLab](https://codelab.website/django-queryset-filter/)


## Migrations

[Djangoのマイグレーションをロールバック、元に戻す方法](https://hodalog.com/how-to-revert-migrations/)

```
python manage.py migrate APP_NAME zero
```

# MySql

Djangoの推奨はmysqlclientです。

[Databases | Django documentation | Django](https://docs.djangoproject.com/en/2.2/ref/databases/#mysql-db-api-drivers)

ただ、「Python Mysql」と検索してたどり着く記事はPyMySqlが使われていたりします。

## PyMySQL

[Djangoでmysqlに接続 - Qiita](https://qiita.com/salvage0707/items/2713d062971d528ab211)

[[Python+MySQL] RuntimeError: cryptography is required - ITips](https://itips.krsw.biz/python-mysql-runtime-error-cryptography-required/)

ここで注意しなければならないのが、現時点でPyMySqlがDjango2.2に対応できていません。

[Django2.2 はPyMySqlに対応していません](https://sleepless-se.net/2019/04/15/django-2-2-no-support-pymysql/)

そのため、PyMySqlを入れた場合は、mysqlclientに変更する必要があります。

## PyMySqlからmysqlclientへの変更

[Django: エラー解決法 "raise ImproperlyConfigured('mysqlclient 1.3.13 or newer is required; 〜) django.core.exceptions.ImproperlyConfigured: 〜" | Yukun's Blog](https://yukun.info/django-mysqlclient-error/)

# 認証

認証周りはDjangoが予め用意しているフレームワークもあったりで多少ややこしくなっています。とくにFirebase Authenticationや独自のモデルを使いたい場合などはカスタマイズが必要になります。

## 公式ドキュメント

[Django の認証方法のカスタマイズ - 公式ドキュメント](https://docs.djangoproject.com/ja/2.1/topics/auth/customizing/)

[認証周りのコード - django/django](https://github.com/django/django/blob/master/django/contrib/auth/models.py)

## 参考記事

[Django ユーザー カスタマイズ方法 - Qiita](https://qiita.com/okoppe8/items/10ae61808dc3056f9c8e)

[ジャンゴ(django)のカスタムユーザーモデル(Custom User Model)](https://dev-yakuza.github.io/django/custom-user-model/)


## Django + REST Framework + Firebase Authentication

Firebase Authenticationを使う場合は、`クライアントでToken取得 → サーバーで検証して一致するUserの取得`という実装が必要になります。

[Verify ID Tokens | Firebase](https://firebase.google.com/docs/auth/admin/verify-id-tokens)

以下記事が具体的な手順の参考になります。

[Django REST Frameworkでユーザ認証周りのAPIを作る - Qiita](https://qiita.com/xKxAxKx/items/60e8fb93d6bbeebcf065)

[Firebase Integration with Django REST - Stack Overflow](https://stackoverflow.com/questions/52428501/firebase-integration-with-django-rest)

### サードパーティーライブラリ

Django + REST Framework + Firebase Authenticationで動作するサードパーティーのライブラリです。Token認証周りを任せられるので便利です。

[garyburgmann/drf-firebase-auth](https://github.com/garyburgmann/drf-firebase-auth)

### Firebase Authenticationユーザーの各プロパティ取得方法

[firebase/firebase-admin-python](https://github.com/firebase/firebase-admin-python/blob/master/firebase_admin/_user_mgt.py#L131)

# GAE for Django

GAEでDjangoを動かすには公式ドキュメントを参考に、必要な設定をプロジェクトに追加します。

[Django スタートガイド | Python | Google Cloud](https://cloud.google.com/python/django/?hl=ja)

[GoogleCloudPlatform/python-docs-samples](https://github.com/GoogleCloudPlatform/python-docs-samples/tree/master/appengine/standard_python37)

requirements.txtやapp.yamlに必要な記述がなかったりすると下記エラーが出てハマるので、注意が必要です。

    Traceback (most recent call last): File "/env/lib/python3.7/site-packages/gunicorn/arbiter.py", line 583, in spawn_worker worker.init_process() File "/env/lib/python3.7/site-packages/gunicorn/workers/gthread.py", line 104, in init_process super(ThreadWorker, self).init_process() File "/env/lib/python3.7/site-packages/gunicorn/workers/base.py", line 129, in init_process self.load_wsgi() File "/env/lib/python3.7/site-packages/gunicorn/workers/base.py", line 138, in load_wsgi self.wsgi = self.app.wsgi() File "/env/lib/python3.7/site-packages/gunicorn/app/base.py", line 67, in wsgi self.callable = self.load() File "/env/lib/python3.7/site-packages/gunicorn/app/wsgiapp.py", line 52, in load return self.load_wsgiapp() File "/env/lib/python3.7/site-packages/gunicorn/app/wsgiapp.py", line 41, in load_wsgiapp return util.import_app(self.app_uri) File "/env/lib/python3.7/site-packages/gunicorn/util.py", line 350, in import_app __import__(module) ModuleNotFoundError: No module named 'main'

[GAE standard環境にて Python3 + Djangoでサーバを構築する - Qiita](https://qiita.com/gansoishiyakibibinba/items/1917271380ab58be2625#3-1-appyaml)

# Cloud Storage

Firebase Authenticationから取得したプロフィール画像などを保存するのにCloud Storageを使います。

[Google Cloud Storage - django-storages 1.7.1 documentation](https://django-storages.readthedocs.io/en/latest/backends/gcloud.html)

## URLから画像を取得

Firebase Authenticationからは画像URLが提供されるので、それをダウンロードした上でCloud Storageに入れる必要があります。URLからの画像保存はメモリに展開後、DjangoStorageに渡します。

[Django pattern: download to FileField](https://goodcode.io/articles/django-download-url-to-file-field/)

python3でurlretrieveの返り値が変わっおり、下記のコードだとエラーになります。古い記事のときは注意が必要です。↑の返り値が正しいです。

[Django save image from url and connect with ImageField](https://stackoverflow.com/questions/16381241/django-save-image-from-url-and-connect-with-imagefield)

# Visual Studio Code

VSCodeを使ってて気になった部分を参考程度に載せておきます。

[Djangoのmodel参照時のpylintの警告を出さないようにする - Qiita](https://qiita.com/RyoMa_0923/items/d0c2613f15dd98280121)

[VScodeのインデント幅を言語毎に指定する - Qiita](https://qiita.com/kenkono/items/85fd0f15bcec0ac64605)

[【pylint】 出力結果の警告についての備忘録 - Qiita](https://qiita.com/ryu1_f/items/6598e847e0323d66aa81)