Source code for openassembly.oa_cache.models

from django.db import models
from django.contrib.contenttypes.models import ContentType
from django.template.loader import render_to_string
from django.shortcuts import render_to_response
from django.core.cache import cache as memcache
from pirate_ranking.models import get_ranked_list
from pirate_comments.models import get_comments
from pirate_deliberation.models import get_argument_list
from pirate_topics.models import get_topics, get_users
from pirate_forum.models import get_children
from django.contrib import admin
from django.core.context_processors import csrf

from settings import DOMAIN

from pirate_core.middleware import TYPE_KEY, OBJ_KEY, CTYPE_KEY, PHASE_KEY, SEARCH_KEY, S_KEY, STR_KEY
from pirate_core.middleware import START_KEY, END_KEY, DIM_KEY, SCROLL_KEY, RETURN_KEY, SIMPLEBOX_KEY
from pirate_forum.models import get_pretty_url, reverse_pretty_url

from settings import DOMAIN


DIMS = {TYPE_KEY: 'TYPE_KEY', OBJ_KEY: "OBJ_KEY", START_KEY: "START_KEY", STR_KEY: "STR_KEY",
            END_KEY: "END_KEY", DIM_KEY: "DIM_KEY", S_KEY: "S_KEY",
            SCROLL_KEY: "SCROLL_KEY", SEARCH_KEY: "SEARCH_KEY", CTYPE_KEY: "CTYPE_KEY", PHASE_KEY: "PHASE_KEY"}

OPP_DIMS = {'TYPE_KEY': TYPE_KEY, "OBJ_KEY": OBJ_KEY, "START_KEY": START_KEY, "STR_KEY": STR_KEY,
            "END_KEY": END_KEY, "DIM_KEY": DIM_KEY, "S_KEY": S_KEY,
            "SCROLL_KEY": SCROLL_KEY, "SEARCH_KEY": SEARCH_KEY, "CTYPE_KEY": CTYPE_KEY,  "PHASE_KEY": PHASE_KEY}


[docs]def initiate_update(obj_pk, content_pk): """ This method is designed to allow objects to access the oa_cache and update their rendered memcache file. If these objects """ #update the listing.html m = ModelCache.objects.get(html="listing.html") #update the detail_dyn.html m = ModelCache.objects.get(html="detail_dyn.html")
[docs]def interpret_hash(h): h = h.replace(DOMAIN, '')[1:] l = h.split('/') retdict = {} if len(l) >= 2: rendertype = l[1] #rendertype = rendertype[1:] key = str(rendertype) num_fields = len(l[2:]) itr = 1 for dim in l[2:]: #if this is the last field, check for hashes and remove them if itr == num_fields: try: idx = dim.index('#') val = dim[2:idx] except: val = dim[2:] else: val = dim[2:] int_key = key + '/' + dim[0:2] + val int_key = DIMS[dim[0:2]] if int_key == 'STR_KEY': ctype_pk, obj_pk = reverse_pretty_url(val) retdict['OBJ_KEY'] = obj_pk retdict['TYPE_KEY'] = ctype_pk else: retdict[int_key] = val else: rendertype = '' retdict = {} return h, rendertype, retdict
[docs]def build_hash(rendertype, paramdict, add_domain=True): l = '/p/' + rendertype obj_pk = None for k, v in paramdict.items(): if k == 'OBJ_KEY': obj_pk = v elif k == 'TYPE_KEY': ctype_pk = v else: l += '/' + OPP_DIMS[k] + v if obj_pk != None: try: obj_str = get_pretty_url(ctype_pk, obj_pk) l += '/' + OPP_DIMS['STR_KEY'] + obj_str except: l += '/' + OPP_DIMS['OBJ_KEY'] + obj_pk l += '/' + OPP_DIMS['TYPE_KEY'] + ctype_pk if add_domain: l = DOMAIN + l return l
[docs]class ModelCache(models.Model): """Stores references to cached objects with template that will be inserted at div_id. content_type references if this Model is a listing type for lists if it is a ListCache, or a detailed content item/user if otherwise. """ template = models.CharField(max_length=200) div_id = models.CharField(max_length=200) content_type = models.CharField(max_length=200) main = models.BooleanField(default=False) is_recursive = models.BooleanField(default=False) jquery_cmd = models.CharField(max_length=200, blank=True, null=True) object_specific = models.BooleanField(default=False)
[docs] def recursive_render(self, tree, context, forcerender): ret_html = "" for obj in tree: if isinstance(obj, list): context['object'] = obj[0] if context['object'] is not None: #context['count'] = len(tree[1]) key = str(self.template) + '-' + str(context['object'].pk) val = memcache.get(key) if val is None or forcerender == True or forcerender == context['object'].pk: val = render_to_string(self.template, context) ret_html += '<ul id="' + self.template.replace('.html', '') + str(context['object'].pk) + '" class="' + self.template.replace('.html', '') + '">' + val if len(obj) > 1: ret_html += self.recursive_render(obj[1], context, forcerender) + "</ul></ul>" else: ret_html += '</ul>' else: context['object'] = obj context['count'] = 0 if context['object'] is not None: key = str(self.template) + '-' + str(context['object'].pk) val = memcache.get(key) if val is None or forcerender == True or forcerender == context['object'].pk: val = render_to_string(self.template, context) ret_html += '<ul id="' + self.template.replace('.html', '') + str(obj.pk) + '" class="' + self.template.replace('.html', '') + '">' + val + "</ul>" return ret_html
[docs] def render(self, context, forcerender=True): #gets from cache or renders an atomic object given template if self.is_recursive == False: try: key = str(self.template) + '-' + str(context['object'].pk) except: key = str(self.template) + '-anon' obj = memcache.get(key) if obj is None or forcerender: obj = render_to_string(self.template, context) #obj = render_to_string(self.template, context) memcache.set(key, obj) else: obj = self.recursive_render([context['object']], context, forcerender) return obj
def __unicode__(self): return '%s %s %s' % (self.template, self.id, self.content_type)
[docs]class ListCache(models.Model): model_cache = models.CharField(max_length=100, null=True, blank=True) template = models.CharField(max_length=200) div_id = models.CharField(max_length=200) content_type = models.CharField(max_length=200) default = models.BooleanField(default=False)
[docs] def get_or_create_list(self, key, paramdict, forcerender=True): #returns list of rendered objs cache = memcache.get(key) if cache is not None and not forcerender: cached_list = cache[0] tot_items = cache[1] elif cache is None or forcerender: if paramdict == {}: key, rtype, paramdict = interpret_hash(key) ctype_id = paramdict.get('TYPE_KEY', None) obj_id = paramdict.get('OBJ_KEY', None) start = paramdict.get('START_KEY', None) end = paramdict.get('END_KEY', None) dimension = paramdict.get('DIM_KEY', None) ctype_list = paramdict.get('CTYPE_KEY', None) phasekey = paramdict.get('PHASE_KEY', None) if ctype_id is not None and obj_id is not None: content_type = ContentType.objects.get(pk=ctype_id) parent = content_type.get_object_for_this_type(pk=obj_id) else: parent = None if start is None or end is None: paramdict['START_KEY'] = 0 paramdict['END_KEY'] = 10 if dimension is None: dimension = 'h' paramdict['DIM_KEY'] = 'hn' #later these functions can be rendered via some loosely coupled method if self.template == 'issues': func = get_ranked_list update = True elif self.template == 'comments': func = get_comments update = False elif self.template == 'yea': func = get_argument_list dimension = "yea" update = False elif self.template == 'nay': func = get_argument_list dimension = "nay" update = False elif self.template == 'children': func = get_ranked_list update = False elif self.template == 'topics': func = get_topics update = True elif self.template == 'users': func = get_users update = True else: func = get_ranked_list update = False #TODO #elif self.template == 'users': # func = get_topics # update = True kwr = {'parent': parent, 'start': paramdict['START_KEY'], 'end': paramdict['END_KEY'], 'dimension': dimension, 'ctype_list': ctype_list} if phasekey is not None: kwr['phase'] = phasekey cached_list, tot_items = func(**kwr) if update: codes = memcache.get("rank_update_codes") #stores all the encoded pages for tasks/update_ranks newkey, rendertype, paramdict = interpret_hash(key) if codes is not None: codes[key] = paramdict memcache.set("rank_update_codes", codes) else: codes = {} memcache.set("rank_update_codes", codes) #save newly rendered list memcache.set(key, (cached_list, tot_items)) return cached_list, tot_items
def __unicode__(self): return '%s %s %s' % (self.template, self.div_id, self.content_type)
[docs]class UserSaltCache(models.Model): """User salt renders based on object and user, only rendered when the corresponding model_cache is rendered""" model_cache = models.CharField('Object_ID', max_length=100, blank=True, null=True) template = models.CharField(max_length=200) div_id = models.CharField(max_length=200) jquery_cmd = models.CharField(max_length=200) is_recursive = models.BooleanField(default=False) #if this is a toggled DIV, when re-rendered we want to toggle again is_toggle = models.BooleanField(default=False) #is this object DIV specific or required an object pk appended #set to TRUE if you want it OA_CACHE to append an object pk object_specific = models.BooleanField(default=False) #if this usersalt is associated with a different context, we need to redirect to that context redirect = models.BooleanField(default=False) #if this userSalt object is only used in a single page #we want all other views to turn off the user salt, by replacing it with an empty salt #thus if this model_cache is OPPOSITE, the model cache is the only one that doesn't #render an empty in this DIV_ID opposite = models.BooleanField(default=False) #should we cache this non-dynamic html? cache = models.BooleanField(default=False) ###does this object need to be loaded last on the page, for instance if an anchor needs to be placed first load_last = models.BooleanField(default=False) ###if we should only load when the user prompts us to load persistent = models.BooleanField(default=False) ###persistent to a single dashboard
[docs] def recursive_render(self, tree, context): ret_html = [] for obj in tree: if isinstance(obj, list): context['object'] = obj[0] #context['count'] = len(tree[1]) ret_html.append((render_to_string(self.template, context), obj[0].pk)) if len(obj) > 1: ret_html.extend(self.recursive_render(obj[1], context)) else: context['object'] = obj #context['count'] = 0 ret_html.append((render_to_string(self.template, context), obj.pk)) return ret_html
[docs] def render(self, context, forcerender=True): if not self.is_recursive: if self.cache: key = str(context['object'].pk) + ' - ' + self.template.replace('/','-').replace('.', '-').replace('_', '-') cached = memcache.get(key) if cached == None or forcerender: r = render_to_string(self.template, context) memcache.set(key, r) return r else: return cached return render_to_string(self.template, context) else: obj = self.recursive_render([context['object']], context) return obj
def __unicode__(self): return '%s %s %s' % (self.template, self.div_id, str(self.pk))
[docs]class SideEffectCache(models.Model): """User salt renders based on object and user, only rendered when the corresponding model_cache is rendered""" user_salt_cache = models.CharField('Object_ID', max_length=100) template = models.CharField(max_length=200) div_id = models.CharField(max_length=200) jquery_cmd = models.CharField(max_length=200) #is this object DIV specific or required an object pk appended #set to TRUE if you want it OA_CACHE to append an object pk object_specific = models.BooleanField(default=False) key_specific = models.BooleanField(default=False) scroll_to = models.BooleanField(default=True)
[docs] def render(self, context): return render_to_string(self.template, context)
def __unicode__(self): return 'USC : %s -- (%s %s)' % (self.user_salt_cache, self.template, self.div_id)