Dies ist eine alte Frage, aber ich dachte, ich würde zeigen, wie es einfach in Django einfach gemacht werden könnte.
Hier ist eine Hilfsklasse für Ihre Entscheidungen vorbereiten:
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]
Definieren Sie Ihr Modell mit einem PositiveIntegerField, und die Entscheidungen würden Sie gerne:
WEEKDAYS = BitChoices((('mon', 'Monday'), ('tue', 'Tuesday'), ('wed', 'Wednesday'),
('thu', 'Thursday'), ('fri', 'Friday'), ('sat', 'Saturday'),
('sun', 'Sunday')
))
Dies bedeutet, dass Sie die Werte zugreifen können wie dies:
>>> 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']
Definieren Sie jetzt Ihr Modell mit PositiveIntegerField
und diese Auswahlmöglichkeiten:
class Entry(models.Model):
weekdays = models.PositiveIntegerField(choices=WEEKDAYS)
Und Ihre Modelle sind fertig. Bei Abfragen, tut folgendes den Trick:
Entry.objects.extra(where=["weekdays & %s"], params=[WEEKDAYS.fri])
Es kann ein Weg sein, um eine Q()
Objektunterklasse zu erstellen, die fein säuberlich Abfragen Pakete, so dass sie wie folgt aussehen:
Entry.objects.filter(HasBit('weekdays', WEEKDAYS.fri))
oder Hack auch bei einem F()
Unterklasse, so etwas zu schaffen:
Entry.objects.filter(weekdays=HasBit(WEEKDAYS.fri))
Aber ich habe nicht die Zeit, die zur Zeit zu erkunden. .where
funktioniert einwandfrei und kann in eine Queryset-Funktion abstrahiert werden.
Eine letzte Überlegung ist, dass Sie möglicherweise ein benutzerdefiniertes Modellfeld erstellen, das die Bitmaske in der Datenbank in eine Liste oder einen Satz in Python konvertiert. Sie können dann ein SelectMultiple
Widget (oder CheckboxSelectMultiple
) verwenden, damit der Benutzer seine Werte im Admin auswählen kann.
Ohne weitere Informationen (Größe des Datensatzes, meist lesen vs meist schreiben, etc.) geht mit Bitfields fühlt sich wie die gefürchtete vorzeitige Optimierung. –
Ich werde zusätzliche Informationen an die Frage anhängen. Danke Herr Rowell. –
Haben Sie darüber nachgedacht, eine Viele-zu-viele-Beziehung zwischen einem "Weekday" -Modell und dem fraglichen Modell hinzuzufügen? Ich weiß, das ist ein bisschen Overkill, wenn man bedenkt, dass die Wochentage in der Anzahl festgelegt sind, aber es würde die Filterung sehr einfach machen. –