Это старый вопрос, но я подумал, что покажу, как это можно сделать достаточно просто в Джанго.
Вот вспомогательный класс для подготовки вашего выбора:
class BitChoices(object):
def __init__(self, choices):
self._choices = []
self._lookup = {}
for index, (key, val) in enumerate(choices):
index = 2**index
self._choices.append((index, val))
self._lookup[key] = index
def __iter__(self):
return iter(self._choices)
def __len__(self):
return len(self._choices)
def __getattr__(self, attr):
try:
return self._lookup[attr]
except KeyError:
raise AttributeError(attr)
def get_selected_keys(self, selection):
""" Return a list of keys for the given selection """
return [ k for k,b in self._lookup.iteritems() if b & selection]
def get_selected_values(self, selection):
""" Return a list of values for the given selection """
return [ v for b,v in self._choices if b & selection]
Определите вашу модель с PositiveIntegerField и выберите нужные варианты:
WEEKDAYS = BitChoices((('mon', 'Monday'), ('tue', 'Tuesday'), ('wed', 'Wednesday'),
('thu', 'Thursday'), ('fri', 'Friday'), ('sat', 'Saturday'),
('sun', 'Sunday')
))
Это означает, что вы можете получить доступ к следующим значениям:
>>> print list(WEEKDAYS)
[(1, 'Monday'), (2, 'Tuesday'), (4, 'Wednesday'), (8, 'Thursday'), (16, 'Friday'), (32, 'Saturday'), (64, 'Sunday')]
>>> print WEEKDAYS.fri
16
>>> print WEEKDAYS.get_selected_values(52)
['Wednesday', 'Friday', 'Saturday']
Теперь определите вашу модель с помощью PositiveIntegerField
и эти варианты:
class Entry(models.Model):
weekdays = models.PositiveIntegerField(choices=WEEKDAYS)
И ваши модели готовы. Для запросов следующее помогает:
Entry.objects.extra(where=["weekdays & %s"], params=[WEEKDAYS.fri])
Может быть способ создать подкласс объекта Q()
, который аккуратно упаковывает запросы, поэтому они выглядят так:
Entry.objects.filter(HasBit('weekdays', WEEKDAYS.fri))
Или даже взломать подкласс F()
, чтобы создать что-то вроде этого:
Entry.objects.filter(weekdays=HasBit(WEEKDAYS.fri))
Но у меня нет времени, чтобы исследовать это в данный момент. .where
отлично работает и может быть абстрагирован в функцию набора запросов.
И последнее замечание: вы можете создать поле пользовательской модели, преобразующее битовую маску в базе данных в список или набор в Python. Затем можно использовать виджет SelectMultiple
(или CheckboxSelectMultiple
), чтобы позволить пользователю выбирать свои значения в админке.