Hello,
I am trying to implement a cache system using the post_save signal.
The problem is the code below, a Thread subclass that ends up calling
run(), the cache database never runs. It's driving me crazy!!! Is
there something going on with the way Django cache's queries which is
what I expect? Can I turn this off? This is the Thread subclass code
is below.
What I am trying to do is implement a staticpages app which is much
like flatpages but it adds a menu foreign key to what is basically a
flatpage. I am trying to make a cache system whereby when a user saves
a link or a menu, the below code rebuilds the XHTML to use in the
staticpage Context.
Here is a sample run:
1) I am in the admin and change a menu to consist of a title called
"Cool Sites 222" and three links
2) post_save runs and here is what is supposed to be saved in the
database (a print is called in my code:
Menu 2
Cool Sites 222
http://www.google.com/";>Google Inc
http://www.microsoft.com";>Microsoft
http://www.ryankaskel.com";>Ryan
Kaskel
http://www.yahoo.com";>Yahoo Homepage
If I don't change anything in the menu, eventually it gets the right
XHTML and prints it
3) The cached XHTML in the database is never changed and still
contains the information from its creation.
I think this is a bug because the following this code:
def _cache_menu(self, menu, xhtml):
"""
Stores xhtml into the CachedMenuXhtml table where the row's
menu matches
the menu_obj.
"""
if menu and xhtml:
cm = self.CachedMenuXhtml.objects.filter(menu__exact=menu)
if cm[0]:
print cm[0].xhtml
cm[0].xhtml = xhtml
cm[0].save()
print cm[0].xhtml
print xhtml
else:
new_cm = self.CachedMenuXhtml(menu=menu,xhtml=xhtml)
new_cm.save()
produces...
Cool Sites
http://www.microsoft.com";>Microsoft
http://www.ryankaskel.com";>Ryan
Kaskel
http://www.yahoo.com";>Yahoo Homepage
[11/Jul/2009 05:03:47] "POST /admin/staticpages/menu/2/ HTTP/1.1" 302
0
Cool Sites
http://www.microsoft.com";>Microsoft
http://www.ryankaskel.com";>Ryan
Kaskel
http://www.yahoo.com";>Yahoo Homepage
Cool Sites 222
http://www.google.com/";>Google Inc
http://www.microsoft.com";>Microsoft
http://www.ryankaskel.com";>Ryan
Kaskel
http://www.yahoo.com";>Yahoo Homepage
CODE for Thread subclass that post_save signal calls
# Signlas for caching of menu XHTML
import threading
from django.template.loader import get_template
from django.template import Context
from django.utils.safestring import mark_safe
from django.core.exceptions import ObjectDoesNotExist
from asqcom.apps.staticpages.settings import STATICPAGE_TEMPLATE,
MENU_TEMPLATE
from asqcom.apps.staticpages.settings import LINK_TEMPLATE,
MENU_CSS_ID
class GenerateMenuXhtml(threading.Thread):
"""
Subclasses a threading.Thread class to generate a menu's XHTML in
a separate
thread. All Link objects that have this menu associated with it
are gathered
and combined in an XHTML unordered list.
If the sender is of type Link, then all menus associated with that
link are
iterated through and rebuilt.
"""
def __init__(self, instance):
from asqcom.apps.staticpages.models import Menu, Link,
CachedMenuXhtml
self.Link = Link
self.Menu = Menu
self.CachedMenuXhtml = CachedMenuXhtml
self.instance = instance
self.menus_to_build = []
self.xhtml_for_menus = []
self.menus_for_cache = []
threading.Thread.__init__(self)
def _cache_menu(self, menu, xhtml):
"""
Stores xhtml into the CachedMenuXhtml table where the row's
menu matches
the menu_obj.
"""
if menu and xhtml:
print menu
print xhtml
cm = self.CachedMenuXhtml.objects.filter(menu__exact=menu)
if cm[0]:
cm[0].xhtml = xhtml
cm[0].save()
else:
new_cm = self.CachedMenuXhtml(menu=menu,xhtml=xhtml)
new_cm.save()
def cache_menus(self):
"""
Unpacks the menu objects and the XHTML for that menu and
iterates
through the list calling _cache_menu which does the real work.
"""
for pair in self.menus_for_cache:
self._cache_menu(pair[0],pair[1])
def _generate_xhtml(self, menu):
link_tmpl = get_template(LINK_TEMPLATE or 'staticpages/
link_default.html')
menu_tmpl = get_template(MENU_TEMPLATE or 'staticpages/
menu_default.html')
# Retrieve all links associated with this menu
links = menu.links.all().order_by('text')
links_strings = []
for link in links:
link_ctx = Context({'title': mark_safe(link.title),
'url': mark_safe(link.url),