serializers.py

シリアライザー

シリアライザーの有用性を拡張することは、私たちが取り組みたいことの一つです。しかし、それは簡単な問題ではなく、本格的な設計作業が必要になります。

— Russell Keith-Magee, Django users group

シリアライザーを使用すると、クエリセットやモデルインスタンスなどの複雑なデータを、JSONXML、またはその他のコンテンツタイプに簡単にレンダリングできるネイティブPythonデータ型に変換できます。シリアライザーは、パースされたデータを受信データが最初に検証された後、複雑な型に変換し直すことができるデシリアライズも提供します。

REST frameworkのシリアライザーは、DjangoのFormおよびModelFormクラスと非常によく似た動作をします。レスポンスの出力を強力かつ汎用的に制御できるSerializerクラスと、モデルインスタンスおよびクエリセットを処理するシリアライザーを作成するための便利なショートカットを提供するModelSerializerクラスを提供します。

シリアライザーの宣言

まず、例として使用できる簡単なオブジェクトを作成しましょう

from datetime import datetime

class Comment:
    def __init__(self, email, content, created=None):
        self.email = email
        self.content = content
        self.created = created or datetime.now()

comment = Comment(email='leila@example.com', content='foo bar')

Commentオブジェクトに対応するデータをシリアライズおよびデシリアライズするために使用できるシリアライザーを宣言します。

シリアライザーの宣言は、フォームの宣言と非常によく似ています

from rest_framework import serializers

class CommentSerializer(serializers.Serializer):
    email = serializers.EmailField()
    content = serializers.CharField(max_length=200)
    created = serializers.DateTimeField()

オブジェクトのシリアライズ

これで、CommentSerializerを使用して、コメントまたはコメントのリストをシリアライズできます。ここでも、Serializerクラスの使用はFormクラスの使用によく似ています。

serializer = CommentSerializer(comment)
serializer.data
# {'email': 'leila@example.com', 'content': 'foo bar', 'created': '2016-01-27T15:17:10.375877'}

この時点で、モデルインスタンスをPythonネイティブデータ型に変換しました。シリアライゼーションプロセスを完了するには、データをjsonにレンダリングします。

from rest_framework.renderers import JSONRenderer

json = JSONRenderer().render(serializer.data)
json
# b'{"email":"leila@example.com","content":"foo bar","created":"2016-01-27T15:17:10.375877"}'

オブジェクトのデシリアライズ

デシリアライゼーションも同様です。最初に、ストリームをPythonネイティブデータ型にパースします...

import io
from rest_framework.parsers import JSONParser

stream = io.BytesIO(json)
data = JSONParser().parse(stream)

...次に、これらのネイティブデータ型を検証済みデータの辞書に復元します。

serializer = CommentSerializer(data=data)
serializer.is_valid()
# True
serializer.validated_data
# {'content': 'foo bar', 'email': 'leila@example.com', 'created': datetime.datetime(2012, 08, 22, 16, 20, 09, 822243)}

インスタンスの保存

検証済みデータに基づいて完全なオブジェクトインスタンスを返せるようにするには、.create()メソッドと.update()メソッドのいずれかまたは両方を実装する必要があります。たとえば

class CommentSerializer(serializers.Serializer):
    email = serializers.EmailField()
    content = serializers.CharField(max_length=200)
    created = serializers.DateTimeField()

    def create(self, validated_data):
        return Comment(**validated_data)

    def update(self, instance, validated_data):
        instance.email = validated_data.get('email', instance.email)
        instance.content = validated_data.get('content', instance.content)
        instance.created = validated_data.get('created', instance.created)
        return instance

オブジェクトインスタンスがDjangoモデルに対応している場合は、これらのメソッドがオブジェクトをデータベースに保存するようにする必要があります。たとえば、CommentがDjangoモデルの場合、メソッドは次のようになります。

    def create(self, validated_data):
        return Comment.objects.create(**validated_data)

    def update(self, instance, validated_data):
        instance.email = validated_data.get('email', instance.email)
        instance.content = validated_data.get('content', instance.content)
        instance.created = validated_data.get('created', instance.created)
        instance.save()
        return instance

これで、データをデシリアライズするときに、検証済みデータに基づいてオブジェクトインスタンスを返すために.save()を呼び出すことができます。

comment = serializer.save()

.save()を呼び出すと、シリアライザークラスのインスタンス化時に既存のインスタンスが渡されたかどうかに応じて、新しいインスタンスが作成されるか、既存のインスタンスが更新されます。

# .save() will create a new instance.
serializer = CommentSerializer(data=data)

# .save() will update the existing `comment` instance.
serializer = CommentSerializer(comment, data=data)

.create()メソッドと.update()メソッドは両方ともオプションです。シリアライザークラスのユースケースに応じて、いずれも実装しないか、いずれか1つまたは両方を実装できます。

.save()に追加の属性を渡す

インスタンスを保存するときに、ビューコードが追加のデータをインジェクトできるようにしたい場合があります。この追加データには、現在のユーザー、現在の時刻、またはリクエストデータの一部ではないその他の情報を含めることができます。

.save()を呼び出すときに追加のキーワード引数を含めることで、それを行うことができます。たとえば

serializer.save(owner=request.user)

追加のキーワード引数は、.create()または.update()が呼び出されるときに、validated_data引数に含められます。

.save()を直接オーバーライドする。

場合によっては、.create()メソッドと.update()メソッドの名前が意味を持たない場合があります。たとえば、お問い合わせフォームでは、新しいインスタンスを作成するのではなく、メールやその他のメッセージを送信する場合があります。

このような場合は、より読みやすく意味のあるものとして、代わりに.save()を直接オーバーライドすることを選択できます。

たとえば

class ContactForm(serializers.Serializer):
    email = serializers.EmailField()
    message = serializers.CharField()

    def save(self):
        email = self.validated_data['email']
        message = self.validated_data['message']
        send_email(from=email, message=message)

上記の例では、シリアライザーの.validated_dataプロパティに直接アクセスする必要があることに注意してください。

バリデーション

データをデシリアライズするときは、検証済みデータにアクセスしたり、オブジェクトインスタンスを保存したりする前に、常にis_valid()を呼び出す必要があります。検証エラーが発生した場合、.errorsプロパティには、結果のエラーメッセージを表す辞書が含まれます。たとえば

serializer = CommentSerializer(data={'email': 'foobar', 'content': 'baz'})
serializer.is_valid()
# False
serializer.errors
# {'email': ['Enter a valid e-mail address.'], 'created': ['This field is required.']}

辞書の各キーはフィールド名になり、値は、そのフィールドに対応するエラーメッセージの文字列のリストになります。non_field_errorsキーも存在する可能性があり、一般的な検証エラーがリストされます。non_field_errorsキーの名前は、NON_FIELD_ERRORS_KEY REST framework設定を使用してカスタマイズできます。

項目のリストをデシリアライズすると、エラーは、デシリアライズされた各項目を表す辞書のリストとして返されます。

無効なデータで例外を発生させる

.is_valid()メソッドは、検証エラーがある場合にserializers.ValidationError例外を発生させるオプションのraise_exceptionフラグを取ります。

これらの例外は、REST frameworkが提供するデフォルトの例外ハンドラーによって自動的に処理され、デフォルトでHTTP 400 Bad Requestレスポンスを返します。

# Return a 400 response if the data was invalid.
serializer.is_valid(raise_exception=True)

フィールドレベルのバリデーション

.validate_<field_name>メソッドをSerializerサブクラスに追加することで、カスタムのフィールドレベルのバリデーションを指定できます。これらは、Djangoフォームの.clean_<field_name>メソッドに似ています。

これらのメソッドは、検証が必要なフィールド値である単一の引数を取ります。

validate_<field_name>メソッドは、検証済みの値を返すか、serializers.ValidationErrorを発生させる必要があります。たとえば

from rest_framework import serializers

class BlogPostSerializer(serializers.Serializer):
    title = serializers.CharField(max_length=100)
    content = serializers.CharField()

    def validate_title(self, value):
        """
        Check that the blog post is about Django.
        """
        if 'django' not in value.lower():
            raise serializers.ValidationError("Blog post is not about Django")
        return value

注: <field_name>がシリアライザーでパラメータrequired=Falseで宣言されている場合、フィールドが含まれていない場合、この検証ステップは実行されません。


オブジェクトレベルのバリデーション

複数のフィールドへのアクセスを必要とするその他の検証を行うには、.validate()というメソッドをSerializerサブクラスに追加します。このメソッドは、フィールド値の辞書である単一の引数を受け取ります。必要に応じてserializers.ValidationErrorを発生させるか、検証済みの値を返すだけです。たとえば

from rest_framework import serializers

class EventSerializer(serializers.Serializer):
    description = serializers.CharField(max_length=100)
    start = serializers.DateTimeField()
    finish = serializers.DateTimeField()

    def validate(self, data):
        """
        Check that start is before finish.
        """
        if data['start'] > data['finish']:
            raise serializers.ValidationError("finish must occur after start")
        return data

バリデーター

シリアライザーの個々のフィールドには、フィールドインスタンスで宣言することにより、バリデーターを含めることができます。たとえば

def multiple_of_ten(value):
    if value % 10 != 0:
        raise serializers.ValidationError('Not a multiple of ten')

class GameRecord(serializers.Serializer):
    score = serializers.IntegerField(validators=[multiple_of_ten])
    ...

シリアライザークラスには、フィールドデータの完全なセットに適用される再利用可能なバリデーターを含めることもできます。これらのバリデーターは、次のように、内部のMetaクラスで宣言することにより含められます

class EventSerializer(serializers.Serializer):
    name = serializers.CharField()
    room_number = serializers.IntegerField(choices=[101, 102, 103, 201])
    date = serializers.DateField()

    class Meta:
        # Each room only has one event per day.
        validators = [
            UniqueTogetherValidator(
                queryset=Event.objects.all(),
                fields=['room_number', 'date']
            )
        ]

詳細については、バリデーターのドキュメントを参照してください。

初期データとインスタンスへのアクセス

初期オブジェクトまたはクエリセットをシリアライザーインスタンスに渡すと、オブジェクトは.instanceとして使用できるようになります。初期オブジェクトが渡されない場合、.instance属性はNoneになります。

データをシリアライザーインスタンスに渡すと、変更されていないデータは.initial_dataとして使用できるようになります。dataキーワード引数が渡されない場合、.initial_data属性は存在しません。

部分更新

デフォルトでは、シリアライザーには、すべての必須フィールドの値が渡される必要があります。そうしないと、検証エラーが発生します。部分更新を許可するために、partial引数を使用できます。

# Update `comment` with partial data
serializer = CommentSerializer(comment, data={'content': 'foo bar'}, partial=True)

ネストされたオブジェクトの処理

前の例は、単純なデータ型のみを持つオブジェクトを処理する場合は問題ありませんが、オブジェクトの属性の一部が文字列、日付、整数などの単純なデータ型ではない、より複雑なオブジェクトを表す必要もある場合があります。

Serializerクラス自体がFieldの一種であり、オブジェクトタイプが別のオブジェクトタイプ内にネストされている関係を表すために使用できます。

class UserSerializer(serializers.Serializer):
    email = serializers.EmailField()
    username = serializers.CharField(max_length=100)

class CommentSerializer(serializers.Serializer):
    user = UserSerializer()
    content = serializers.CharField(max_length=200)
    created = serializers.DateTimeField()

ネストされた表現でNone値をオプションとして受け入れる場合は、ネストされたシリアライザーにrequired=Falseフラグを渡す必要があります。

class CommentSerializer(serializers.Serializer):
    user = UserSerializer(required=False)  # May be an anonymous user.
    content = serializers.CharField(max_length=200)
    created = serializers.DateTimeField()

同様に、ネストされた表現がアイテムのリストである必要がある場合は、ネストされたシリアライザーにmany=Trueフラグを渡す必要があります。

class CommentSerializer(serializers.Serializer):
    user = UserSerializer(required=False)
    edits = EditItemSerializer(many=True)  # A nested list of 'edit' items.
    content = serializers.CharField(max_length=200)
    created = serializers.DateTimeField()

書き込み可能なネストされた表現

データのデシリアライズをサポートするネストされた表現を扱う場合、ネストされたオブジェクトのエラーはすべて、ネストされたオブジェクトのフィールド名の下にネストされます。

serializer = CommentSerializer(data={'user': {'email': 'foobar', 'username': 'doe'}, 'content': 'baz'})
serializer.is_valid()
# False
serializer.errors
# {'user': {'email': ['Enter a valid e-mail address.']}, 'created': ['This field is required.']}

同様に、.validated_dataプロパティには、ネストされたデータ構造が含まれます。

ネストされた表現のための.create()メソッドの記述

書き込み可能なネストされた表現をサポートする場合は、複数のオブジェクトの保存を処理する.create()または.update()メソッドを記述する必要があります。

次の例は、ネストされたプロファイルオブジェクトを使用してユーザーを作成する方法を示しています。

class UserSerializer(serializers.ModelSerializer):
    profile = ProfileSerializer()

    class Meta:
        model = User
        fields = ['username', 'email', 'profile']

    def create(self, validated_data):
        profile_data = validated_data.pop('profile')
        user = User.objects.create(**validated_data)
        Profile.objects.create(user=user, **profile_data)
        return user

ネストされた表現のための.update()メソッドの記述

更新の場合、関係の更新をどのように処理するかを慎重に検討する必要があります。たとえば、関係のデータがNoneである場合、または提供されていない場合、次のうちどれが発生する必要がありますか?

  • データベース内の関係をNULLに設定します。
  • 関連付けられたインスタンスを削除します。
  • データを無視し、インスタンスをそのままにします。
  • 検証エラーを発生させます。

以前のUserSerializerクラスの.update()メソッドの例を次に示します。

    def update(self, instance, validated_data):
        profile_data = validated_data.pop('profile')
        # Unless the application properly enforces that this field is
        # always set, the following could raise a `DoesNotExist`, which
        # would need to be handled.
        profile = instance.profile

        instance.username = validated_data.get('username', instance.username)
        instance.email = validated_data.get('email', instance.email)
        instance.save()

        profile.is_premium_member = profile_data.get(
            'is_premium_member',
            profile.is_premium_member
        )
        profile.has_support_contract = profile_data.get(
            'has_support_contract',
            profile.has_support_contract
         )
        profile.save()

        return instance

ネストされた作成と更新の動作は曖昧になる可能性があり、関連するモデル間で複雑な依存関係が必要になる場合があるため、RESTフレームワーク3では、これらのメソッドを常に明示的に記述する必要があります。デフォルトのModelSerializer.create()および.update()メソッドには、書き込み可能なネストされた表現のサポートは含まれていません。

ただし、DRF Writable Nestedなどの自動書き込み可能なネストされた表現をサポートするサードパーティパッケージが利用可能です。

シリアライザーで複数の関連インスタンスを保存する代わりに、正しいインスタンスの作成を処理するカスタムモデルマネージャクラスを作成する方法があります。

たとえば、UserインスタンスとProfileインスタンスが常にペアとして一緒に作成されるようにする必要があるとします。次のようなカスタムマネージャクラスを作成できます。

class UserManager(models.Manager):
    ...

    def create(self, username, email, is_premium_member=False, has_support_contract=False):
        user = User(username=username, email=email)
        user.save()
        profile = Profile(
            user=user,
            is_premium_member=is_premium_member,
            has_support_contract=has_support_contract
        )
        profile.save()
        return user

このマネージャクラスは、ユーザーインスタンスとプロファイルインスタンスが常に同時に作成されることをより適切にカプセル化するようになりました。シリアライザークラスの.create()メソッドを、新しいマネージャメソッドを使用するように書き換えることができます。

def create(self, validated_data):
    return User.objects.create(
        username=validated_data['username'],
        email=validated_data['email'],
        is_premium_member=validated_data['profile']['is_premium_member'],
        has_support_contract=validated_data['profile']['has_support_contract']
    )

このアプローチの詳細については、Djangoドキュメントのモデルマネージャと、モデルクラスとマネージャクラスの使用に関するこのブログ記事を参照してください。

複数のオブジェクトの処理

Serializerクラスは、オブジェクトのリストのシリアライズまたはデシリアライズも処理できます。

複数のオブジェクトのシリアライズ

単一のオブジェクトインスタンスではなく、クエリセットまたはオブジェクトのリストをシリアライズするには、シリアライザーをインスタンス化するときにmany=Trueフラグを渡す必要があります。次に、シリアライズするクエリセットまたはオブジェクトのリストを渡すことができます。

queryset = Book.objects.all()
serializer = BookSerializer(queryset, many=True)
serializer.data
# [
#     {'id': 0, 'title': 'The electric kool-aid acid test', 'author': 'Tom Wolfe'},
#     {'id': 1, 'title': 'If this is a man', 'author': 'Primo Levi'},
#     {'id': 2, 'title': 'The wind-up bird chronicle', 'author': 'Haruki Murakami'}
# ]

複数のオブジェクトのデシリアライズ

複数のオブジェクトをデシリアライズするためのデフォルトの動作は、複数のオブジェクトの作成をサポートしますが、複数のオブジェクトの更新はサポートしません。これらのケースをサポートまたはカスタマイズする方法の詳細については、以下のListSerializerドキュメントを参照してください。

追加のコンテキストの組み込み

シリアライズするオブジェクトに加えて、追加のコンテキストをシリアライザーに提供する必要がある場合があります。一般的なケースの1つは、ハイパーリンクされた関係を含むシリアライザーを使用している場合です。これには、完全に修飾されたURLを適切に生成するために、シリアライザーが現在のリクエストにアクセスできる必要があります。

シリアライザーをインスタンス化するときにcontext引数を渡すことで、任意の追加のコンテキストを提供できます。例:

serializer = AccountSerializer(account, context={'request': request})
serializer.data
# {'id': 6, 'owner': 'denvercoder9', 'created': datetime.datetime(2013, 2, 12, 09, 44, 56, 678870), 'details': 'http://example.com/accounts/6/details'}

コンテキストディクショナリは、self.context属性にアクセスすることで、カスタムの.to_representation()メソッドなど、任意のシリアライザーフィールドロジック内で使用できます。


ModelSerializer

多くの場合、Djangoモデル定義に密接に対応するシリアライザークラスが必要になります。

ModelSerializerクラスは、モデルフィールドに対応するフィールドを持つSerializerクラスを自動的に作成できるショートカットを提供します。

ModelSerializerクラスは、通常のSerializerクラスと同じですが、次の点が異なります。:

  • モデルに基づいて、フィールドのセットを自動的に生成します。
  • unique_togetherバリデーターなどのシリアライザーのバリデーターを自動的に生成します。
  • .create()および.update()の単純なデフォルト実装が含まれています。

ModelSerializerの宣言は次のようになります。

class AccountSerializer(serializers.ModelSerializer):
    class Meta:
        model = Account
        fields = ['id', 'account_name', 'users', 'created']

デフォルトでは、クラスのすべてのモデルフィールドは、対応するシリアライザーフィールドにマップされます。

モデルの外部キーなどの関係は、PrimaryKeyRelatedFieldにマップされます。逆関係は、シリアライザー関係のドキュメントで指定されているように明示的に含めない限り、デフォルトでは含まれません。

ModelSerializerの検査

シリアライザークラスは、フィールドの状態を完全に検査できる便利な詳細表現文字列を生成します。これは、自動的に作成されるフィールドとバリデーターのセットを決定する場合に、ModelSerializersを使用する場合に特に役立ちます。

これを行うには、python manage.py shellを使用してDjangoシェルを開き、シリアライザークラスをインポートし、インスタンス化して、オブジェクト表現を出力します。

>>> from myapp.serializers import AccountSerializer
>>> serializer = AccountSerializer()
>>> print(repr(serializer))
AccountSerializer():
    id = IntegerField(label='ID', read_only=True)
    name = CharField(allow_blank=True, max_length=100, required=False)
    owner = PrimaryKeyRelatedField(queryset=User.objects.all())

含めるフィールドの指定

モデルシリアライザーで使用するデフォルトフィールドのサブセットのみが必要な場合は、ModelFormの場合と同様に、fieldsまたはexcludeオプションを使用できます。モデルが変更されたときに意図せずにデータを公開する可能性を低くするために、fields属性を使用してシリアライズする必要があるすべてのフィールドを明示的に設定することを強くお勧めします。

たとえば

class AccountSerializer(serializers.ModelSerializer):
    class Meta:
        model = Account
        fields = ['id', 'account_name', 'users', 'created']

fields属性を特別な値'__all__'に設定して、モデルのすべてのフィールドを使用する必要があることを示すこともできます。

たとえば

class AccountSerializer(serializers.ModelSerializer):
    class Meta:
        model = Account
        fields = '__all__'

exclude属性をシリアライザーから除外するフィールドのリストに設定できます。

たとえば

class AccountSerializer(serializers.ModelSerializer):
    class Meta:
        model = Account
        exclude = ['users']

上記の例では、Accountモデルに3つのフィールドaccount_nameusers、およびcreatedがある場合、これによりフィールドaccount_namecreatedがシリアライズされます。

fields属性とexclude属性の名前は通常、モデルクラスのモデルフィールドにマップされます。

または、fieldsオプションの名前は、モデルクラスに存在する引数を取らないプロパティまたはメソッドにマップできます。

バージョン3.3.0以降、fieldsまたはexcludeのいずれかの属性を提供することは**必須**です。

ネストされたシリアライゼーションの指定

デフォルトのModelSerializerは関係にプライマリキーを使用しますが、depthオプションを使用してネストされた表現を簡単に生成することもできます。

class AccountSerializer(serializers.ModelSerializer):
    class Meta:
        model = Account
        fields = ['id', 'account_name', 'users', 'created']
        depth = 1

depthオプションは、フラット表現に戻る前にトラバースする必要がある関係の深さを示す整数値に設定する必要があります。

シリアライズの方法をカスタマイズする場合は、フィールドを自分で定義する必要があります。

フィールドの明示的な指定

ModelSerializerに余分なフィールドを追加したり、クラスでフィールドを宣言することでデフォルトのフィールドをオーバーライドしたりできます。これはSerializerクラスの場合と同じです。

class AccountSerializer(serializers.ModelSerializer):
    url = serializers.CharField(source='get_absolute_url', read_only=True)
    groups = serializers.PrimaryKeyRelatedField(many=True)

    class Meta:
        model = Account
        fields = ['url', 'groups']

余分なフィールドは、モデルの任意のプロパティまたは呼び出し可能に対応できます。

読み取り専用フィールドの指定

複数のフィールドを読み取り専用として指定したい場合があります。read_only=True属性を持つ各フィールドを明示的に追加する代わりに、ショートカットメタオプションread_only_fieldsを使用できます。

このオプションは、フィールド名のリストまたはタプルである必要があり、次のように宣言されます。

class AccountSerializer(serializers.ModelSerializer):
    class Meta:
        model = Account
        fields = ['id', 'account_name', 'users', 'created']
        read_only_fields = ['account_name']

editable=Falseが設定されているモデルフィールドとAutoFieldフィールドは、デフォルトで読み取り専用に設定されるため、read_only_fieldsオプションに追加する必要はありません。


:読み取り専用フィールドがモデルレベルでunique_together制約の一部である特別なケースがあります。この場合、フィールドは制約を検証するためにシリアライザークラスで必要ですが、ユーザーが編集可能であってはなりません。

これに対処する適切な方法は、シリアライザーでフィールドを明示的に指定し、read_only=Truedefault=…キーワード引数の両方を提供することです。

この例の1つは、現在認証されているUserへの読み取り専用の関係であり、これは別の識別子とunique_togetherです。この場合、ユーザーフィールドは次のように宣言します。

user = serializers.PrimaryKeyRelatedField(read_only=True, default=serializers.CurrentUserDefault())

バリデーターのドキュメントで、UniqueTogetherValidatorクラスとCurrentUserDefaultクラスの詳細を確認してください。


追加のキーワード引数

extra_kwargsオプションを使用して、フィールドに任意の追加キーワード引数を指定できるショートカットもあります。read_only_fieldsの場合と同様に、これはシリアライザーでフィールドを明示的に宣言する必要がないことを意味します。

このオプションは、フィールド名をキーワード引数のディクショナリにマッピングするディクショナリです。例:

class CreateUserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ['email', 'username', 'password']
        extra_kwargs = {'password': {'write_only': True}}

    def create(self, validated_data):
        user = User(
            email=validated_data['email'],
            username=validated_data['username']
        )
        user.set_password(validated_data['password'])
        user.save()
        return user

フィールドがシリアライザークラスで明示的に宣言されている場合は、extra_kwargsオプションは無視されることに注意してください。

リレーショナルフィールド

モデルインスタンスをシリアライズする場合、関係を表すためにさまざまな方法を選択できます。ModelSerializerのデフォルトの表現は、関連インスタンスのプライマリキーを使用することです。

代替表現には、ハイパーリンクを使用したシリアライズ、完全にネストされた表現を使用したシリアライズ、またはカスタム表現を使用したシリアライズが含まれます。

詳細については、シリアライザー関係ドキュメントを参照してください。

フィールドマッピングのカスタマイズ

ModelSerializerクラスは、シリアライザーをインスタンス化するときにシリアライザーフィールドが自動的に決定される方法を変更するためにオーバーライドできるAPIも公開しています。

通常、ModelSerializerが必要なフィールドをデフォルトで生成しない場合は、それらをクラスに明示的に追加するか、代わりに通常のSerializerクラスを使用する必要があります。ただし、場合によっては、特定のモデルに対してシリアライザーフィールドがどのように作成されるかを定義する新しい基本クラスを作成する必要がある場合があります。

serializer_field_mapping

DjangoモデルフィールドからRESTフレームワークシリアライザーフィールドへのマッピング。このマッピングをオーバーライドして、各モデルフィールドに使用する必要があるデフォルトのシリアライザーフィールドを変更できます。

このプロパティは、デフォルトでリレーショナルフィールドに使用されるシリアライザーフィールドクラスである必要があります。

ModelSerializerの場合、これはデフォルトでserializers.PrimaryKeyRelatedFieldになります。

HyperlinkedModelSerializerの場合、これはデフォルトでserializers.HyperlinkedRelatedFieldになります。

serializer_url_field

シリアライザーのurlフィールドに使用する必要があるシリアライザーフィールドクラス。

デフォルトはserializers.HyperlinkedIdentityFieldです。

serializer_choice_field

シリアライザーの選択フィールドに使用する必要があるシリアライザーフィールドクラス。

デフォルトはserializers.ChoiceFieldです。

field_classおよびfield_kwargs API

次のメソッドは、シリアライザーに自動的に含める必要がある各フィールドのクラスとキーワード引数を決定するために呼び出されます。これらの各メソッドは、(field_class, field_kwargs)の2つのタプルを返す必要があります。

build_standard_field(self, field_name, model_field)

標準モデルフィールドにマップされるシリアライザーフィールドを生成するために呼び出されます。

デフォルトの実装では、serializer_field_mapping属性に基づいてシリアライザークラスが返されます。

build_relational_field(self, field_name, relation_info)

リレーショナルモデルフィールドにマップされるシリアライザーフィールドを生成するために呼び出されます。

デフォルトの実装では、serializer_related_field属性に基づいてシリアライザークラスが返されます。

relation_info引数は、model_fieldrelated_modelto_many、およびhas_through_modelプロパティを含む名前付きタプルです。

build_nested_field(self, field_name, relation_info, nested_depth)

depthオプションが設定されている場合に、リレーショナルモデルのフィールドにマッピングするシリアライザーフィールドを生成するために呼び出されます。

デフォルトの実装では、ModelSerializerまたはHyperlinkedModelSerializerのいずれかに基づいて、ネストされたシリアライザークラスを動的に作成します。

nested_depthは、depthオプションの値から1を引いた値になります。

relation_info引数は、model_fieldrelated_modelto_many、およびhas_through_modelプロパティを含む名前付きタプルです。

build_property_field(self, field_name, model_class)

モデルクラスのプロパティまたは引数なしのメソッドにマッピングするシリアライザーフィールドを生成するために呼び出されます。

デフォルトの実装では、ReadOnlyFieldクラスを返します。

build_url_field(self, field_name, model_class)

シリアライザー自身のurlフィールドのシリアライザーフィールドを生成するために呼び出されます。デフォルトの実装では、HyperlinkedIdentityFieldクラスを返します。

build_unknown_field(self, field_name, model_class)

フィールド名がモデルフィールドまたはモデルプロパティのいずれにもマッピングされなかった場合に呼び出されます。デフォルトの実装ではエラーが発生しますが、サブクラスはこの動作をカスタマイズできます。


HyperlinkedModelSerializer

HyperlinkedModelSerializerクラスは、プライマリキーではなくハイパーリンクを使用してリレーションシップを表すことを除いて、ModelSerializerクラスに似ています。

デフォルトでは、シリアライザーはプライマリキーフィールドの代わりにurlフィールドを含みます。

urlフィールドはHyperlinkedIdentityFieldシリアライザーフィールドを使用して表され、モデル上のリレーションシップはHyperlinkedRelatedFieldシリアライザーフィールドを使用して表されます。

例えば、fieldsオプションにプライマリキーを追加することで、明示的に含めることができます。

class AccountSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = Account
        fields = ['url', 'id', 'account_name', 'users', 'created']

絶対URLと相対URL

例えば、HyperlinkedModelSerializerをインスタンス化するときは、シリアライザーコンテキストに現在のrequestを含める必要があります。

serializer = AccountSerializer(queryset, context={'request': request})

これにより、ハイパーリンクに適切なホスト名を含めることが保証され、結果として得られる表現は、次のような完全修飾URLを使用します。

http://api.example.com/accounts/1/

次のような相対URLではなく。

/accounts/1/

相対URLを使用する場合は、シリアライザーコンテキストで{'request': None}を明示的に渡す必要があります。

ハイパーリンクビューがどのように決定されるか

モデルインスタンスへのハイパーリンクに使用するビューを決定する方法が必要です。

デフォルトでは、ハイパーリンクは'{model_name}-detail'というスタイルに一致し、pkキーワード引数でインスタンスをルックアップするビュー名に対応することが期待されています。

例えば、extra_kwargs設定でview_nameオプションとlookup_fieldオプションのいずれかまたは両方を使用することで、URLフィールドのビュー名とルックアップフィールドを上書きできます。

class AccountSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = Account
        fields = ['account_url', 'account_name', 'users', 'created']
        extra_kwargs = {
            'url': {'view_name': 'accounts', 'lookup_field': 'account_name'},
            'users': {'lookup_field': 'username'}
        }

または、例えば、シリアライザーのフィールドを明示的に設定することもできます。

class AccountSerializer(serializers.HyperlinkedModelSerializer):
    url = serializers.HyperlinkedIdentityField(
        view_name='accounts',
        lookup_field='slug'
    )
    users = serializers.HyperlinkedRelatedField(
        view_name='user-detail',
        lookup_field='username',
        many=True,
        read_only=True
    )

    class Meta:
        model = Account
        fields = ['url', 'account_name', 'users', 'created']

ヒント: ハイパーリンク表現とURL構成を適切に一致させるのは、やや面倒な場合があります。HyperlinkedModelSerializerインスタンスのreprを印刷することは、リレーションシップがマップされることが期待されるビュー名とルックアップフィールドを正確に検査する上で特に便利な方法です。


URLフィールド名の変更

URLフィールドの名前はデフォルトで'url'です。これは、URL_FIELD_NAME設定を使用することでグローバルに上書きできます。


ListSerializer

ListSerializerクラスは、複数のオブジェクトを一度にシリアライズおよび検証するための動作を提供します。通常、ListSerializerを直接使用する必要はありませんが、シリアライザーをインスタンス化するときにmany=Trueを渡すだけで済みます。

シリアライザーがインスタンス化され、many=Trueが渡されると、ListSerializerインスタンスが作成されます。その後、シリアライザークラスは親のListSerializerの子になります。

次の引数を、ListSerializerフィールドまたはmany=Trueが渡されたシリアライザーに渡すこともできます。

allow_empty

これはデフォルトでTrueですが、空のリストを有効な入力として許可しない場合はFalseに設定できます。

max_length

これはデフォルトでNoneですが、リストにこの数以下の要素しか含まれていないことを検証する場合は、正の整数に設定できます。

min_length

これはデフォルトでNoneですが、リストにこの数以上の要素が含まれていることを検証する場合は、正の整数に設定できます。

ListSerializerの動作のカスタマイズ

ListSerializerの動作をカスタマイズしたい場合がいくつかあります。例えば

  • リストの特定の検証を提供したい場合、たとえば、リスト内の1つの要素が別の要素と競合しないことを確認する場合。
  • 複数のオブジェクトの作成または更新の動作をカスタマイズしたい場合。

これらのケースでは、many=Trueが渡されたときに使用されるクラスを、シリアライザーのMetaクラスのlist_serializer_classオプションを使用して変更できます。

たとえば

class CustomListSerializer(serializers.ListSerializer):
    ...

class CustomSerializer(serializers.Serializer):
    ...
    class Meta:
        list_serializer_class = CustomListSerializer

複数の作成のカスタマイズ

複数のオブジェクト作成のデフォルトの実装は、リスト内の各項目に対して.create()を呼び出すだけです。この動作をカスタマイズしたい場合は、many=Trueが渡されたときに使用されるListSerializerクラスの.create()メソッドをカスタマイズする必要があります。

たとえば

class BookListSerializer(serializers.ListSerializer):
    def create(self, validated_data):
        books = [Book(**item) for item in validated_data]
        return Book.objects.bulk_create(books)

class BookSerializer(serializers.Serializer):
    ...
    class Meta:
        list_serializer_class = BookListSerializer

複数の更新のカスタマイズ

デフォルトでは、ListSerializerクラスは複数の更新をサポートしていません。これは、挿入と削除に期待される動作があいまいであるためです。

複数の更新をサポートするには、明示的に行う必要があります。複数の更新コードを作成するときは、次の点に留意してください。

  • データのリスト内の各項目に対して、どのインスタンスを更新する必要があるかをどのように判断しますか?
  • 挿入はどのように処理する必要がありますか?それらは無効ですか、それとも新しいオブジェクトを作成しますか?
  • 削除はどのように処理する必要がありますか?オブジェクトの削除、またはリレーションシップの削除を意味しますか?それらは黙って無視されるべきですか、それとも無効ですか?
  • 順序はどのように処理する必要がありますか?2つの項目の位置を変更すると、状態が変更されることを意味しますか、それとも無視されますか?

インスタンスシリアライザーに明示的なidフィールドを追加する必要があります。デフォルトの暗黙的に生成されたidフィールドはread_onlyとしてマークされています。これにより、更新時に削除されます。明示的に宣言すると、リストシリアライザーのupdateメソッドで使用できるようになります。

複数の更新を実装する方法の例を次に示します。

class BookListSerializer(serializers.ListSerializer):
    def update(self, instance, validated_data):
        # Maps for id->instance and id->data item.
        book_mapping = {book.id: book for book in instance}
        data_mapping = {item['id']: item for item in validated_data}

        # Perform creations and updates.
        ret = []
        for book_id, data in data_mapping.items():
            book = book_mapping.get(book_id, None)
            if book is None:
                ret.append(self.child.create(data))
            else:
                ret.append(self.child.update(book, data))

        # Perform deletions.
        for book_id, book in book_mapping.items():
            if book_id not in data_mapping:
                book.delete()

        return ret

class BookSerializer(serializers.Serializer):
    # We need to identify elements in the list using their primary key,
    # so use a writable field here, rather than the default which would be read-only.
    id = serializers.IntegerField()
    ...

    class Meta:
        list_serializer_class = BookListSerializer

RESTフレームワーク2に存在していたallow_add_removeの動作と同様に、複数の更新操作の自動サポートを提供するサードパーティパッケージが3.1リリースに同梱される可能性があります。

ListSerializerの初期化のカスタマイズ

many=Trueのシリアライザーがインスタンス化されたとき、子Serializerクラスと親ListSerializerクラスの両方の.__init__()メソッドに渡す必要がある引数とキーワード引数を決定する必要があります。

デフォルトの実装では、validatorsと、子シリアライザーのクラスを対象とすると想定されるカスタムキーワード引数を除く、すべての引数を両方のクラスに渡します。

場合によっては、many=Trueが渡されたときに子クラスと親クラスをどのようにインスタンス化する必要があるかを明示的に指定する必要がある場合があります。これは、many_initクラスメソッドを使用することで実行できます。

    @classmethod
    def many_init(cls, *args, **kwargs):
        # Instantiate the child serializer.
        kwargs['child'] = cls()
        # Instantiate the parent list serializer.
        return CustomListSerializer(*args, **kwargs)

BaseSerializer

代替のシリアル化およびデシリアル化スタイルを簡単にサポートするために使用できるBaseSerializerクラス。

このクラスは、Serializerクラスと同じ基本的なAPIを実装します。

  • .data - 出力されるプリミティブな表現を返します。
  • .is_valid() - 入力データをデシリアライズして検証します。
  • .validated_data - 検証された入力データを返します。
  • .errors - 検証中のエラーを返します。
  • .save() - 検証されたデータをオブジェクトインスタンスに永続化します。

シリアライザークラスがサポートする機能に応じて、オーバーライドできる4つのメソッドがあります。

  • .to_representation() - 読み取り操作のシリアル化をサポートするために、これをオーバーライドします。
  • .to_internal_value() - 書き込み操作のデシリアル化をサポートするために、これをオーバーライドします。
  • .create()および.update() - インスタンスの保存をサポートするために、これらいずれかまたは両方をオーバーライドします。

このクラスはSerializerクラスと同じインターフェイスを提供するため、通常のSerializerまたはModelSerializerの場合とまったく同じように、既存の汎用クラスベースのビューで使用できます。

実行時に気付く唯一の違いは、BaseSerializerクラスがブラウズ可能なAPIでHTMLフォームを生成しないことです。これは、それらが返すデータに、各フィールドを適切なHTML入力にレンダリングできるようにするすべてのフィールド情報が含まれていないためです。

読み取り専用のBaseSerializerクラス

BaseSerializerクラスを使用して読み取り専用のシリアライザーを実装するには、.to_representation()メソッドをオーバーライドするだけです。単純なDjangoモデルを使用した例を見てみましょう。

class HighScore(models.Model):
    created = models.DateTimeField(auto_now_add=True)
    player_name = models.CharField(max_length=10)
    score = models.IntegerField()

HighScoreインスタンスをプリミティブなデータ型に変換するための読み取り専用シリアライザーを作成するのは簡単です。

class HighScoreSerializer(serializers.BaseSerializer):
    def to_representation(self, instance):
        return {
            'score': instance.score,
            'player_name': instance.player_name
        }

このクラスを使用して、単一のHighScoreインスタンスをシリアライズできるようになりました。

@api_view(['GET'])
def high_score(request, pk):
    instance = HighScore.objects.get(pk=pk)
    serializer = HighScoreSerializer(instance)
    return Response(serializer.data)

または、複数のインスタンスをシリアライズするために使用することもできます。

@api_view(['GET'])
def all_high_scores(request):
    queryset = HighScore.objects.order_by('-score')
    serializer = HighScoreSerializer(queryset, many=True)
    return Response(serializer.data)

読み書きのBaseSerializerクラス

読み書きシリアライザーを作成するには、最初に.to_internal_value()メソッドを実装する必要があります。このメソッドは、オブジェクトインスタンスの構築に使用される検証済みの値を返し、提供されたデータの形式が正しくない場合は、serializers.ValidationErrorを発生させる可能性があります。

.to_internal_value()を実装すると、シリアライザーで基本的な検証APIが使用可能になり、.is_valid().validated_data、および.errorsを使用できるようになります。

.save()もサポートする場合は、.create()メソッドと.update()メソッドのいずれかまたは両方も実装する必要があります。

読み取りと書き込みの両方の操作をサポートするように更新された、以前のHighScoreSerializerの完全な例を次に示します。

class HighScoreSerializer(serializers.BaseSerializer):
    def to_internal_value(self, data):
        score = data.get('score')
        player_name = data.get('player_name')

        # Perform the data validation.
        if not score:
            raise serializers.ValidationError({
                'score': 'This field is required.'
            })
        if not player_name:
            raise serializers.ValidationError({
                'player_name': 'This field is required.'
            })
        if len(player_name) > 10:
            raise serializers.ValidationError({
                'player_name': 'May not be more than 10 characters.'
            })

        # Return the validated values. This will be available as
        # the `.validated_data` property.
        return {
            'score': int(score),
            'player_name': player_name
        }

    def to_representation(self, instance):
        return {
            'score': instance.score,
            'player_name': instance.player_name
        }

    def create(self, validated_data):
        return HighScore.objects.create(**validated_data)

新しいベースクラスの作成

BaseSerializerクラスは、特定のシリアル化スタイルを処理したり、代替のストレージバックエンドと統合したりするための新しい汎用シリアライザークラスを実装する場合にも役立ちます。

次のクラスは、任意の複合オブジェクトをプリミティブな表現に変換できる汎用シリアライザーの例です。

class ObjectSerializer(serializers.BaseSerializer):
    """
    A read-only serializer that coerces arbitrary complex objects
    into primitive representations.
    """
    def to_representation(self, instance):
        output = {}
        for attribute_name in dir(instance):
            attribute = getattr(instance, attribute_name)
            if attribute_name.startswith('_'):
                # Ignore private attributes.
                pass
            elif hasattr(attribute, '__call__'):
                # Ignore methods and other callables.
                pass
            elif isinstance(attribute, (str, int, bool, float, type(None))):
                # Primitive types can be passed through unmodified.
                output[attribute_name] = attribute
            elif isinstance(attribute, list):
                # Recursively deal with items in lists.
                output[attribute_name] = [
                    self.to_representation(item) for item in attribute
                ]
            elif isinstance(attribute, dict):
                # Recursively deal with items in dictionaries.
                output[attribute_name] = {
                    str(key): self.to_representation(value)
                    for key, value in attribute.items()
                }
            else:
                # Force anything else to its string representation.
                output[attribute_name] = str(attribute)
        return output

高度なシリアライザーの使用法

シリアライゼーションとデシリアライゼーションの動作のオーバーライド

シリアライザークラスのシリアル化またはデシリアル化の動作を変更する必要がある場合は、.to_representation()または.to_internal_value()メソッドをオーバーライドすることで変更できます。

これが役立つ可能性がある理由を次に示します...

  • 新しいシリアライザーベースクラスの新しい動作の追加。
  • 既存のクラスの動作を少し変更します。
  • 大量のデータを返す頻繁にアクセスされるAPIエンドポイントのシリアル化パフォーマンスの向上。

これらのメソッドのシグネチャは次のとおりです。

to_representation(self, instance)

シリアル化が必要なオブジェクトインスタンスを受け取り、プリミティブな表現を返す必要があります。通常、これは組み込みのPythonデータ型の構造を返すことを意味します。処理できる正確な型は、API用に構成したレンダークラスによって異なります。

表現スタイルを変更するためにオーバーライドできます。例えば

def to_representation(self, instance):
    """Convert `username` to lowercase."""
    ret = super().to_representation(instance)
    ret['username'] = ret['username'].lower()
    return ret

to_internal_value(self, data)

検証されていない受信データを入力として受け取り、serializer.validated_dataとして利用可能になる検証済みのデータを返す必要があります。戻り値は、シリアライザークラスで.save()が呼び出された場合、.create()または.update()メソッドにも渡されます。

検証に失敗した場合、メソッドはserializers.ValidationError(errors)を発生させる必要があります。errors引数は、フィールド名(またはsettings.NON_FIELD_ERRORS_KEY)をエラーメッセージのリストにマッピングする辞書である必要があります。逆シリアル化の動作を変更する必要がなく、オブジェクトレベルの検証を提供したい場合は、代わりに.validate()メソッドをオーバーライドすることをお勧めします。

このメソッドに渡されるdata引数は、通常はrequest.dataの値となるため、提供するデータ型はAPIに構成したパーサークラスに依存します。

シリアライザーの継承

Djangoフォームと同様に、継承を通じてシリアライザーを拡張および再利用できます。これにより、親クラスに共通のフィールドまたはメソッドを宣言し、それを多数のシリアライザーで使用できます。例:

class MyBaseSerializer(Serializer):
    my_field = serializers.CharField()

    def validate_my_field(self, value):
        ...

class MySerializer(MyBaseSerializer):
    ...

DjangoのModelクラスやModelFormクラスと同様に、シリアライザーの内側のMetaクラスは、親の内側のMetaクラスから暗黙的に継承しません。Metaクラスが親クラスから継承するようにする場合は、明示的に行う必要があります。例:

class AccountSerializer(MyBaseSerializer):
    class Meta(MyBaseSerializer.Meta):
        model = Account

通常、内部のMetaクラスで継承を使用するのではなく、すべてのオプションを明示的に宣言することをお勧めします。

さらに、シリアライザーの継承には次の注意点があります。

  • 通常のPythonの名前解決ルールが適用されます。Meta内部クラスを宣言する複数のベースクラスがある場合、最初のもののみが使用されます。これは、子にMetaが存在する場合はそれが使用され、それ以外の場合は最初の親のMetaが使用されるということです。
  • サブクラスで名前をNoneに設定することにより、親クラスから継承されたFieldを宣言的に削除できます。

    class MyBaseSerializer(ModelSerializer):
        my_field = serializers.CharField()
    
    class MySerializer(MyBaseSerializer):
        my_field = None
    

    ただし、このテクニックは、親クラスによって宣言的に定義されたフィールドをオプトアウトする場合にのみ使用できます。ModelSerializerがデフォルトのフィールドを生成するのを防ぐことはできません。デフォルトのフィールドをオプトアウトするには、「含めるフィールドの指定」を参照してください。

フィールドの動的な変更

シリアライザーが初期化されると、シリアライザーに設定されたフィールドの辞書は、.fields属性を使用してアクセスできます。この属性にアクセスして変更することで、シリアライザーを動的に変更できます。

fields引数を直接変更することで、シリアライザーを宣言する時点ではなく、実行時にシリアライザーフィールドの引数を変更するなど、興味深いことができます。

たとえば、シリアライザーを初期化する時点で、シリアライザーで使用するフィールドを設定できるようにする場合は、次のようなシリアライザークラスを作成できます。

class DynamicFieldsModelSerializer(serializers.ModelSerializer):
    """
    A ModelSerializer that takes an additional `fields` argument that
    controls which fields should be displayed.
    """

    def __init__(self, *args, **kwargs):
        # Don't pass the 'fields' arg up to the superclass
        fields = kwargs.pop('fields', None)

        # Instantiate the superclass normally
        super().__init__(*args, **kwargs)

        if fields is not None:
            # Drop any fields that are not specified in the `fields` argument.
            allowed = set(fields)
            existing = set(self.fields)
            for field_name in existing - allowed:
                self.fields.pop(field_name)

これにより、次のことが可能になります。

>>> class UserSerializer(DynamicFieldsModelSerializer):
>>>     class Meta:
>>>         model = User
>>>         fields = ['id', 'username', 'email']
>>>
>>> print(UserSerializer(user))
{'id': 2, 'username': 'jonwatts', 'email': 'jon@example.com'}
>>>
>>> print(UserSerializer(user, fields=('id', 'email')))
{'id': 2, 'email': 'jon@example.com'}

デフォルトフィールドのカスタマイズ

REST framework 2には、ModelSerializerクラスがデフォルトのフィールドセットを自動的に生成する方法を開発者がオーバーライドできるようにするAPIが用意されていました。

このAPIには、.get_field().get_pk_field()、その他のメソッドが含まれていました。

シリアライザーは3.0で根本的に再設計されたため、このAPIは存在しなくなりました。作成されるフィールドを変更することはできますが、ソースコードを参照する必要があり、行った変更がAPIのプライベート部分に対するものである場合は、変更される可能性があることに注意してください。


サードパーティパッケージ

次のサードパーティパッケージも利用可能です。

Django REST marshmallow

django-rest-marshmallowパッケージは、Pythonのmarshmallowライブラリを使用して、シリアライザーの代替実装を提供します。これはREST frameworkシリアライザーと同じAPIを公開し、一部のユースケースではドロップイン代替として使用できます。

Serpy

serpyパッケージは、速度を重視して構築されたシリアライザーの代替実装です。Serpyは、複雑なデータ型を単純なネイティブ型にシリアル化します。ネイティブ型は、JSONまたは必要なその他の形式に簡単に変換できます。

MongoengineModelSerializer

django-rest-framework-mongoengineパッケージは、Django REST frameworkのストレージレイヤーとしてMongoDBを使用することをサポートするMongoEngineModelSerializerシリアライザークラスを提供します。

GeoFeatureModelSerializer

django-rest-framework-gisパッケージは、読み取りおよび書き込み操作の両方でGeoJSONをサポートするGeoFeatureModelSerializerシリアライザークラスを提供します。

HStoreSerializer

django-rest-framework-hstoreパッケージは、django-hstore DictionaryFieldモデルフィールドとそのschema-mode機能をサポートするHStoreSerializerを提供します。

Dynamic REST

dynamic-restパッケージは、ModelSerializerとModelViewSetインターフェースを拡張し、フィルタリング、ソート、およびシリアライザーで定義されたすべてのフィールドと関係を含める/除外するためのAPIクエリパラメーターを追加します。

Dynamic Fields Mixin

drf-dynamic-fieldsパッケージは、URLパラメーターで指定されたサブセットにシリアライザーごとのフィールドを動的に制限するためのミックスインを提供します。

DRF FlexFields

drf-flex-fieldsパッケージは、ModelSerializerとModelViewSetを拡張し、URLパラメーターとシリアライザークラスの定義の両方から、フィールドを動的に設定したり、プリミティブフィールドをネストされたモデルに展開したりするための一般的に使用される機能を提供します。

Serializer Extensions

django-rest-framework-serializer-extensionsパッケージは、ビュー/リクエストごとにフィールドを定義できるようにすることで、シリアライザーをDRY化するためのツールのコレクションを提供します。フィールドをホワイトリスト、ブラックリストに登録したり、子シリアライザーをオプションで展開したりできます。

HTML JSON Forms

html-json-formsパッケージは、(非アクティブな)HTML JSON Form仕様に基づいて、<form>送信を処理するためのアルゴリズムとシリアライザーを提供します。シリアライザーは、HTML内の任意にネストされたJSON構造の処理を容易にします。たとえば、<input name="items[0][id]" value="5">は、{"items": [{"id": "5"}]}と解釈されます。

DRF-Base64

DRF-Base64は、base64エンコードされたファイルのアップロードを処理するフィールドとモデルシリアライザーのセットを提供します。

QueryFields

djangorestframework-queryfieldsを使用すると、APIクライアントは、含める/除外クエリパラメーターを介してレスポンスで送信されるフィールドを指定できます。

DRF Writable Nested

drf-writable-nestedパッケージは、ネストされた関連データを使用してモデルを作成/更新できる書き込み可能なネストされたモデルシリアライザーを提供します。

DRF Encrypt Content

drf-encrypt-contentパッケージは、ModelSerializerを通じてシリアル化されたデータを暗号化するのに役立ちます。また、データ暗号化に役立ついくつかのヘルパー関数も含まれています。