1
|
# -*- coding: utf-8 -*-
|
2
|
|
3
|
from django.db import models
|
4
|
from django.db.models import fields
|
5
|
from django import forms
|
6
|
from localflavor.fr.forms import FRPhoneNumberField, FRZipCodeField
|
7
|
from django.utils.text import capfirst
|
8
|
|
9
|
|
10
|
class BaseModelMixin(object):
|
11
|
def __repr__(self):
|
12
|
return '<%s %s %r>' % (self.__class__.__name__, self.id, unicode(self))
|
13
|
|
14
|
|
15
|
class PhoneNumberField(models.CharField):
|
16
|
def __init__(self, *args, **kwargs):
|
17
|
kwargs['max_length'] = 20
|
18
|
super(PhoneNumberField, self).__init__(*args, **kwargs)
|
19
|
|
20
|
def formfield(self, **kwargs):
|
21
|
default = { 'form_class': FRPhoneNumberField }
|
22
|
default.update(kwargs)
|
23
|
return super(PhoneNumberField, self).formfield(**kwargs)
|
24
|
|
25
|
|
26
|
class ZipCodeField(models.CharField):
|
27
|
def __init__(self, **kwargs):
|
28
|
kwargs['max_length'] = 5
|
29
|
super(ZipCodeField, self).__init__(**kwargs)
|
30
|
|
31
|
def formfield(self, **kwargs):
|
32
|
default = { 'form_class': FRZipCodeField }
|
33
|
default.update(kwargs)
|
34
|
return super(ZipCodeField, self).formfield(**kwargs)
|
35
|
|
36
|
class WeekRankField(models.PositiveIntegerField):
|
37
|
'''Map a list of integers to its encoding as a binary number'''
|
38
|
__metaclass__ = models.SubfieldBase
|
39
|
|
40
|
def __init__(self, **kwargs):
|
41
|
kwargs['blank'] = True
|
42
|
kwargs['null'] = True
|
43
|
super(WeekRankField, self).__init__(**kwargs)
|
44
|
|
45
|
def to_python(self, value):
|
46
|
if isinstance(value, list):
|
47
|
if value:
|
48
|
try:
|
49
|
value = map(int, value)
|
50
|
except ValueError:
|
51
|
raise forms.ValidationError('value must be a sequence of value coercible to integers')
|
52
|
if any((i < 0 or i > 4 for i in value)):
|
53
|
raise forms.ValidationError('value must be a list of integers between 0 and 4')
|
54
|
return map(int, set(value))
|
55
|
else:
|
56
|
return None
|
57
|
value = super(WeekRankField, self).to_python(value)
|
58
|
if value is None:
|
59
|
return None
|
60
|
try:
|
61
|
value = int(value)
|
62
|
except ValueError:
|
63
|
raise forms.ValidationError('value must be convertible to an integer')
|
64
|
if value < 0 or value >= 64:
|
65
|
raise forms.ValidationError('value must be between 0 and 64')
|
66
|
return tuple((i for i in range(0, 5) if (1 << i) & value))
|
67
|
|
68
|
|
69
|
def clean(self, value, model_instance):
|
70
|
"""
|
71
|
Convert the value's type and run validation. Validation errors
|
72
|
from to_python and validate are propagated. The correct value is
|
73
|
returned if no error is raised.
|
74
|
"""
|
75
|
value = self.to_python(value)
|
76
|
[self.validate(v, model_instance) for v in value]
|
77
|
self.run_validators(value)
|
78
|
return value
|
79
|
|
80
|
|
81
|
def get_prep_lookup(self, lookup_type, value):
|
82
|
if lookup_type in ('exact', 'in'):
|
83
|
s = set(((1 << v) | i for v in value for i in range(0, 64)))
|
84
|
return s
|
85
|
elif lookup_type == 'range':
|
86
|
value = sorted(value)
|
87
|
return set(((1 << v) | i for v in range(value[0], value[1]) for i in range(0, 64)))
|
88
|
else:
|
89
|
return fields.Field.get_prep_lookup(self, lookup_type, value)
|
90
|
|
91
|
|
92
|
def get_prep_value(self, value):
|
93
|
if value:
|
94
|
x = sum((1 << int(i) for i in value))
|
95
|
return x
|
96
|
else:
|
97
|
return None
|
98
|
|
99
|
def formfield(self, **kwargs):
|
100
|
defaults = {'required': not self.blank, 'label': capfirst(self.verbose_name),
|
101
|
'help_text': self.help_text, 'choices': self.get_choices(include_blank=False)}
|
102
|
if self.has_default():
|
103
|
defaults['initial'] = self.get_default()
|
104
|
defaults.update(kwargs)
|
105
|
return forms.MultipleChoiceField(**defaults)
|
106
|
|
107
|
from south.modelsinspector import add_introspection_rules
|
108
|
add_introspection_rules([], ["^calebasse\.models\..*Field"])
|
109
|
|