You can perform bitwise operations at the database level with F objects .
, , field & mask > 0 (field > 0) AND (field >= (field & mask)). , mask ((field & mask) == mask), , sql AND. , , . ( QuerySet . django, has_one_of has_all , PathThroughManager). . 1 * F - , django ( 1.5) sql (colors >= colors & mask, , TRUE & mask)
import operator
from django.db import models
from django.db.models import Q, F
_bit = lambda x: 2**(x-1)
RED = _bit(1)
GREEN = _bit(2)
BLUE = _bit(3)
WHITE = _bit(4)
class ItemColorsQuerySet(models.QuerySet):
def has_one_of(self, colors):
"""
Only those that has at least one of provided colors
"""
return self.filter(
colors__gt=0,
colors__gte=1 * F('colors').bitand(reduce(operator.or_, colors, 0))
)
def has_all(self, colors):
"""
Has all provided colors (and probably others)
"""
colors_q = map(lambda c: Q(colors__gte=1 * F('colors').bitand(c)), colors)
filter_q = reduce(operator.and_, colors_q, Q(colors__gt=0))
return self.filter(filter_q)
class Item(models.Model):
name = models.CharField(max_length=100, unique=True)
colors = models.PositiveIntegerField(default=0)
objects = ItemColorsQuerySet.as_manager()