Skip to content

Commit

Permalink
Split cache_model and cache_relation into separate modules.
Browse files Browse the repository at this point in the history
Signed-off-by: Chris Lamb <chris@playfire.com>
  • Loading branch information
lamby committed Jun 23, 2011
1 parent cfeeb26 commit ad7cbf0
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 78 deletions.
80 changes: 2 additions & 78 deletions cache_relation/__init__.py
@@ -1,78 +1,2 @@
from django.db.models.signals import post_save, post_delete

from .core import get_instance, delete_instance

def cache_relation(descriptor, duration=60 * 60 * 24 * 3):
"""
Usage::
from django.db import models
from django.contrib.auth.models import User
class Foo(models.Model):
user = models.ForeignKey(User)
cache_relation(User.foo)
Then replace ``user_instance.foo`` with ``user_instance.foo_cache``.
"""

rel = descriptor.related
related_name = '%s_cache' % rel.field.related_query_name()

@property
def get(self):
# Always use the cached "real" instance if available
try:
return getattr(self, descriptor.cache_name)
except AttributeError:
pass

# Lookup cached instance
try:
return getattr(self, '_%s_cache' % related_name)
except AttributeError:
pass

instance = get_instance(rel.model, self.pk)

setattr(self, '_%s_cache' % related_name, instance)

return instance
setattr(rel.parent_model, related_name, get)

# Clearing cache

def clear(self):
delete_instance(rel.model, self)

@classmethod
def clear_pk(cls, *instances_or_pk):
delete_instance(rel.model, *instances_or_pk)

def on_post_save(sender, instance, created, *args, **kwargs):
delete_instance(rel.model, instance)

setattr(rel.model, '%s_clear' % related_name, clear)
setattr(rel.parent_model, '%s_clear' % related_name, clear)
setattr(rel.parent_model, '%s_clear_pk' % related_name, clear_pk)
post_save.connect(on_post_save, sender=rel.model, weak=False)

def cache_model(model, duration=60 * 60 * 24 * 3):
if hasattr(model, 'get_cached'):
# Already patched
return

def clear_cache(sender, instance, *args, **kwargs):
delete_instance(sender, instance)

post_save.connect(clear_cache, sender=model, weak=False)
post_delete.connect(clear_cache, sender=model, weak=False)

@classmethod
def get(cls, pk):
if pk is None:
return None
return get_instance(cls, pk, duration)

model.get_cached = get
from .model import cache_model
from .relation import cache_relation
22 changes: 22 additions & 0 deletions cache_relation/model.py
@@ -0,0 +1,22 @@
from django.db.models.signals import post_save, post_delete

from .core import get_instance, delete_instance

def cache_model(model, duration=60 * 60 * 24 * 3):
if hasattr(model, 'get_cached'):
# Already patched
return

def clear_cache(sender, instance, *args, **kwargs):
delete_instance(sender, instance)

post_save.connect(clear_cache, sender=model, weak=False)
post_delete.connect(clear_cache, sender=model, weak=False)

@classmethod
def get(cls, pk):
if pk is None:
return None
return get_instance(cls, pk, duration)

model.get_cached = get
59 changes: 59 additions & 0 deletions cache_relation/relation.py
@@ -0,0 +1,59 @@
from django.db.models.signals import post_save

from .core import get_instance, delete_instance

def cache_relation(descriptor, duration=60 * 60 * 24 * 3):
"""
Usage::
from django.db import models
from django.contrib.auth.models import User
class Foo(models.Model):
user = models.ForeignKey(User)
cache_relation(User.foo)
Then replace ``user_instance.foo`` with ``user_instance.foo_cache``.
"""

rel = descriptor.related
related_name = '%s_cache' % rel.field.related_query_name()

@property
def get(self):
# Always use the cached "real" instance if available
try:
return getattr(self, descriptor.cache_name)
except AttributeError:
pass

# Lookup cached instance
try:
return getattr(self, '_%s_cache' % related_name)
except AttributeError:
pass

instance = get_instance(rel.model, self.pk)

setattr(self, '_%s_cache' % related_name, instance)

return instance
setattr(rel.parent_model, related_name, get)

# Clearing cache

def clear(self):
delete_instance(rel.model, self)

@classmethod
def clear_pk(cls, *instances_or_pk):
delete_instance(rel.model, *instances_or_pk)

def on_post_save(sender, instance, created, *args, **kwargs):
delete_instance(rel.model, instance)

setattr(rel.model, '%s_clear' % related_name, clear)
setattr(rel.parent_model, '%s_clear' % related_name, clear)
setattr(rel.parent_model, '%s_clear_pk' % related_name, clear_pk)
post_save.connect(on_post_save, sender=rel.model, weak=False)

0 comments on commit ad7cbf0

Please sign in to comment.