Package: redisco
Python Containers and Simple Models for RedisDescriptionRedisco allows you to store objects inRedis. It is inspired by the Ruby libraryOhmand its design and code are loosely based on Ohm and the Django ORM.
It is built on top ofredis-py. It includes container classes that allow
easier access to Redis sets, lists, and sorted sets.InstallationRedisco requires redis-py 2.0.0 so get it first.pip install redisThen install redisco.pip install rediscoModelsfrom redisco import models
class Person(models.Model):
    name = models.Attribute(required=True)
    created_at = models.DateTimeField(auto_now_add=True)
    fave_colors = models.ListField(str)

>>> person = Person(name="Conchita")
>>> person.is_valid()
True
>>> person.save()
True
>>> conchita = Person.objects.filter(name='Conchita')[0]
>>> conchita.name
'Conchita'
>>> conchita.created_at
datetime.datetime(2010, 5, 24, 16, 0, 31, 954704)Model AttributesAttributeStores unicode strings. If used for large bodies of text,
turn indexing of this field off by setting indexed=True.IntegerFieldStores an int. Ints are stringified using unicode() before saving to
Redis.CounterAn IntegerField that can only be accessed via Model.incr and Model.decr.DateTimeFieldCan store a DateTime object. Saved in the Redis store as a float.DateFieldCan store a Date object. Saved in Redis as a float.FloatFieldCan store floats.BooleanFieldCan store bools. Saved in Redis as 1’s and 0’s.ReferenceFieldCan reference other redisco model.ListFieldCan store a list of unicode, int, float, as well as other redisco models.Attribute OptionsrequiredIf True, the attirbute cannot be None or empty. Strings are stripped to
check if they are empty. Default is False.defaultSets the default value of the attribute. Default is None.indexedIf True, redisco will create index entries for the attribute. Indexes
are used in filtering and ordering results of queries. For large bodies
of strings, this should be set to False. Default is True.validatorSet this to a callable that accepts two arguments – the field name and
the value of the attribute. The callable should return a list of tuples
with the first item is the field name, and the second item is the error.uniqueThe field must be unique. Default is False.DateField and DateTimeField Optionsauto_now_addAutomatically set the datetime/date field to now/today when the object
is first created. Default is False.auto_nowAutomatically set the datetime/date field to now/today everytime the object
is saved. Default is False.Saving and ValidatingTo save an object, call its save method. This returns True on success (i.e. when
the object is valid) and False otherwise.Calling Model.is_valid will validate the attributes and lists. Model.is_valid
is called when the instance is being saved. When there are invalid fields,
Model.errors will hold the list of tuples containing the invalid fields and
the reason for its invalidity. E.g.
[(‘name’, ‘required’),(‘name’, ‘too short’)]Fields can be validated using the validator argument of the attribute. Just
pass a callable that accepts two arguments – the field name and the value
of the attribute. The callable should return a list of errors.Model.validate will also be called before saving the instance. Override it
to validate instances not related to attributes.def not_me(field_name, value):
    if value == 'Me':
        return ((field_name, 'it is me'),)

class Person(models.Model):
    name = models.Attribute(required=True, validator=not_me)
    age = models.IntegerField()

    def validate(self):
        if self.age and self.age < 21:
            self._errors.append(('age', 'below 21'))

>>> person = Person(name='Me')
>>> person.is_valid()
False
>>> person.errors
[('name', 'it is me')]QueriesQueries are executed using a manager, accessed via the objects class
attribute.Person.objects.all()
Person.objects.filter(name='Conchita')
Person.objects.filter(name='Conchita').first()
Person.objects.all().order('name')
Person.objects.filter(fave_colors='Red')Ranged QueriesRedisco has a limited support for queries involving ranges – it can only
filter fields that are numeric, i.e. DateField, DateTimeField, IntegerField,
and FloatField. The zfilter method of the manager is used for these queries.Person.objects.zfilter(created_at__lt=datetime(2010, 4, 20, 5, 2, 0))
Person.objects.zfilter(created_at__gte=datetime(2010, 4, 20, 5, 2, 0))
Person.objects.zfilter(created_at__in=(datetime(2010, 4, 20, 5, 2, 0), datetime(2010, 5, 1)))ContainersRedisco has three containers that roughly match Redis’s supported data
structures: lists, sets, sorted set. Anything done to the container is
persisted to Redis.Sets>>> from redisco.containers import Set
>>> s = Set('myset')
>>> s.add('apple')
>>> s.add('orange')
>>> s.members
set(['orange', 'apple'])
>>> t = Set('nset')
>>> t.add('kiwi')
>>> t.add('guava')
>>> t.members
set(['kiwi', 'guava'])
>>> s.update(t)
>>> s.members
set(['kiwi', 'orange', 'guava', 'apple'])Lists>>> import redis
>>> from redisco.containers import List
>>> l = List('alpha')
>>> l.append('a')
>>> l.append('b')
>>> l.append('c')
>>> 'a' in l
True
>>> 'd' in l
False
>>> len(l)
3
>>> l.index('b')
1
>>> l.members
['a', 'b', 'c']Sorted Sets>>> zset = SortedSet('zset')
>>> zset.members
['d', 'a', 'b', 'c']
>>> 'e' in zset
False
>>> 'a' in zset
True
>>> zset.rank('d')
0
>>> zset.rank('b')
2
>>> zset[1]
'a'
>>> zset.add('f', 200)
>>> zset.members
['d', 'a', 'b', 'c', 'f']
>>> zset.add('d', 99)
>>> zset.members
['a', 'b', 'c', 'd', 'f']Dicts/Hashes>>> h = cont.Hash('hkey')
>>> len(h)
0
>>> h['name'] = "Richard Cypher"
>>> h['real_name'] = "Richard Rahl"
>>> h
<Hash 'hkey' {'name': 'Richard Cypher', 'real_name': 'Richard Rahl'}>
>>> h.dict
{'name': 'Richard Cypher', 'real_name': 'Richard Rahl'}Additional Info on ContainersSome methods of the Redis client that require the key as the first argument
can be accessed from the container itself.>>> l = List('mylist')
>>> l.lrange(0, -1)
0
>>> l.rpush('b')
>>> l.rpush('c')
>>> l.lpush('a')
>>> l.lrange(0, -1)
['a', 'b', 'c']
>>> h = Hash('hkey')
>>> h.hset('name', 'Richard Rahl')
>>> h
<Hash 'hkey' {'name': 'Richard Rahl'}>Connecting to RedisAll models and containers use a global Redis client object to
interact with the key-value storage. By default, it connects
to localhost:6379, selecting db 0. If you wish to specify settings:import redisco
redisco.connection_setup(host='localhost', port=6380, db=10)The arguments to connect are simply passed to the redis.Redis init method.For the containers, you can specify a second argument as the Redis client.
That client object will be used instead of the default.>>> import redis
>>> r = redis.Redis(host='localhost', port=6381)
>>> Set('someset', r)CreditsMost of the concepts are taken fromSoveran’s Redis related Ruby libraries.cyxfor sharing his expertise in indexing in Redis.
Django, of course, for the popular model API.