DRF::ひとつのapi.viewで複数のモデル操作の仕方(特にsave()について)

- アーティスト: O.S.T.
- 出版社/メーカー: Universal
- 発売日: 2017/04/07
- メディア: CD
- この商品を含むブログを見る
メリット
DRFは、Django単体と違って、views.py上にmodelを呼んできて、save()としただけではモデルを引っ張ってきて操作を手軽にできません。(delete()はできます)なので、例えばページビュー数をカウントして、別のモデルに記録させるという場合は、今から各やり方ならできるので便利です。Django単体とDRFの相違点は要するに、serializer でデータを全部やりとりするようにかませるとsave()も含めモデル操作ができるということです。実例を見た方が早いので下記記します
実例1(pkが同じモデルAとBを更新)
#api.views.py
# url: a/detail/1(=pk) を想定ください
class ArticleDetailAPIView(RetrieveAPIView):
permission_classes = [AllowAny]
queryset = A.objects.all()
serializer_class =ADetailSerializer
lookup_field = 'pk'
def get_object(self):
try:
instance = A.objects.get(id=self.kwargs['pk'])
#↑とりあえずget_objectでオーバーライドしたものの、
#返すクエリは同じなので下記のように揃えておく
obj = B.objects.filter(id=self.kwargs['pk']).first()
#↑ここで別のモデルを呼び出す
#ポイントは更新するにはQuerysetだとエラーがでるので
#.first()をつけてBオブジェクト単体にしておくこと
data = {'hoge_field': 'fuga'}
#↑更新したい箇所だけjsonデータを作っておく
update_serializer =BDetailSerializer(obj, data=data)
#↑更新しないデータ=>obj,更新したい箇所のデータ=>dataに格納されている。
#これをセーブしたいモデルに対応したシリアライザーを呼んできてserializedされた(正確な表現しらない・・・)
#データを変数化。
if update_serializer.is_valid(): #serializedされたデータがバリデーションTrueなら、
update_serializer.save() #更新セーブ
except:
raise Http404
return instance
実例2(モデルArticle内のPVフィールドを再帰的に更新)
#api.views.py
# url: article/detail/1(=pk) を想定ください
class ArticleDetailAPIView(RetrieveAPIView):
permission_classes = [AllowAny]
queryset = Article.objects.all()
serializer_class = ArticleDetailSerializer
lookup_field = 'pk'
def get_object(self):
try:
instance = Article.objects.get(id=self.kwargs['pk'])
#↑とりあえずget_objectでオーバーライドしたものの、
#返すクエリは同じなので下記のように揃えておく
obj = Article.objects.filter(id=self.kwargs['pk']).first()
#↑ここでPV数を反映させたいので、Articleのモデルを呼び出す
#ポイントは更新するにはQuerysetだとエラーがでるので
#.first()をつけてBオブジェクト単体にしておくこと
now_pv_num = obj.pv_num + 1 #pv数を+1する
data = {'pv_num': now_pv_num}
#↑更新したい箇所(pv数)だけjsonデータを作っておく
update_serializer = ArticleDetailSerializer(obj, data=data)
#↑更新しないデータ=>obj,更新したい箇所のデータ=>dataに格納されている。
#これをセーブしたいArticleモデルに対応したArticleシリアライザーを呼んできてserializedされた(正確な表現しらない・・・)
#データを変数化。
if update_serializer.is_valid():#serializedされたデータがバリデーションTrueなら、
update_serializer.save()#更新セーブ
except:
raise Http404
return instance
という感じで、DRF独特の書き方に慣れるといいと思われます^^
参考記事
'QuerySet' object has no attribute '_meta'このエラー解決はこれが役立ちました!