I created a Field to save the weekdays, used in a model like that (models.py):
from myfields import *
from django.db import models
class MyModel(models.Model):
weekdays = WeekdayField()
The file in which i have stored the form declaration is myfields.py and is this one:
from django.db import models
from django import forms
class Weekdays(object):
CHOICES = (
(1, "Monday"),
(2, "Tuesday"),
(4, "Wednesday"),
(8, "Thursday"),
(16, "Friday"),
(32, "Saturday"),
(64, "Sunday"),
)
MONDAY,TUESDAY,WEDNESDAY,THURSDAY,FRIDAY,SATURDAY,SUNDAY = [2**i for i in range(0,7)]
del i
def __init__(self, value=0):
self.raw = value
def __add__(self, other):
return Weekdays(self.raw | other)
def __sub__(self, other):
return Weekdays(self.raw & (-1 ^ other))
def __unicode__(self):
ret = []
for ele in Weekdays.CHOICES:
if (self.raw & ele[0]) >> ele[0] == 1:
ret.append(ele[1])
return ",".join(ret)
def __iter__(self):
ret = []
for ele in Weekdays.CHOICES:
if (self.raw & ele[0]) >> ele[0] == 1:
ret.append(ele)
return iter(ret)
def __len__(self):
i = 0
for n in range(7):
if (self.raw & n) >> n == 1:
i += 1
return i
class WeekdayField(models.Field):
description = "Multiple select of weekdays"
__metaclass__ = models.SubfieldBase
def __init__(self, *args, **kwargs):
kwargs['max_length'] = 3
super(WeekdayField, self).__init__(*args, **kwargs)
def to_python(self, value):
if isinstance(value, int):
return [ wd for wd in Weekdays(value) ]
if isinstance(value, Weekdays):
return value
if isinstance(value, list): #list of weekstay
wd = Weekdays()
for val in value:
wd += int(val)
return wd
# PY to DB
def get_prep_value(self, value):
return value.raw
def formfield(self, **kwargs):
defaults = {'form_class': WeekdayFormField}
defaults.update(kwargs)
return super(WeekdayField, self).formfield(**defaults)
def get_internal_type(self):
return "IntegerField"
class WeekdayFormField(forms.MultipleChoiceField):
def __init__(self, *args, **kwargs):
if 'choices' not in kwargs:
kwargs['choices'] = Weekdays.CHOICES
kwargs.pop('max_length', None)
if 'widget' not in kwargs:
kwargs['widget'] = forms.widgets.CheckboxSelectMultiple
super(WeekdayFormField, self).__init__(*args, **kwargs)
def clean(self, value):
super(WeekdayFormField, self).clean(value)
possible_values = [ str(x[0]) for x in Weekdays.CHOICES ]
for v in value:
if not v in possible_values:
raise forms.ValidationError("Day not valid")
return value
Using this i can create and remove the elements through Django Admin, but when i modify a value i don’t see the value that i stored before. I looked into the database and the value are stored right.
Any ideas on how to make me see what is the current value on Django Admin, during the modification?
I’ve the solution! it was a wrong the implementation of the methods
Weekdays.__unicode__()andWeekdays.__iter__().Finally i had also changed the two methods reported below, in
WeekdayField.I hope this will be helpful to someone!