Sometimes it is convenient to import a module when the name is not known until runtime. Python has a handy function called __import__() which handles this and can be wrapped into a handy utility method like this:
def _import(name):
path = name.split('.')
fromlist = path[1:]
mod = __import__(path[0], globals(), locals(), fromlist)
for n in fromlist:
mod = getattr(mod, n)
return mod
When pushing a Django application into production, it can greatly help performance to enabled some form of server-side page caching to avoid costly database calls on high traffic sites. Fortunately, Django comes with a built in caching framework making setting up site-wide caching quick and straightforward.
However, this isn't always desirable. Usually a successful caching strategy needs a little more granularity. For example, on this site I want to cache per view using the cache_page function.
from django.views.decorators.cache import cache_page
However, I would like only to cache if not authenticated to the site. That makes it easy to see any new content on the site right away without waiting for the cache to invalidate.
To solve this I created a wrapper function (inside my urls.py in the main project for convenience). This function takes a view function as an argument. This is the view that I intend to use, but first determine whether or not I should apply cache_page to it. Since I am using this in the context of my urlpatterns, this should return a function that can act as a view, not execute the view itself.
Using Python's *args and **kwargs has it's advantage so I can apply this generically to any view function I have written.
def cache_if_not_auth(view, should_cache=True, cache_interval=30):
"""
Cache a view only if caching is enabled and the current request's user is not authenticated.
"""
def _func(request, *args, **kwargs):
if (should_cache) and not request.user.is_authenticated():
return cache_page(cache_interval)(view)(request, *args, **kwargs)
else:
return view(request, *args, **kwargs)
return _func
I then wrote a wrapper called "cache" simply for shorthand to reuse my criteria for whether or not to cache and how long. Here I am storing those criteria in the settings module.
def cache(view):
"""
Shorthand thats calls cache_if_not_auth specific to where I'm storing my settings.
"""
return cache_if_not_auth(view, should_cache=settings.PROD, cache_interval=settings.CACHE_INTERVAL)
I then use "cache" directly on any view that I need to be cachable in my URL mappings in urls.py:
urlpatterns = patterns('',
url(r'^some_url/$', cache(some_view), name='some_view'),
)
Now the view's output will be cached for non-authenticated users. If a user logs into the site, the views will not be cached.
My new version of the Game of Life is up using the HTML5 canvas. Check it out here.