Created
May 11, 2011 10:43
-
-
Save barbuza/966267 to your computer and use it in GitHub Desktop.
BitOptionsField holds a short list of predefined options in a single integer field
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*- coding: utf-8 -*- | |
from django.db import models | |
from django.core import exceptions | |
__all__ = ("BitOptionsField", ) | |
class BitOptionsField(models.Field): | |
""" | |
BitOptionsField holds a short list of predefined options | |
in a single integer field. | |
'options' argument is required, it should provide predefined | |
list of options | |
'default' argument is optional, it can provide default list | |
of options | |
""" | |
__metaclass__ = models.SubfieldBase | |
def __init__(self, *args, **kwargs): | |
if "options" not in kwargs: | |
raise RuntimeError("options param is required for BitOptionsField") | |
self.options = kwargs.pop("options") | |
if "default" in kwargs: | |
if not isinstance(kwargs["default"], int): | |
kwargs["default"] = self._encode_options(kwargs["default"]) | |
else: | |
kwargs["default"] = 0 | |
super(BitOptionsField, self).__init__(*args, **kwargs) | |
def get_internal_type(self): | |
return "IntegerField" | |
def to_python(self, value): | |
if type(value) in (int, long): | |
return self._decode_options(value) | |
return value | |
def get_db_prep_value(self, value, connection=None, prepared=False): | |
if type(value) in (int, long): | |
return value | |
return self._encode_options(value) | |
def _decode_options(self, value): | |
opts = [] | |
for index, option in enumerate(self.options): | |
if value & (1 << index): | |
opts.append(option) | |
return opts | |
def _encode_options(self, value): | |
int_val = 0 | |
for option in value: | |
if option not in self.options: | |
raise exceptions.ValidationError("%s is not valid option" \ | |
% option) | |
int_val += (1 << self.options.index(option)) | |
return int_val | |
def south_field_triple(self): | |
from south.modelsinspector import introspector | |
field_class = self.__class__.__module__ + "." + self.__class__.__name__ | |
args, kwargs = introspector(self) | |
kwargs["options"] = [] | |
return (field_class, args, kwargs) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment