1

I want to prepare my Django webservice for distributed requests using cloud computing (stateless!). Therefore I need to make my requests completely modular and take care that no data from a previous request are used. Since I need a lot of data and functions for some requests, it is not reasonable to pass these data to each and every function.

Question: Which possibilities are there to store data "globally" for a single request?

As far as I see there are two possibilities, but both of them do not seem to meet my needs:

1. Django Session

Store data in request.session (using the middleware 'django.contrib.sessions.middleware.SessionMiddleware').

When I understood it properly, the data are still kept after the request for the next requests of the same user until the user logs out.

Is this correct?

In my tests the data are empty for each new request. But I don't understand why. And still I don't have a handle to the request in all of my functions.

For more info about Django sessions see:

2. Python Global Keyword

Store data in python global variables.

These data are stored independently of Django requests and sessions.

For more info about global variables see:

Workaraound

As an ugly workaround for both solutions I can delete the "global" data at the end of each request to keep each request independent from others.

Is there a better way to go?

How is this situation meant in Django?

Thank you in advance for your kind support.

Harald Mandl
  • 91
  • 1
  • 8

1 Answers1

1

This might not be a very efficient solution but you could store it in the thread space.

I used this to add a unique ID - a request_id to every request and add it to the logger format. That way I didn't have to pass the request_id to every function.

init.py for my middleware:

import threading
local = threading.local()

This was my custom middleware:

import json
import uuid
import traceback
from django.utils.deprecation import MiddlewareMixin
class RequestIDMiddleware(MiddlewareMixin):
    def process_request(self, request):
        de_run_id = str(uuid.uuid4())
        local.de_run_id = de_run_id
        request.de_run_id = de_run_id
        if request.body:
            try:
                req = json.loads(request.body)
                if req.get("app_id"):
                    local.app_id = req["app_id"]
                elif req.get("APP_DATA", {}).get("metadata", {}).get("app_id"):
                    local.app_id = req["APP_DATA"]["metadata"]["app_id"]
                else:
                    local.app_id = None
            except Exception, e:
                local.app_id = None
        else:
            local.app_id = None

And this was my custom logging filter:

import logging
from xxxx.middleware import local


class RequestIDFilter(logging.Filter):
    def filter(self, record):
        record.de_run_id = getattr(local, 'de_run_id')
        record.app_id = getattr(local, "app_id")
        return True

you can define local in the init.py of your project. and then overwrite it with a middleware (or whatever feels right to you) and access local throughout the project.

Whether this is the best solution for you depends on a lot factors discussed here

Gaurav Agarwal
  • 611
  • 6
  • 18