Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

819
Vistas
How to log requests and responses in Django?

How can I log all my requests and responses (headers and body) in Django using a middleware? I'm using Django 2.2 with Django rest framework, so sometimes the requests and responses are original Django type, sometimes of drf. The app is served behind gunicorn. I've developed middleware but the main problem is I can't read request's body twice as it gives me error.

over 4 years ago · Santiago Trujillo
2 Respuestas
Responde la pregunta

0

Here's an example of logging requests in the database.

Note: This will hit the database once extra with each request. So it will slow down the response time.

models.py

class Request(models.Model):
    endpoint = models.CharField(max_length=100, null=True) # The url the user requested
    user = models.ForeignKey(User, on_delete=models.SET_NULL, null=True) # User that made request, if authenticated
    response_code = models.PositiveSmallIntegerField() # Response status code
    method = models.CharField(max_length=10, null=True)  # Request method
    remote_address = models.CharField(max_length=20, null=True) # IP address of user
    exec_time = models.IntegerField(null=True) # Time taken to create the response
    date = models.DateTimeField(auto_now=True) # Date and time of request
    body_response = models.TextField() # Response data
    body_request = models.TextField() # Request data

middleware.py

class SaveRequest:
    def __init__(self, get_response):
        self.get_response = get_response

        # Filter to log all request to url's that start with any of the strings below.
        # With example below:
        # /example/test/ will be logged.
        # /other/ will not be logged.
        self.prefixs = [
            '/example'
        ]

    def __call__(self, request):
        _t = time.time() # Calculated execution time.
        response = self.get_response(request) # Get response from view function.
        _t = int((time.time() - _t)*1000)    

        # If the url does not start with on of the prefixes above, then return response and dont save log.
        # (Remove these two lines below to log everything)
        if not list(filter(request.get_full_path().startswith, self.prefixs)): 
            return response 

        # Create instance of our model and assign values
        request_log = Request(
            endpoint=request.get_full_path(),
            response_code=response.status_code,
            method=request.method,
            remote_address=self.get_client_ip(request),
            exec_time=_t,
            body_response=str(response.content),
            body_request=str(request.body)
        )

        # Assign user to log if it's not an anonymous user
        if not request.user.is_anonymous:
            request_log.user = request.user

        # Save log in db
        request_log.save() 
        return response

    # get clients ip address
    def get_client_ip(self, request):
        x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
        if x_forwarded_for:
            _ip = x_forwarded_for.split(',')[0]
        else:
            _ip = request.META.get('REMOTE_ADDR')
        return _ip

settings.py

# Activate the middleware in settings.py like this.
MIDDLEWARE = [
    ... # Django default middleware
    '<your_appname>.middleware.SaveRequest'
]
over 4 years ago · Santiago Trujillo Denunciar

0

I originally tried to do something like request = copy.copy(request) but clearly it's a mistake because shallow copying does not copy nested objects. So the correct approach is (__call__ is middleware's class instance method):

def __call__(self, request):
    request_body = copy.copy(request.body)
    # Here goes more code for further processing
    # and now I can safely use request_body before or after
    # the view code runs

Update

As Felix Eklöf suggested, you can also use str(request.body) and python will handle copying the body contents, cause strings are immutable in python. (I guess it has better readability too).

over 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda