2

I'm sure there must be something I don't understand about type hierarchies and initialisation in python... I wanted to log post bodies with django rest framework like suggested here on stackoverflow: by overriding initial and finalize_response.

This is how my mixin looks like:

class LoggingMixin(object):
"""
Provides full logging of requests and responses
"""

def finalize_response(self, request, response, *args, **kwargs):
    # do the logging
    if settings.DEBUG:
        logger.debug("[{0}] {1}".format(self.__class__.__name__, response.data))
    return super(LoggingMixin, self).finalize_response(request, response, *args, **kwargs)

def initial(self, request, *args, **kwargs):
    # do the logging
    if settings.DEBUG:
        try:
            data = request._data
            logger.debug("[{0}] {1}".format(self.__class__.__name__, data))
        except exceptions.ParseError:
            data = '[Invalid data in request]'

    super(LoggingMixin, self).initial(self, request, *args, **kwargs)

And my view:

class BulkScan(LoggingMixin, generics.ListCreateAPIView):
"""
Provides get (list all) and post (single) for scans.
"""
queryset = Scan.objects.all()
serializer_class = ScanSerializer
authentication_classes = (OAuth2Authentication,)
permission_classes = (IsAuthenticated,)

# insert the user on save
def pre_save(self, obj):
    for scan in obj:
        scan.user = self.request.user

def post(self, request, *args, **kwargs):
    serializer = ScanSerializer(data=request.DATA, many=True)
    if serializer.is_valid():
        self.pre_save(serializer.object)
        self.object = serializer.save(force_insert=True)
        self.post_save(self.object, created=True)
        headers = self.get_success_headers(serializer.data)
        return Response(serializer.data, status=status.HTTP_201_CREATED,
                        headers=headers)

    return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

Yet, a post or get request fails, complaining that the request.user property is not present. This must automagically be injected there. If I don't overwrite initial then everything is fine and the user is set when APIView.initial is called.

For now, I resorted to overriding get and post and then logging the content of the post body but I don't get why the user property is not set when I override the method.

Many thanks for any clarification on this matter.

Community
  • 1
  • 1
Dan Schien
  • 1,392
  • 1
  • 17
  • 29

2 Answers2

1

You're calling the super implementation of initial wrong. Don't pass self:

super(LoggingMixin, self).initial(request, *args, **kwargs)

Hopefully that fixes it — there doesn't seem to be anything else wrong.

Carlton Gibson
  • 7,278
  • 2
  • 36
  • 46
0

@carlton-gibson is correct, but there's one other thing. I had this same issue. Fixed it by calling the super()'s initial() before doing the logging.

def initial(self, request, *args, **kwargs):
    # do the logging
    result = super(LoggingMixin, self).initial(request, *args, **kwargs)
    if settings.DEBUG:
        try:
            data = request._data
            logger.debug("[{0}] {1}".format(self.__class__.__name__, data))
        except exceptions.ParseError:
            data = '[Invalid data in request]'
    return result
Dougyfresh
  • 586
  • 3
  • 15