David Lam
David Lam

Reputation: 4948

what's a good/structured way to prevent memcached CacheKeyWarning's?

I was wondering if anyone knew of a handy way or method to make sure the keys you pass to django.core.cache.set() or cache.get() are ok.

From https://docs.djangoproject.com/en/1.3/topics/cache/#cache-key-warnings:

Memcached, the most commonly-used production cache backend, does not allow cache keys longer than 250 characters or containing whitespace or control characters, and using such keys will cause an exception.

I found this md5_constructor() function here: https://github.com/django/django/blob/master/django/utils/hashcompat.py,

maybe one way is to md5-ifiy the key you use always? Not 100% sure if that's safe or not.

Upvotes: 5

Views: 3841

Answers (2)

iMom0
iMom0

Reputation: 12931

  1. md5_constructor is hashlib.md5 in standard library, its digest method can return safe key fit the length limit. If the length of your original key is bigger than 250, you should use it or others to make key safe.
  2. for every character in origin key, make sure ord(character) >= 33, if not, replace unsafe character with underscore or other safe character you like.

Upvotes: 8

Germano
Germano

Reputation: 2482

You might want to use a custom key function https://docs.djangoproject.com/en/dev/ref/settings/#std:setting-CACHES-KEY_FUNCTION

Set it in your settings:

CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
        'KEY_FUNCTION': 'path.to.my.make_key',
        'LOCATION': [
            '127.0.0.1:11211',
        ]
    }
}

I would use something like:

from django.utils.encoding import smart_str

def _smart_key(key):
    return smart_str(''.join([c for c in key if ord(c) > 32 and ord(c) != 127]))

def make_key(key, key_prefix, version):
    "Truncate all keys to 250 or less and remove control characters"
    return ':'.join([key_prefix, str(version), _smart_key(key)])[:250]

Upvotes: 10

Related Questions