[解決済み] Django Rest Frameworkの部分更新
質問
私は
partial_update
と
Django Rest フレームワーク
を使用していますが、私は行き詰っているので、いくつかの明確化が必要です。
-
なぜpartial=Trueを指定する必要があるのでしょうか?
私の理解では、Demo オブジェクトの更新はpartial_update
メソッドの中で簡単に更新できます。これの目的は何ですか? -
シリアライズされた変数の中身は何ですか?
の内部には何があるのでしょうか?serialized
の中のpartial_update
メソッドですか?それは Demo オブジェクトですか?裏でどのような関数が呼び出されているのでしょうか? - ここでの実装をどのように終わらせるのでしょうか?
ビューセット
class DemoViewSet(viewsets.ModelViewSet):
serializer_class = DemoSerializer
def partial_update(self, request, pk=None):
serialized = DemoSerializer(request.user, data=request.data, partial=True)
return Response(status=status.HTTP_202_ACCEPTED)
<ブロッククオート
シリアライザ
class DemoSerializer(serializers.ModelSerializer):
class Meta:
model = Demo
fields = '__all__'
def update(self, instance, validated_data):
print 'this - here'
demo = Demo.objects.get(pk=instance.id)
Demo.objects.filter(pk=instance.id)\
.update(**validated_data)
return demo
どのように解決するのですか?
私も以前、あなたと同じ疑問を持っていましたが、rest_frameworkのソースコードを掘り下げたところ、以下のような知見を得ましたので、お役に立てれば幸いです。
質問1について。なぜpartial=Trueを指定する必要があるのでしょうか?
この質問は、関連する HTTP 動詞 .
PUT : PUT メソッドは、対象リソースの現在のすべての表現をリクエストペイロードで置き換えます。
PATCH : PATCHメソッドは、リソースに部分的な変更を加えるために使われます。
一般的に言えば
partial
は、クライアントがビューにデータを送信する際に、モデル内のフィールドがフィールドバリデーションを行うために必要であるかどうかを確認するために使用されます。
例えば、私たちは
Book
というモデルがあったとして、plsは両方の
name
と
author_name
のフィールドは
必須
(not null & not blank)です。
class Book(models.Model):
name = models.CharField('name of the book', max_length=100)
author_name = models.CharField('the name of the author', max_length=50)
# Create a new instance for testing
Book.objects.create(name='Python in a nut shell', author_name='Alex Martelli')
あるシナリオでは、モデルのフィールドの一部だけを更新する必要があるかもしれません。
name
フィールドの
Book
. ですから、この場合、クライアントが送信するのは
name
フィールドをビューに送信します。クライアントからのデータ送信は次のようになります。
{"pk": 1, name: "PYTHON IN A NUT SHELL"}
しかし、このモデル定義では
author_name
を空白にすることはできません。そこで、私たちは
partial_update
の代わりに
update
. そのため、レストフレームワークでは
フィールドのバリデーションチェック
を実行しません。
テスト目的のために、両方のために2つのビューを作成することができます。
update
と
partial_update
というようにすれば、私が言ったことをもっと理解できるようになるでしょう。
例
views.pyfrom rest_framework.generics import GenericAPIView
from rest_framework.mixins import UpdateModelMixin
from rest_framework.viewsets import ModelViewSet
from rest_framework import serializers
class BookSerializer(serializers.ModelSerializer):
class Meta:
model = Book
class BookUpdateView(GenericAPIView, UpdateModelMixin):
'''
Book update API, need to submit both `name` and `author_name` fields
At the same time, or django will prevent to do update for field missing
'''
queryset = Book.objects.all()
serializer_class = BookSerializer
def put(self, request, *args, **kwargs):
return self.update(request, *args, **kwargs)
class BookPartialUpdateView(GenericAPIView, UpdateModelMixin):
'''
You just need to provide the field which is to be modified.
'''
queryset = Book.objects.all()
serializer_class = BookSerializer
def put(self, request, *args, **kwargs):
return self.partial_update(request, *args, **kwargs)
urls.py
urlpatterns = patterns('',
url(r'^book/update/(?P<pk>\d+)/$', BookUpdateView.as_view(), name='book_update'),
url(r'^book/update-partial/(?P<pk>\d+)/$', BookPartialUpdateView.as_view(), name='book_partial_update'),
)
送信するデータ
{"pk": 1, name: "PYTHON IN A NUT SHELL"}
上記のjsonを送信すると
/book/update/1/
に送信すると、HTTP_STATUS_CODE=400で以下のエラーが発生します。
{
"author_name": [
"This field is required."
]
}
しかし、上記のjsonを送信すると
/book/update-partial/1/
に送信すると、HTTP_STATUS_CODE=200となり、以下のようなレスポンスが返ってきます。
{
"id": 1,
"name": "PYTHON IN A NUT SHELL",
"author_name": "Alex Martelli"
}
質問2. シリアライズされた変数の中身は何ですか?
serialized
はモデルインスタンスをシリアライズ可能なオブジェクトとしてラップしたもので、このシリアライズを利用して、プレーンなJSON文字列を
serialized.data
.
質問3について。ここでの実装はどのように仕上げるのでしょうか?
上の回答を読んだ時点で自分で答えられると思うのですが、どのタイミングで
update
を使うべきか、そして
partial_update
.
もし、まだ何か疑問があれば、遠慮なく質問してください。私はrest frameworkのソースコードを一部読んだだけで、あまり深く理解していない用語もあるかもしれませんので、間違っていたらご指摘ください...。
関連
-
[解決済み] Djangoのバージョンを確認する方法
-
[解決済み】Djangoでnull=Trueとblank=Trueの違いは何ですか?
-
[解決済み] Django restフレームワーク、同じModelViewSetで異なるシリアライザーを使用する。
-
[解決済み] Spyderを仮想環境で動作させるには?
-
[解決済み] 小数点以下1桁を取得する[重複]。
-
[解決済み] 文字列のリストを内容に基づいてフィルタリングする
-
[解決済み] Pythonで、ウェブサイトが404か200かを確認するためにurllibをどのように使用しますか?
-
[解決済み] Pythonの文字列の前にあるbという接頭辞は何を意味するのですか?
-
[解決済み] 認証プラグイン 'caching_sha2_password' はサポートされていません。
-
[解決済み] Alembicアップグレードスクリプトでインサートやアップデートを実行するにはどうすればよいですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] Pandasのデータフレームでタプルの列を分割するにはどうしたらいいですか?
-
[解決済み] PythonでファイルのMD5チェックサムを計算するには?重複
-
[解決済み] Djangoで2つの日付の間を選択する
-
[解決済み] Pythonの要素別タプル演算(sumなど
-
[解決済み] Python 3でバイナリデータを標準出力に書き込むには?
-
[解決済み] Pythonのargparseを使った隠し引数の作成
-
[解決済み] Jupyter (IPython)ノートブックのセッションをpickleして保存する方法
-
[解決済み] djangoフレームワークでフォームフィールドから値を取得するには?
-
[解決済み] Pythonによる一対のクロスプロダクト [重複] (英語)
-
[解決済み] Pythonでランダムなファイル名を生成する最良の方法