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.

2 Answers 2

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.

Sign up to request clarification or add additional context in comments.

2 Comments

Sadly not. This complains that super(LoggingMixin).initial(self, request, *args, **kwargs) AttributeError: 'super' object has no attribute 'initial'
Erm... I meant don't pass self to initial. (See the code in answer.)
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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.