-
Notifications
You must be signed in to change notification settings - Fork 9
/
hashfield.py
65 lines (50 loc) · 1.92 KB
/
hashfield.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
import hashlib
from django.db import models
from south.modelsinspector import add_introspection_rules
_hashit = lambda s: hashlib.sha1(s).hexdigest()
class HashField(models.CharField):
description = ('HashField is related to some other field in a model and'
'stores its hashed value for better indexing performance.')
def __init__(self, original, *args, **kwargs):
'''
:param original: name of the field storing the value to be hashed
'''
self.original = original
kwargs['max_length'] = 40
kwargs['null'] = False
kwargs.setdefault('db_index', True)
kwargs.setdefault('editable', False)
super(HashField, self).__init__(*args, **kwargs)
def calculate_hash(self, model_instance):
original_value = getattr(model_instance, self.original)
setattr(model_instance, self.attname, _hashit(original_value))
def pre_save(self, model_instance, add):
self.calculate_hash(model_instance)
return super(HashField, self).pre_save(model_instance, add)
# This tells South, how to store the field.
# more information: http://south.readthedocs.org/en/0.7.6/customfields.html
add_introspection_rules([
(
[HashField],
[],
{
"original": ["original", {}],
},
),
],
["^myproject\.fields\.HashField"]) # use your own path to HashField
class HashMixin(object):
'''Model mixin for easy work with HashFields.'''
def calculate_hashes(self):
'''Calculate hashes of all the HashFields in the model.
'''
hashed_fields = [field for field in self._meta.fields
if isinstance(field, HashField)]
for field in hashed_fields:
field.calculate_hash(self)
@classmethod
def calculate_hash(cls, value):
'''Calculate hash of the given value, which belongs to no specific
field.
'''
return _hashit(value)