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'このエラー解決はこれが役立ちました!