==================
Django Redisession
==================
A Redis-based Django session engine for django.contrib.sessions.

This engine supports storing session data as a Redis String, or distributing sessions to Redis hashs for more efficient usage of Redis storage(without much extra CPU cost on Redis server. Refs http://antirez.com/post/redis-weekly-update-7.html and http://redis.io/topics/memory-optimization , you may need to tweak Redis conf for actual usage. The tech is referred as hash mode below).

TODO
====
    - Possible premature optimization: firstly try marshal v2 / yajl.

Installation
============
#. ``pip install django-redisession`` or, in source, ``python setup.py install``.
#. Add `redisession` to INSTALLED_APPS in your current settings file.
#. Set ``SESSION_ENGINE='redisession.backend'`` in the settings file.
    
Configuration
=============
Configuration options to the django-redisession can be placed in dict `REDIS_SESSION_CONFIG`:
    - `SERVER` -- If set to a dict then the value will be used as arguments for redis.Redis() to make a redis connection instance. If set to a string then the django-redisession will get redisession.helper.get_redis to lookup the value in `REDIS_CONFIG` for existing connection instance, see below.
    - `USE_HASH` -- If set to True (hash mode), the django-redisession will store sessions as items of Redis Hashes. `HASH_KEY_GENERATOR` will be used to generate corresponding Redis keys. If set to False, the data of a session will be stored as Redis String value of the Redis key which is generated by `KEY_GENERATOR`. session keys generated by md5 is not as well distribudated as those by sha1, but still acceptable.
    - `KEY_GENERATOR` -- the callable to generate Redis key, or Redis Hash field name when in hash mode, for a session. The callable accept session_key as the only parameter. The default generates the binary string, 16 bytes for md5, from session_key which is normally a hex string.
    - `HASH_KEY_GENERATOR` -- the callable to generate Redis key for Redis Hashes, in hash mode. The default uses the first two bytes of the binary string of a session_key, and thus distributes sessions to 65536 hashes. Other dispatching logics or key prefix could be achieved by customizing this option.
    - `COMPRESS_LIB` -- the module name of the compress library used to compress session data, leave blank to disable compress. Defaults to 'snappy', refs `snappy <http://code.google.com/p/snappy/>`_ and `python-snappy <https://github.com/andrix/python-snappy>`_ . The compress library should support compress and decompress, such as zlib, lzo, etc. A slow library may have higher compression ratio, which implies higher load on web server, but less IO on communicating w/ Redis. So decide it by your tradeoff.
    - `COMPRESS_MIN_LENGTH` -- the minimal length of the session data to try compress. Defaults to 400.

Examples:

::

    # default: distributes sessions to 65536 Redis Hashes,
    #          use binary string form of session_key,
    #          try to compress data (length >= 400) by using snappy. 
    REDIS_SESSION_CONFIG = {
        'SERVER': {},
        'USE_HASH': True,
        'KEY_GENERATOR': lambda x: x.decode('hex'),
        'HASH_KEY_GENERATOR': lambda x: x[:4].decode('hex'),
        'COMPRESS_LIB': 'snappy',
        'COMPRESS_MIN_LENGTH': 400,
    }
    
::

    # use session thru Redis get/set. store session key just as it is, hex string.
    REDIS_SESSION_CONFIG = {
        'USE_HASH': False,
        'KEY_GENERATOR': lambda x: x
    }

::

    # almost as above, but add key prefix 's:' for Redis keys
    REDIS_SESSION_CONFIG = {
        'USE_HASH': False,
        'KEY_GENERATOR': lambda x: 's:'+x
    }

::

    # use Redis connection instance through redisession.helper.get_redis
    # here django-redisession will try to use Redis connection instance 'foo'
    REDIS_SESSION_CONFIG = {
        'SERVER': 'foo'
    }

    # see following
    REDIS_CONFIG = {
        'default': {'db':1},
        'foo': {'db':2, unix_socket_path='/tmp/bar'}
    }


You could use ``redisession.helper.get_redis`` to create and get global Redis connection instance by name. First, setting `REDIS_CONFIG` in the settings file, which is similar to DBs settings in django. For example:

::

    REDIS_CONFIG = {
        # 'name': arguments passed to redis.Redis to build a connection instance, as dict items
        'default': {'port':63790, 'db':1},
        'foo': {'db':2, unix_socket_path='/tmp/bar'}
    }

then

::

    >>> from redisession.helper import get_redis
    >>> r = get_redis() # get Redis connection instance of name 'default'
    >>> r = get_redis('foo') # or of name 'foo'
    >>> r.info()

Test
====
    ``python manager.py test redisession``. It uses your REDIS_SESSION_CONFIG settings for tests, so corresponding Redis server should be available.
