+class UserProperty(BaseModel):
+ user = models.ForeignKey(User, related_name='properties')
+ key = models.CharField(max_length=16)
+ value = PickledObjectField()
+
+ class Meta:
+ app_label = 'forum'
+ unique_together = ('user', 'key')
+
+ def cache_key(self):
+ return self._generate_cache_key("%s:%s" % (self.user.id, self.key))
+
+ @classmethod
+ def infer_cache_key(cls, querydict):
+ if 'user' in querydict and 'key' in querydict:
+ cache_key = cls._generate_cache_key("%s:%s" % (querydict['user'].id, querydict['key']))
+ if len(cache_key) > django_settings.CACHE_MAX_KEY_LENGTH:
+ cache_key = cache_key[:django_settings.CACHE_MAX_KEY_LENGTH]
+ return cache_key
+
+ return None
+
+class UserPropertyDict(object):
+ def __init__(self, user):
+ self.__dict__['_user'] = user
+
+ def __get_property(self, name):
+ if self.__dict__.get('__%s__' % name, None):
+ return self.__dict__['__%s__' % name]
+ try:
+ user = self.__dict__['_user']
+ prop = UserProperty.objects.get(user=user, key=name)
+ self.__dict__['__%s__' % name] = prop
+ self.__dict__[name] = prop.value
+ return prop
+ except:
+ return None
+
+
+ def __getattr__(self, name):
+ if self.__dict__.get(name, None):
+ return self.__dict__[name]
+
+ prop = self.__get_property(name)
+
+ if prop:
+ return prop.value
+ else:
+ return None
+
+ def __setattr__(self, name, value):
+ current = self.__get_property(name)
+
+ if value is not None:
+ if current:
+ current.value = value
+ self.__dict__[name] = value
+ current.save(full_save=True)
+ else:
+ user = self.__dict__['_user']
+ prop = UserProperty(user=user, value=value, key=name)
+ prop.save()
+ self.__dict__[name] = value
+ self.__dict__['__%s__' % name] = prop
+ else:
+ if current:
+ current.delete()
+ del self.__dict__[name]
+ del self.__dict__['__%s__' % name]
+
+