【学習記録】Django REST frameworkチュートリアル3 Serializerなど

この記事の続きです。

programming-gogogogo.hatenablog.com

こちらの動画を見ながらPythonDjango REST framework(DRF)について勉強しています。

www.youtube.com

Articleモデルのマイグレーションまで実行した後、admin.pyにArticleモデルを追記して、Djangoの管理画面でもArticleモデルを表示できるようにします。

api_basic/admin.py

from django.contrib import admin
from .models import Article

admin.site.register(Article)

f:id:JunpeiNakasone:20210313154420p:plain

admin.pyを上記内容にしてローカルサーバーを以下のコマンドで再起動するとlocalhost:8000/adminで管理画面にArticleが追加されているのが確認できます。

python manage.py runserver 0:8000

f:id:JunpeiNakasone:20210313154615p:plain

次にSerializerを実装していきます。

公式ドキュメントでのSerializerについての説明はこちらです。 www.django-rest-framework.org

内容としてはSerializerはpythonインスタンスのデータをjsonなどに変換してクライアントに返すことをSerializingと呼ぶらしいです。
->このあたりは理解浅いので要勉強。とりあえず現時点ではGoでのmarshal/unmarshalと同じようなものと推測しておく。

api_basicディレクトリにserializer.pyを新規追加し、以下のArticleSerializerクラスを定義します。
(モデルの定義を呼び出せば各フィールドを全部書く必要はないけど確認のためひとつずつ記述しています)

serializers.py

from rest_framework import serializers
from .models import Article


class ArticleSerializer(serializers.Serializer):
    title = serializers.CharField(max_length=100)
    author = serializers.CharField(max_length=100)
    email = serializers.EmailField(max_length=100)
    date = serializers.DateTimeField()

    def create(self, validated_data):
        return Article.objects.create(validated_data)

    def update(self, instance, validated_data):
        instance.title = validated_data.get('title', instance.title)
        instance.author = validated_data.get('author', instance.author)
        instance.email = validated_data.get('email', instance.email)
        instance.date = validated_data.get('date', instance.date)
        instance.save()
        return instance

f:id:JunpeiNakasone:20210313165312p:plain

次にDjangoのshellから対話式にコードを入力し動作を確認します。
以下のコマンドを実行してshellモードにします。

python manage.py shell

f:id:JunpeiNakasone:20210313165601p:plain

ターミナルに以下の内容で入力します。

>>> from api_basic.models import Article
>>> from api_basic.serializers import ArticleSerializer
>>> from rest_framework.renderers import JSONRenderer
>>> from rest_framework.parsers import JSONParser
>>> a = Article(title = 'Article_a', author = 'author_a', email 
= 'a@email.com')
>>> a.save()

上記内容でデータが登録されていることを管理画面から確認します。
f:id:JunpeiNakasone:20210313170150p:plain

次に以下のようにコードを入力するとpythonの辞書型でデータが出力されます。

serializer_a = ArticleSerializer(a)
>>> serializer_a.data
{'title': 'Article_a', 'author': 'author_a', 'email': 'a@email.c
om', 'date': '2021-03-13T08:00:18.044248Z'}

f:id:JunpeiNakasone:20210313170616p:plain

この時点ではまだJSONになっていないので下記のコードを入力することでJSONで出力されます。

>>> json_a = JSONRenderer().render(serializer_a.data)
>>> json_a
b'{"title":"Article_a","author":"author_a","email":"a@email.com","date":"2021-03-13T08:00:18.044248Z"}'

f:id:JunpeiNakasone:20210313170843p:plain

また、以下のようにコードを記述するとモデルの全データを取得できます。

>>> serializer_all = ArticleSerializer(Article.objects.all(), many=True)
>>> serializer_all.data
[OrderedDict([('title', 'Articletitle1'), ('author', 'testauthor'), ('email', 'test@email.com'), ('date', '2021-03-13T07:01:44.309453Z')]), OrderedDict([('title', 't'), ('author', 'a'), ('email', ''), ('date', '2021-03-13T07:07:35.029618Z')]), OrderedDict([('title', 'ctitle'), ('author', 'cauthor'), ('email', 'c@email.com'), ('date', '2021-03-13T07:11:17.787088Z')]), OrderedDict([('title', 'etitle'), ('author', 'eauthor'), ('email', 'e@email.com'), ('date', '2021-03-13T07:15:28.921016Z')]), OrderedDict([('title', 'Article_a'), ('author', 'author_a'), ('email', 'a@email.com'), ('date', '2021-03-13T08:00:18.044248Z')])]

f:id:JunpeiNakasone:20210313171127p:plain

many=Trueの意味がまだわかっておらず、試しにmany=True無しで以下のように実行したところエラーになりました。

>>> serializer_fail = ArticleSerializer(Article.objects.all())>>> serializer_fail.data

出力されたエラー文を抜粋

AttributeError: Got AttributeError when attempting to get a value for field `title` on serializer `ArticleSerializer`.
The serializer field might be named incorrectly and not match any attribute or key on the `QuerySet` instance.
Original exception text was: 'QuerySet' object has no attribute 'title'.

動くコードのどの部分をどう変更したらどういうエラーが出た、みたいな確認はどんどんやって少しずつ理解を深めていけるようにしたいと思います。