Desidero aggiungere un campo a un serializzatore che contiene informazioni specifiche dell'utente che effettua la richiesta corrente (non voglio creare un endpoint separato per questo). Ecco il modo in cui l'ho fatto:Aggiungere campi specifici dell'utente al serializzatore Django REST Framework
Il viewset:
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
Il serializzatore:
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
C'è un posto migliore per iniettare il prefetching di articoli voluto, o un modo migliore per farlo in generale?
Mi piace il campo personalizzato, ma 'user_likes_article' non sarebbe in grado di fare molto in termini di caching/prefetching se tutto ciò che fai è passarlo un unico articolo. La ragione per cui ho il prefetching all'interno di 'get_queryset' è che tutti gli id degli articoli rilevanti per la richiesta sono noti lì. Il queryset è in qualche modo disponibile nel campo del serializzatore? –
Suppongo che useresti il parametro articolo singolo per scegliere l'articolo da una raccolta (memorizzata nella cache) di user_likes (o simili). Il tuo QuerySet è solo Articles.objects.all() giusto? Non c'è nulla di specifico, ma esattamente come implementate user_likes_article (ovviamente) dipenderà esattamente da cosa state provando a fare. –
Mi sono reso conto che c'era un bug grave nella mia domanda iniziale; non ha rispettato il filtraggio o l'impaginazione del queryset. L'ho modificato ora, e penso che abbia un po 'più senso. Puoi vedere come il prefetching è strettamente associato alla richiesta (filtraggio e impaginazione) e che non posso spostarlo facilmente nel modello Like. –