It\'s a pretty standard task in Django REST Framework to supply additional args
/kwargs
to a serializer to set values of fields set not via reques
Whenever you use generic views or viewsets, DRF(3.3.2) adds request
object, view
object and format
to the serializer context
. You can use serializer.context
to access, lets say request.user
in the serializer.
This is added when get_serializer_class()
is called. Inside that, it calls get_serializer_context()
method where all these parameters are added to its context.
DRF source code for reference:
class GenericAPIView(views.APIView):
"""
Base class for all other generic views.
"""
def get_serializer(self, *args, **kwargs):
"""
Return the serializer instance that should be used for validating and
deserializing input, and for serializing output.
"""
serializer_class = self.get_serializer_class()
kwargs['context'] = self.get_serializer_context()
return serializer_class(*args, **kwargs)
def get_serializer_context(self):
"""
Extra context provided to the serializer class.
"""
return {
'request': self.request,
'format': self.format_kwarg,
'view': self
}
to set values of fields set not via request.data, but via the value in url parameters or cookies. For instance, I need to set user field of my Comment model equal to request.user upon POST request.
This is how I handle both cases in my ModelViewSet:
def perform_create(self, serializer):
# Get article id from url e.g. http://myhost/article/1/comments/
# obviously assumes urls.py is setup right etc etc
article_pk = self.kwargs['article_pk']
article = get_object_or_404(Article.objects.all(), pk=article_pk)
# Get user from request
serializer.save(author=self.request.user, article=article)
Unfortunately the nested objects is not standard for DRF but that's besides the point. :)