前回は、開発環境の構築まで行いました。本日は、Django Rest Frameworkのシリアライズについて学びます。
前回
シリアライズとは
シリアライズとは、DjangoのQuerySetsやモデルインスタンスをレンダリングしやすい形式にフォーマットすることを指します。
例えば、QuerySetsをPythonの基本データ型に変換し、最終的にJSONにすることも可能です。
デシリアライズはその逆で、JSONなどのデータをpythonが扱えるデータ形式に変換することを指します。
通常、APIとブラウザ間のデータのやり取りには、それぞれが処理できるデータ形式に変換(シリアライズ/デシリアライズ)する必要があります。
DjangoのQuerySetsをブラウザが受け取っても処理はできないですし、その逆もまた然りなのです。
シリアライズクラスの実装
Django Rest Frameworkでは、Serializersクラスを提供しています。
このクラスを使って、シリアライズを実装してみましょう。
まずは、ディレクトリとファイルを用意します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
mkdir news/api touch news/api/serializers.py $ tree . ├── db.sqlite3 ├── manage.py ├── news │ ├── __init__.py │ ├── __pycache__ │ │ ├── __init__.cpython-37.pyc │ │ ├── admin.cpython-37.pyc │ │ └── models.cpython-37.pyc │ ├── admin.py │ ├── api # new │ │ └── serializers.py │ ├── apps.py │ ├── migrations │ │ ├── 0001_initial.py │ │ ├── __init__.py │ │ └── __pycache__ │ │ ├── 0001_initial.cpython-37.pyc │ │ └── __init__.cpython-37.pyc │ ├── models.py │ ├── tests.py │ └── views.py └── selfnote_api ├── __init__.py ├── __pycache__ │ ├── __init__.cpython-37.pyc │ ├── settings.cpython-37.pyc │ ├── urls.cpython-37.pyc │ └── wsgi.cpython-37.pyc ├── asgi.py ├── settings.py ├── urls.py └── wsgi.py |
続いて、シリアライズクラスを実装します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
# news/api/serializers.py from rest_framework import serializers from news.models import Article class ArticleSerializer(serializers.Serializer): """Article Serializer """ id = serializers.IntegerField(read_only=True) author = serializers.CharField() title = serializers.CharField() body = serializers.CharField() location = serializers.CharField() publication_date = serializers.DateField() active = serializers.BooleanField() created_at = serializers.DateTimeField(read_only=True) updated_at = serializers.DateTimeField(read_only=True) def create(self, validate_data): print(validate_data) return Article.objects.create(**validate_data) def update(self, instance, validated_data): instance.author = validated_data.get( 'author', instance.author) instance.title = validated_data.get( 'title', instance.title) instance.description = validated_data.get( 'description', instance.description) instance.body = validated_data.get( 'body', instance.body) instance.location = validated_data.get( 'location', instance.location) instance.publication_date = validated_data.get( 'publication_date', instance.publication_date) instance.active = validated_data.get( 'active', instance.active) instance.save() return instance |
上記のコードでは、Serializerクラスを継承したArticleSerializerクラスを定義しています。
そして、フィールド(idやauthorなど)は、Articleモデルと同じフィールド名を指定しています。
また、create, updateは、Serializerクラスのcreateとupdateをオーバーライドしています。
Articleデータの作成
python manage.py shellからArticleデータを作成しましょう。
1 2 3 4 5 |
python manage.py shell import timedate from news.models import Article Article.objects.create(author="selfnote", title="first post", body="this is a first post", location="tokyo", publication_date=datetime.datetime.now()) exec() |
シリアライズクラスの検証
先ほど作成したArticleSerializerを検証してみましょう。
1 2 3 4 5 6 7 8 |
python manage.py shell from news.api.serializers import ArticleSerializer from news.models import Article a_instance = Article.objects.first() >>> a_instance <Article: selfnote first post> |
上記では、DjangoのテーブルからArticleクラスを取得しました。
これをシリアライズクラスに渡します。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
serializer = ArticleSerializer(a_instance) >>> serializer ArticleSerializer(<Article: selfnote first post>): id = IntegerField(read_only=True) author = CharField() title = CharField() body = CharField() location = CharField() publication_date = DateField() active = BooleanField() created_at = DateTimeField(read_only=True) updated_at = DateTimeField(read_only=True) |
上記が、Article instanceです。Django Classなどの複雑なデータをPythonの基本データ型に変換してくれます。
1 2 3 |
serializer.data {'id': 1, 'author': 'selfnote', 'title': 'first post', 'body': 'this is a first post', 'location': 'tokyo', 'publication_date': '2020-05-22', 'active': True, 'created_at': '2020-05-22T02:46:11.609404Z', 'updated_at': '2020-05-22T02:46:11.609436Z'} |
これがシリアライズです。あとは、このデータをJSON形式にフォーマットしてあげれば良いわけです。
1 2 3 4 5 |
from rest_framework.renderers import JSONRenderer json = JSONRenderer().render(serializer.data) >>> json b'{"id":1,"author":"selfnote","title":"first post","body":"this is a first post","location":"tokyo","publication_date":"2020-05-22","active":true,"created_at":"2020-05-22T02:46:11.609404Z","updated_at":"2020-05-22T02:46:11.609436Z"}' |
APIとフロントのデータ間のやり取りは、 byteに変換されるため、
が先頭についてます。b
一方、byteに変換されたJSONをAPI側で受け取る場合は、以下の方法を用います。
1 2 3 4 5 6 7 |
>>> import io >>> from rest_framework.parsers import JSONParser >>> stream = io.BytesIO(json) >>> data = JSONParser().parse(stream) >>> data {'id': 1, 'author': 'selfnote', 'title': 'first post', 'body': 'this is a first post', 'location': 'tokyo', 'publication_date': '2020-05-22', 'active': True, 'created_at': '2020-05-22T02:46:11.609404Z', 'updated_at': '2020-05-22T02:46:11.609436Z'} |
ちなみに、シリアライズクラスにデータを渡すと自動的にバリデーションチェックを実行します。
1 2 3 |
serializer = ArticleSerializer(data=data) serializer.is_valid() True |
バリデーションチェックがOKの場合、シリアライズクラスのvalidated_dataからデータを取得できます。
1 2 3 4 |
serializer.validated_data OrderedDict([('author', 'selfnote'), ('title', 'first post'), ('body', 'this is a first post'), ('location', 'tokyo'), ('publication_date', datetime.date(2020, 5, 22)), ('active', True)]) |
saveメソッドを使用すると保存もできます。
1 2 3 4 5 6 7 8 |
serializer.save() {'author': 'selfnote', 'title': 'first post', 'body': 'this is a first post', 'location': 'tokyo', 'publication_date': datetime.date(2020, 5, 22), 'active': True} <Article: selfnote first post> Article.objects.all().count() 2 <<< articleが一つ増えている |
次回
次回は、API Viewについて学んでいきましょう。
関連
こちらもどうぞ
Djangoおすすめ書籍
Djangoを学ぶなら以下の書籍がオススメです。
緑 -> 赤 -> 紫の順でやればOKです。読みやすい英語で書かれているので、英語力もついでに上がるかもしれません^^
[…] Django Rest Frameworkを学ぼう! ~シリアライズについて~ […]