自由にDRFのシリアライザーを定義するrestframework-definable-serializerを作った

この記事は Django Advent Calendar 2017 9日目の記事です。

django-restframeworkのモデルシリアライザーは非常に強力な機能。だけど、シリアライザーに変更が入ると必然的にモデルを変更を強いられます。モデルの変更が入れば必然的にデプロイ作業が必須になります。もう深夜作業はいやだ！！

そんな人に向けて作ったライブラリをご紹介させていただきたいと思います。

# TL;DR
- ノーモア無駄なデプロイ&無駄なモデルのマイグレーション作業！！
- YAMLやJSONでシリアライザーを定義していつでも定義を変更可能にしてノーモアデプロイ＆マイグレーション作業！
- [JSON/YAMLでシリアライザーを定義できるrestframework-definable-serializerを考えてみた](https://qiita.com/salexkidd@github/items/34c2027a39acd1b0b963)を実装・公開したのご紹介

ようはAdmin画面でシリアライザーの定義を流し込んで動的に生成するというお話です。

<blockquote class="twitter-tweet" data-lang="ja"><p lang="und" dir="ltr"><a href="https://t.co/LeitqBH9Tp">https://t.co/LeitqBH9Tp</a></p>&mdash; salexkidd (@salexkidd) <a href="https://twitter.com/salexkidd/status/936900633747013633?ref_src=twsrc%5Etfw">2017年12月2日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

# restframework-definable-serializerを作ったよ

> 営業「アンケート作ってや」
> PG「OK（ごそごそ）。つくったよ！」
> 営業「アリガト！」　

そして数日後…

> 営業「あのアンケートに動物が好き？っていれてや」
> PG　「OK（ごそごそ）いれた！　けどデプロイは今夜な」
> 営業「まじかよすぐやってや」
> PG「無理ンゴ。マイグレーション必須だから深夜作業必須やで」
> 営業「クソやな」
> PG「…」

そして数日後…

> 営業「この前入れたやつやっぱいらへからはずしてや。んで好きな食べ物は？ってのいれてや」
> PG「殺るしかない。このビッグウェーブに・・・！！！」

こんな経験、プログラマーなら誰しもが通る道。しかしこれは **容易に内容を変更できないものを用意してしまった我々のせいでもあります。**

この問題を解決するにはどうしたらいいのかを[考えてみました。](https://qiita.com/salexkidd@github/items/34c2027a39acd1b0b963)そして、実装してみました。

今回はrestframework-definable-serializerのご紹介をさせていただければとおもいます。


# 定義からシリアライザーを作ろう

> イヌも人も、夜は寝るもんだぜ、寝ろよ！ (MOTHER2のイヌのチビ)

細かい修正に追われると精神を消耗し、本当にやりたい作業ができなくなるもの。ましてやその修正末に待ち受ける深夜のデプロイ作業なんかをしてたら時間がもったいありません。そう、我々は叫ばなければなりません。

**ノーモア無駄なデプロイ&マイグレーション作業！**　

これらを減らすためにrestframework-definableserializerは作られました。上のような寸劇は、本当にどこの現場でも目にするものです。では、この問題を読み解くと一体どこに問題があるのでしょうか。それはモデルシリアライザーです。

**変更の多いシリアライザーをモデルシリアライザーをから生成してしまうから問題がおきるのです。** 
(それか営業の腐った脳みその問題かもしれません)

しかし、普通のシリアライザーで定義してもデプロイの手間は減るわけではありません。我々にはシステムをメンテナンスモードに落とさず、動的に変更可能なシリアライザーさえあればこの無駄なデプロイを回避することができるはずです。

では、動的にシリアライザーを作成するにはどうしたらいいでしょうか？それは、動的に変更可能な定義からシリアライザーを起こすことです。

そう、以下のようなYAMLやJSONで書かれた定義からシリアライザーを生成すればよいのです！

```yaml:test.yml
main:
  name: TestSerializer
  fields:
  - name: my_text_field
    field: CharField
    initial: We Love Django!!!
```

これを解釈し、シリアライザークラスとして示すと以下のようになります。

```python:t.py
class TestSerializer(serializers.Serializer):
　　　　my_text_field = models.CharField(initial="We Love Django!!!!")
```

そして、上記のYAMLをADMIN画面で変更可能にする仕組みを作れば、我々は動的にシリアライザーを変更して提供をすることができるようになるはずです！

で、こちらが実際に作ったものになります。

<blockquote class="twitter-tweet" data-lang="ja"><p lang="und" dir="ltr"><a href="https://t.co/LeitqBH9Tp">https://t.co/LeitqBH9Tp</a></p>&mdash; salexkidd (@salexkidd) <a href="https://twitter.com/salexkidd/status/936900633747013633?ref_src=twsrc%5Etfw">2017年12月2日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

もちろん動的に変更可能なので、フィールドの追加や削除も自由自在！

<blockquote class="twitter-tweet" data-lang="ja"><p lang="und" dir="ltr"><a href="https://t.co/pb3cohbUFg">https://t.co/pb3cohbUFg</a></p>&mdash; salexkidd (@salexkidd) <a href="https://twitter.com/salexkidd/status/936900661198884865?ref_src=twsrc%5Etfw">2017年12月2日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

これで早くおうちにかえれるね！やったぜベイビー！

# リポジトリとかドキュメントとか
github: [https://github.com/salexkidd/restframework-definable-serializer](https://github.com/salexkidd/restframework-definable-serializer)
READ THE DOCS: [http://restframework-definable-serializer.readthedocs.io/ja/latest/](http://restframework-definable-serializer.readthedocs.io/ja/latest/)
PyPI: [https://pypi.python.org/pypi/restframework-definable-serializer](https://pypi.python.org/pypi/restframework-definable-serializer)

あとデモ用のアプリケーションあります！
[https://github.com/salexkidd/restframework-definable-serializer-example](https://github.com/salexkidd/restframework-definable-serializer-example)

docker-compose ですぐに試してもらうことができますよー

# まとめ
- 変更がガンガンかかるシリアライザーにモデルシリアライザー使うと死ぬ
- 動的に変更可能なシリアライザー定義から起こせば死なない！
- 頑張って作ったから誰か見て・・・あと英語版のドキュメントのコントリビューターおまちしております。