David Cramer's Blog

BitField's in Django

Today we’re releasing another heavily used component from the DISQUS code base, our BitField class. While not a true BIT field (it uses a BIGINT), it still allows you the convenience of accessing the values as if they were bit flags.

When I joined DISQUS about 7 months ago, we were using a Q-like object class to do checks against our BigIntegerField’s. It worked fairly well, but was just too verbose. To add to that, we had a function which would attach callables to the instance for each flag. This let us do things like instance.FLAG_NAME() to check if it was set, and intance.FLAG_NAME(True) to set the flag. This worked well, but, like many things, we wanted to improve on it.

So we ended up building out BitField. We modeled it off of the concept of a simple attribute key store. The idea was to keep it dead simple to add flags, but also allow easy access and querying on those flags. A complete guide is available on the GitHub project page, so we’re just going to highlight usage of it.

First things first, defining your BitField. All you have to do is pass it a list of keys as the flags kwarg:

1
2
3
4
5
6
7
8
from bitfield import BitField

class MyModel(models.Model):
    flags = BitField(flags=(
        'awesome_flag',
        'flaggy_foo',
        'baz_bar',
    ))

Now reading and writing bits is very pythonic:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# Create the model
o = MyModel.objects.create(flags=0)

# Add awesome_flag (does not work in SQLite)
MyModel.objects.filter(pk=o.pk).update(flags=MyModel.flags.awesome_flag)

# Set flags manually to [awesome_flag, flaggy_foo]
MyModel.objects.filter(pk=o.pk).update(flags=3)

# Remove awesome_flag (does not work in SQLite)
MyModel.objects.filter(pk=o.pk).update(flags=~MyModel.flags.awesome_flag)

# Test awesome_flag
if o.flags.awesome_flag:
    print "Happy times!"

# List all flags on the field
for f in o.flags:
    print f

Let us know if you have any feedback, and make sure you subscribe to updates from our code blog.