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
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:
# 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.