2015-10-18 8 views
0

Я хотел бы сохранить список запросов «Последнее посещение» 20 в представлении Django. Также я хочу избежать создания отдельной модели для нее и просто сохранить запрошенные URL-адреса в memcached, нажав каждый новый запрос на очередь фиксированного размера и затем получить очередь в представлениях. Но поскольку кеш - это просто ключ: словарь значений. Мне интересно, как лучше всего это достичь?Как кешировать список запросов в представлениях Django?

+0

Часть проблема в том, что это именно то, что РСУБД был разработан и не в рубке Memcached в. – FlipperPA

+0

@FlipperPA: почему сохранить список в кеше такой плохой идеей, а можно исключить попадание базы данных для каждого запроса? – Jand

+0

это было бы намного проще, если бы вы могли использовать Redis вместо memcached – Anentropic

ответ

1

Одним из способов сделать это с помощью memcache было бы хранить маринованный объект python в виде одного ключа в кеше.

В этом случае мы могли бы использовать Python deque, который имеет точно свойства, которые мы бы хотели получить список 20 самых последних пунктов

Каждый раз, когда мы записываем новый вид страницы нам нужно обновить Deque, который означает получить его, раскрыть, добавить, рассолить и установить новое значение обратно в memcache.

К счастью, кэш-память Django будет обрабатывать травление и раскатывание для нас. Однако мы должны позаботиться о возможности гонки - другими словами, если другой процесс также обновит deque после того, как мы получим нашу копию, и прежде чем у нас появится возможность вернуть ее в кеш.

По этой причине мы должны использовать операцию memcache CAS ('сравнение и набор'). Существует расширенные Джанго бэкэнды что позволяет CAS доступны здесь:
https://github.com/anentropic/django-cas-cache

pip install django-cas-cache

Мы бы некоторый код в пользовательском Django middleware для обновления кэша на каждой страницу, глядя примерно так:

middleware.py

from collections import deque 
from django.core.cache import cache 

class LastSeenMiddleware(object): 
    def process_response(request, response): 
     # you might want some logic like this to only 
     # record successful requests 
     if response.status != 200: 
      return response 

     # in case we don't already have a deque, try to add 
     # (add will not overwrite if key already exists) 
     added = cache.add('last_seen', deque([request.path], maxlen=20)) 

     if not added: 
      def update(val): 
       val.append(request.path) 
       return val 

      cache.cas('last_seen', update) 

     return response 

v iews.py

from django.core.cache import cache 
from django.shortcuts import render_to_response 

def myview(request): 
    last_seen = cache.get('last_seen') 
    # whatever 
    return render_to_response('mytemplate.html', {'last_seen': last_seen}) 

settings.py

CACHES = { 
    'default': { 
     'BACKEND': 'cascache.backends.memcached.MemcachedCASCache', 
     'LOCATION': '127.0.0.1:11211', 
    } 
} 

# as a response processor, our middleware should probably come 
# first in this list, in order to run *last* 
MIDDLEWARE_CLASSES = (
    'myapp.middleware.LastSeenMiddleware', 
    'django.contrib.sessions.middleware.SessionMiddleware', 
    'django.middleware.common.CommonMiddleware', 
    'django.middleware.csrf.CsrfViewMiddleware', 
    'django.contrib.auth.middleware.AuthenticationMiddleware', 
    'django.contrib.auth.middleware.SessionAuthenticationMiddleware', 
    'django.contrib.messages.middleware.MessageMiddleware', 
    'django.middleware.clickjacking.XFrameOptionsMiddleware', 
    'django.middleware.security.SecurityMiddleware', 
) 
+0

Ницца! но нам нужно будет кэшировать как 'request.path', так и' article.title', если мы хотим избежать любых ударов базы данных для рендеринга 'last_seen'. Как с этим справиться? – Jand

+0

хорошо, вам нужно разобраться в деталях промежуточного программного обеспечения, специфичного для вашего случая (например, откуда происходит экземпляр 'article'), но вы можете добавить кортежи' (request.path, article.title) 'в deque, а не просто 'request.path' – Anentropic

 Смежные вопросы

  • Нет связанных вопросов^_^