0

I am making a Django Web app which initalizes two large dictionaries when I load the home page. I would like this dictionary to be available to all views after being initialized first. I understand this could be done with Global variables. But how do this in Django without using Global Variable?

def startLoading():
      p, songs = loadSongs()

I would like p and songs to be accessible and mutable from every view.

user3766332
  • 319
  • 1
  • 5
  • 17

2 Answers2

1

Django does not provide any way, per se, of doing that. Using global variables is, most of the times, a bad idea. My suggestion comes in the following steps:

  1. If you are forced to store such values in memory, use a Singleton object instead of a plain global variable (on the end, you are assuming the same risks, or similar, so be wary).
  2. Declare methods to access the object and make the data available or store new values.
  3. Remember this approach may fail (actually not fail but become less efficient) in development since stuff can be reloaded.
  4. Remember to make those methods thread safe: my suggestion is you use a mutex.

Remember that, in Python, either you store something in a member of a global reference, or declare a global variable. This is a minor adjustment of what you did:

def startLoading():
    global p, songs
    # If you don't acquire a mutex here, God will flood earth again
    if not (p or songs):
        p, songs = loadSongs()
    # release the mutex
    return p, songs

I always suggest having another reference to store everything (the singleton I told you later):

from a.certain.module import my_store

def startLoading():
    # ACQUIRE MUTEX here
    if not myStore.has_data():
        my_store.set_data(loadSongs())
    # RELEASE MUTEX here
    return my_store.get_data()

What get_data, set_data, and has_data do is up to you. I still think storing global values is a terrible idea in particular if you use something like gunicorn and have several (2n+1) django processes attending clients. It is always preferrable an external process like memcache to achieve that. But if you insist, you have these guidelines.

Luis Masuelli
  • 12,079
  • 10
  • 49
  • 87
-1

The most obvious way of doing this is to use Django Cache framework. You will need to add CACHES variable to your settings.py and then you can do something like this on project load

from django.conf import settings
from django.core.cache import caches

cache = caches['default']
key=settings.THEKEY # the cache key to access your dictionary

the_dict = generate_the_big_dict()
cache.set(key, the_dict)

and in your views that need to access the dictionary you would do something like

from django.conf import settings
from django.core.cache import caches

cache = caches['default']
key=settings.THEKEY

the_dict = cache.get(key)

If you really only want to generate the key once, you can put the generation of it into the django app ready() method (relevant docs link https://docs.djangoproject.com/en/1.9/ref/applications/#django.apps.AppConfig.ready) and set some very large timeout value on it. Otherwise you might want to make sure somehow that you keep updating it before it expires.

https://docs.djangoproject.com/en/1.9/topics/cache/

Mad Wombat
  • 14,490
  • 14
  • 73
  • 109
  • Performance of serialization and sending huge dict will be terribly slow – thedk May 24 '19 at 10:12
  • I think there are issues with choosing cache 1. Memcache : cannot run it within same docker container where my app is running, and don't want another container as it is small data 2. Locmemcache : as mentioned in documentation it is per process. so not shared between process. let me know if you have any cache which is truely global and can run within django – archit Apr 17 '22 at 18:17
  • On any production setup a Django app runs on a WSGI server like uWSGI or gunicorn. These servers usually run multiple worker processes with separate copies of the app loaded into each worker. So in order to have a "global" variable you would need some sort of external storage. Whether you use cache, database or something else. – Mad Wombat Apr 18 '22 at 20:35