0
0

Django カスタムメソッドでシリアライズして返す方法 そしてmany=Trueとは

Posted at

TL;DR

  • many=Trueが指定されると、Serializerクラスの__new__メソッドでそれが確認され、ListSerializerのインスタンスが生成されます。
  • ListSerializerはリスト内の各オブジェクトをシリアライズするために使用されます。
  • ListSerializerはBaseSerializerおよびSerializerクラスから自動的に呼び出されます。
rest_framework/serializers.py
class BaseSerializer(Field):
    # ~~ 省略 ~~
    def __new__(cls, *args, **kwargs):
        # We override this method in order to automatically create
        # `ListSerializer` classes instead when `many=True` is set.
        if kwargs.pop('many', False):#こいつだ!!!
            return cls.many_init(*args, **kwargs)
        return super().__new__(cls, *args, **kwargs)

カスタムメソッド

models.py
from django.db import models
class Books(models.Model):
    hcode = models.CharField(primary_key=True, max_length=13)
    hname = models.CharField(max_length=30, blank=True, null=True)
views.py
from django.shortcuts import render
from rest_framework.decorators import action
from rest_framework import viewsets,response
from .models import Books
from .serializers import BookSerializer

class BooksAPIView(viewsets.ModelViewSet):
    queryset = Books.objects.db_manager("sqlserver").all()
    serializer_class = BookSerializer

    # カスタムアクション
    @action(detail=False, methods=['get'])
    def custom_action(self, request):
        hcode :str = request.GET.get('hcode', None)
        fmthcode :str = ('5'+(('000000000000'+hcode)[-12:]))
        d = Books.objects.db_manager("sqlserver").filter(hcode=fmthcode)
        s = BookSerializer(d,many=True) # filterやallにより戻り値がListの場合はmany=Trueを指定する
        return response.Response({"data": s.data})
urls.py
from django.urls import path,include
from rest_framework import routers
from .views import BooksAPIView

router = routers.DefaultRouter()
router.register('books', BooksAPIView)

urlpatterns = [
    path('', include(router.urls)),
    # 他のルートもここに追加する場合があります
]
  • http://127.0.0.1:8000/api/books/:通常このアドレスにアクセスすると一覧が取得される(Listが帰ってくる)
  • http://127.0.0.1:8000/api/books/custom_action?hcode=30000:このアドレスにアクセスするとCRUD以外のviews.pyで定義したアクションを呼び出す事ができる

シリアライズしてレスポンスを返す方法

querysetの結果が一つの場合

views.py
queryset = Books.objects.db_manager("sqlserver").get(pk=1)
result = BookSerializer(queryset)
return response.Response({"data": result})

複数の場合

  • よくわからない引数をシリアライザに渡している...
views.py
queryset = Books.objects.db_manager("sqlserver").all()
result = BookSerializer(queryset,many=True)# many = Trueとはなんだ?
return response.Response({"data": result.data}) # .dataが必要だよ
  • そこで調べてみると・・・rest_framework/serializers.pyの中にいました。
rest_framework/serializers.py
class BaseSerializer(Field):
    # ~~ 省略 ~~
    def __new__(cls, *args, **kwargs):
        # We override this method in order to automatically create
        # `ListSerializer` classes instead when `many=True` is set.
        if kwargs.pop('many', False):#こいつだ!!!
            return cls.many_init(*args, **kwargs)
        return super().__new__(cls, *args, **kwargs)
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0