modelserializer framework example create python django django-rest-framework

python - example - modelserializer django rest framework



Registro de solicitudes a django-rest-framework (5)

Para propósitos de depuración, me gustaría usar el mecanismo de registro de Django para registrar cada solicitud entrante cuando "llegue" a la puerta de django-rest-framework.

Djagno ofrece el registro de sus solicitudes (solo nivel de registro de "advertencia" y superior) de la siguiente manera (en la sección de REGISTRO en settings.py):

''django.request'': { ''handlers'': [''mail_admins''], ''level'': ''ERROR'', ''propagate'': False, },

Estoy buscando lograr algo como esto (aviso: el nivel de registro es DEBUG):

''rest_framework.request'': { ''handlers'': [''logfile''], ''level'': ''DEBUG'', ''propagate'': False, },

¿Hay alguna manera de hacerlo sin incrustar un registrador en el código fuente de DRF?
¿Hay algún tipo de opción de "Logging Backend" en DRF que no conozco?


Aquí está el código de @Glyn Jackson''s Answer:

en middleware / mixin.py

class RequestLogMiddleware(object): def initial(self, request, *args, **kwargs): super(RequestLogMiddleware, self).initial(request, *args, **kwargs) # store/log the request

en la vista:

class ViewClass(RequestLogMiddleware, generics.RetrieveAPIView): ...


Aquí mi solución actual para obtener cada SOLICITUD / RESPUESTA en el registro. Creé un middleware compatible con el middleware antiguo (Django <1.10) y el nuevo middleware que registra cada solicitud / respuesta. Esta solución es la mejor que he encontrado hasta ahora.

import logging from django.utils.deprecation import MiddlewareMixin _logger = logging.getLogger(__name__) class LogRestMiddleware(MiddlewareMixin): """Middleware to log every request/response. Is not triggered when the request/response is managed using the cache """ def _log_request(self, request): """Log the request""" user = str(getattr(request, ''user'', '''')) method = str(getattr(request, ''method'', '''')).upper() request_path = str(getattr(request, ''path'', '''')) query_params = str(["%s: %s" %(k,v) for k, v in request.GET.items()]) query_params = query_params if query_params else '''' _logger.debug("req: (%s) [%s] %s %s", user, method, request_path, query_params) def _log_response(self, request, response): """Log the response using values from the request""" user = str(getattr(request, ''user'', '''')) method = str(getattr(request, ''method'', '''')).upper() status_code = str(getattr(response, ''status_code'', '''')) status_text = str(getattr(response, ''status_text'', '''')) request_path = str(getattr(request, ''path'', '''')) size = str(len(response.content)) _logger.debug("res: (%s) [%s] %s - %s (%s / %s)", user, method, request_path, status_code, status_text, size) def process_response(self, request, response): """Method call when the middleware is used in the `MIDDLEWARE_CLASSES` option in the settings. Django < 1.10""" self._log_request(request) self._log_response(request, response) return response def __call__(self, request): """Method call when the middleware is used in the `MIDDLEWARE` option in the settings (Django >= 1.10)""" self._log_request(request) response = self.get_response(request) self._log_response(request, response) return response


Descubrí que la mejor y más flexible manera era agregar el registro a través de un decorador. Simplemente agrego el decorador a cada una de las funciones (publicación, obtención) desde las que deseo registrar la solicitud, en lugar de que sea parte de la clase de vista general. Más control sobre lo que se registra. Este decorador toma el objeto de solicitud pasado en (arg [1]) y luego registra partes del objeto de solicitud en un archivo.

Consulte https://github.com/slogan621/tscharts/commit/39ed479b04b7077f128774d3a203a86d6f68f03e para obtener información sobre lo que equivale a una plantilla para hacerlo (commit muestra los cambios en settings.py necesarios para insertar el registro en el esquema de registro de archivos que tengo en su lugar, así como como el uso del decorador y el ejemplo).


Hice un RequestLogMiddleware genérico que se puede conectar a cualquier Django View usando decorator_from_middleware .

request_log / middleware.py

import socket import time class RequestLogMiddleware(object): def process_request(self, request): request.start_time = time.time() def process_response(self, request, response): if response[''content-type''] == ''application/json'': if getattr(response, ''streaming'', False): response_body = ''<<<Streaming>>>'' else: response_body = response.content else: response_body = ''<<<Not JSON>>>'' log_data = { ''user'': request.user.pk, ''remote_address'': request.META[''REMOTE_ADDR''], ''server_hostname'': socket.gethostname(), ''request_method'': request.method, ''request_path'': request.get_full_path(), ''request_body'': request.body, ''response_status'': response.status_code, ''response_body'': response_body, ''run_time'': time.time() - request.start_time, } # save log_data in some way return response

request_log / mixins.py

from django.utils.decorators import decorator_from_middleware from .middleware import RequestLogMiddleware class RequestLogViewMixin(object): """ Adds RequestLogMiddleware to any Django View by overriding as_view. """ @classmethod def as_view(cls, *args, **kwargs): view = super(RequestLogViewMixin, cls).as_view(*args, **kwargs) view = decorator_from_middleware(RequestLogMiddleware)(view) return view

my_django_rest_api / views.py

from rest_framework import generics from ...request_log.mixins import RequestLogViewMixin class SomeListView( RequestLogViewMixin, generics.ListAPIView ): ...


Reemplace el método APIView.initial() para agregar el registro usted mismo.

Métodos de envío

Los siguientes métodos son llamados directamente por el método .dispatch () de la vista. Estos realizan cualquier acción que deba ocurrir antes o después de llamar a los métodos del controlador como .get (), .post (), put (), patch () y .delete ().

.initial(self, request, *args, **kwargs)
Realiza las acciones que deben ocurrir antes de que se llame al método del controlador. Este método se utiliza para imponer permisos y limitaciones, y para realizar la negociación de contenido.