Django-rest-framework 3.で、これらの単純なモデルを使用する場合:
class Book(models.Model):
title = models.CharField(max_length=50)
class Page(models.Model):
book = models.ForeignKey(Books, related_name='related_book')
text = models.CharField(max_length=500)
そして、このJSONリクエストが与えられた場合:
{
"book_id":1,
"pages":[
{
"page_id":2,
"text":"loremipsum"
},
{
"page_id":4,
"text":"loremipsum"
}
]
}
このJSONを処理し、特定のpage
のbook
ごとにネストされたシリアライザーを作成して、新しいページを作成するか、存在する場合は更新する方法はありますか。
class RequestSerializer(serializers.Serializer):
book_id = serializers.IntegerField()
page = PageSerializer(many=True)
class PageSerializer(serializers.ModelSerializer):
class Meta:
model = Page
instance
でシリアライザーをインスタンス化すると現在のものが更新されることを知っていますが、ネストされたシリアライザーのcreate
メソッド内でどのように使用する必要がありますか?
まず、新しいブックインスタンスの作成をサポートしますか、それとも既存のインスタンスの更新のみをサポートしますか?
新しい本のインスタンスを作成したいだけなら、次のようなことができます...
_class PageSerializer(serializers.Serializer):
text = serializers.CharField(max_length=500)
class BookSerializer(serializers.Serializer):
page = PageSerializer(many=True)
title = serializers.CharField(max_length=50)
def create(self, validated_data):
# Create the book instance
book = Book.objects.create(title=validated_data['title'])
# Create or update each page instance
for item in validated_data['pages']:
page = Page(id=item['page_id'], text=item['text'], book=book)
page.save()
return book
_
Iはここに_book_id
_を含めていないことに注意してください。本のインスタンスを作成するとき、本のIDは含めません。書籍のインスタンスを更新する場合、通常、リクエストデータではなく、URLの一部として書籍IDを含めます。
ブックインスタンスの作成と更新の両方をサポートする場合は、リクエストに含まれていないがare現在関連付けられているページをどのように処理するかを考える必要があります本のインスタンス。
これらのページを静かに無視してそのままにしておくか、検証エラーを発生させるか、削除することができます。
リクエストに含まれていないページを削除したいとします。
_def create(self, validated_data):
# As before.
...
def update(self, instance, validated_data):
# Update the book instance
instance.title = validated_data['title']
instance.save()
# Delete any pages not included in the request
page_ids = [item['page_id'] for item in validated_data['pages']]
for page in instance.books:
if page.id not in page_ids:
page.delete()
# Create or update page instances that are in the request
for item in validated_data['pages']:
page = Page(id=item['page_id'], text=item['text'], book=instance)
page.save()
return instance
_
また、onlyブックの更新をサポートし、作成をサポートしない場合もあります。その場合、onlyはupdate()
メソッド。
また、クエリの数を減らすことができるさまざまな方法があります。一括作成/削除を使用しますが、上記はかなり簡単な方法でジョブを実行します。
ご覧のとおり、ネストされたデータを処理する際に必要な動作の種類には微妙な点があるため、さまざまな場合に期待される動作を正確に検討してください。
また、上記の例ではSerializer
ではなくModelSerializer
を使用していることに注意してください。この場合、デフォルトでModelSerializer
が生成するフィールドの自動セットに依存するのではなく、シリアライザークラスのすべてのフィールドを明示的に含める方が簡単です。
drf-writable-nested を使用するだけです。ネストされたシリアライザーを自動的に書き込み可能および更新可能にします。
あなたに serializers.py
:
from drf_writable_nested import WritableNestedModelSerializer
class RequestSerializer(WritableNestedModelSerializer):
book_id = serializers.IntegerField()
page = PageSerializer(many=True)
class PageSerializer(serializers.ModelSerializer):
class Meta:
model = Page
以上です!
また、ライブラリは、create
ロジックとupdate
ロジックの両方を必要としない場合に、どちらか一方のみの使用をサポートします。