如何在Google云AppEngine上为Django配置Memcache?

4
在我的设置中,我有以下内容:
CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
        'LOCATION': '127.0.0.1:11211',
    }
}

我已经安装了https://pypi.org/project/python-memcached/

还需要做其他的事情吗?

2个回答

2

0
对于在2023年尝试此操作的任何人的更新:接受的答案是一个很好的起点,但是不完整。google.appengine.api.memcache接口和django.core.cache.backends.memcached.BaseMemcachedCache接口之间存在一些不一致之处,需要解决。
我正在使用Django 3.2在Google App Engine Python 3.10运行时。
对于我的使用情况,最重要的不一致之处是:
GAE的`memcache.get`不支持`BaseMemcachedCache.get`的`default`参数。这会导致一个令人困惑的`TypeError: Cannot set google.appengine.MemcacheGetRequest.name_space`错误。
Google的`memcache.incr`和`memcache.decr`支持一个`initial_value`参数,而`BaseMemcachedCache.incr/decr`不支持。
与(1)相关的一个重要推论是,GAE的`memcache`不支持默认对象模式,用于区分缓存未命中和合法缓存的`None`值。
下面的实现解决了我的使用情况中的这些不一致性。我相信GAE的`memcache` API和`BaseMemcachedCache`之间还存在其他不一致性,但它们目前与我的使用情况无关。请随意将此作为您自己实现的起点。
from google.appengine.api import memcache

from django.utils.functional import cached_property
from django.core.cache.backends.base import DEFAULT_TIMEOUT
from django.core.cache.backends.memcached import BaseMemcachedCache


class GaeMemcachedCache(BaseMemcachedCache):
    def __init__(self, server, params):
        super().__init__(server, params, library=memcache, value_not_found_exception=ValueError)

    def decr(self, key, delta=1, version=None, initial_value=None):
        if delta < 0:
            return self.incr(key, delta=-delta, version=version, initial_value=initial_value)

        key = self.make_key(key, version=version)
        self.validate_key(key)

        value = self._cache.decr(key, delta=delta, initial_value=initial_value)

        if value is None:
            raise ValueError(f"Key '{key}' not found")

        return value

    def get(self, key, default=None, version=None):
        if not self.has_key(key, version=version):
            return default

        key = self.make_key(key, version=version)
        self.validate_key(key)

        return self._cache.get(key)

    def has_key(self, key, version=None):
        """
        Returns `True` if a key is present in the cache, otherwise `False`.

        `google.appengine.api.memcache.get` doesn't support a `default` argument. Instead, it
        returns `None` for a cache miss. `replace()`, however, returns False if the intended
        key isn't present in the cache. We can therefore check to see if key is present by
        `get`ing it and then replacing it with itself.

        `google.appengine.api.memcache` also doesn't support a way to determine a key's
        expiration time, so this approach results in the loss of that information, but
        only for keys whose value was positively set to `None`.
        """
        key = self.make_key(key, version=version)
        self.validate_key(key)

        value = self._cache.get(key)

        if value is None:
            return self._cache.replace(key, value)

        return True

    def incr(self, key, delta=1, version=None, initial_value=None):
        if delta < 0:
            return self.decr(key, delta=-delta, version=version, initial_value=initial_value)

        key = self.make_key(key, version=version)
        self.validate_key(key)

        value = self._cache.incr(key, delta=delta, initial_value=initial_value)

        if value is None:
            raise ValueError(f"Key '{key}' not found")

        return value

    @cached_property
    def _cache(self):
        if getattr(self, '_client', None) is None:
            self._client = self._lib._CLIENT
        return self._client


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接