четверг, 8 декабря 2011 г.

Кеширование отдельных запросов

На днях возникла необходимость сделать кеширование некоторых сложных запросов. Просто по таймауту, без инвалидации. Делать общее кеширование на сайте нельзя, потому что шаблоны генерируются сложно, в зависимости от многих данных.



По-быстрому был настрочен небольшой класс-хелпер:


from django.core.cache import cache

class Cacher():

    obj=None
    name=''
    timeout=30

    def __init__(self, request=None, obj=None, name='', key='', timeout=30):
        if request:
            name += ('_'+request.user.username)
        if key:
            name += ('_'+key)
        self.name = name
        self.obj = obj
        self.timeout = timeout

    def cache_proc(self, title='', **kwargs):
        local_name = self.name + '_' + title
        retval = cache.get(local_name, None)
        if not retval:
            exec "retval = self.obj.%s(**kwargs)" % title
            cache.set(local_name, retval, self.timeout)
        return retval


    def filter(self, *args, **kwargs):
        return self.cache_proc(title='filter', **kwargs)

    def get(self, *args, **kwargs):
        return self.cache_proc(title='get', **kwargs)

    def all(self, *args, **kwargs):
        return self.cache_proc(title='all', **kwargs)

    def aggregate(self, *args, **kwargs):
        return self.cache_proc(title='aggregate', **kwargs)

    def annotate(self, *args, **kwargs):
        return self.cache_proc(title='annotate', **kwargs)

Юзать так:

Cacher(obj=UserProfile.objects, name='up_p1', request=request).filter(partner=partner) 

Или так: 

Cacher(obj=UserProfile.objects, name='up_p1', key=self.username).filter(partner=partner) 

Если есть request, код привязывает имя ключа к имени юзера. Если нет, к переменной key. Это как бы суффикс. Ну и можно задать время хранения кеша в timeout.

Ничего военного, но возможно кому-то будет полезно.

Комментариев нет:

Отправить комментарий