現在のリクエストを作成しているユーザ固有の情報を含むシリアライザにフィールドを追加したい(このために別のエンドポイントを作成したくない)。シリアライザDjango REST Frameworkシリアライザにユーザ固有のフィールドを追加する
class ArticleViewSet(viewsets.ModelViewSet):
queryset = Article.objects.all()
serializer_class = ArticleSerializer
filter_class = ArticleFilterSet
def prefetch_likes(self, ids):
self.current_user_likes = dict([(like.article_id, like.pk) for like in Like.objects.filter(user=self.request.user, article_id__in=ids)])
def get_object(self, queryset=None):
article = super(ArticleViewSet, self).get_object(queryset)
self.prefetch_likes([article.pk])
return article
def paginate_queryset(self, queryset, page_size=None):
page = super(ArticleViewSet, self).paginate_queryset(queryset, page_size)
if page is None:
return None
ids = [article.pk for article in page.object_list]
self.prefetch_likes(ids)
return page
:
ビューセット:
class ArticleSerializer(serializers.ModelSerializer):
class Meta:
model = Article
def to_native(self, obj):
ret = super(ArticleSerializer, self).to_native(obj)
if obj:
view = self.context['view']
ret['has_liked'] = False
if hasattr(view, 'current_user_liked'):
ret['has_liked'] = obj.pk in view.current_user_liked
return ret
は言っています記事のプリフェッチを注入するより良い場所があり、あるいはここに私はそれをやった方法ですこれを一般的に行うより良い方法は?
私は、カスタムフィールドを好きですが、あなたがすべてはそれを単一の物品を渡している場合、 'user_likes_article'はキャッシュ/プリフェッチの方法で多くを行うことができないだろう。私が 'get_queryset'の中で先読みをしているのは、リクエストに関連するすべての記事IDがそこにあるからです。シリアライザのフィールドでクエリーセットを使用できますか? –
私はあなたがuser_likesの(キャッシュされた)コレクションからアーティクルを選択するために単一のアーティクルパラメータを使用すると仮定しています(またはそのような)QuerySetは単にArticles.objects.all()ですか?そこには特別なリクエストはありませんが、正確にuser_likes_articleを実装する方法は、あなたがやろうとしていることに正確に依存します。 –
私は元の質問に深刻なバグがあることに気付きました。クエリーセットのフィルタリングやページ区切りではありませんでした。私は今それを修正しました、そして私はそれがもう少し意味をなさないと思います。プリフェッチがリクエスト(フィルタリングとページネーション)と密接に結びついていて、Likeモデルに簡単に移動できないことがわかります。 –