import datetime
-import hashlib
+import re
from urllib import quote_plus, urlencode
from django.db import models, IntegrityError, connection, transaction
from django.utils.http import urlquote as django_urlquote
class CachedManager(models.Manager):
use_for_related_fields = True
+ int_cache_re = re.compile('^_[\w_]+cache$')
+
+ def cache_obj(self, obj):
+ int_cache_keys = [k for k in obj.__dict__.keys() if self.int_cache_re.match(k)]
+
+ for k in int_cache_keys:
+ del obj.__dict__[k]
+
+ cache.set(self.model.cache_key(obj.id), obj, 60 * 60)
def get(self, *args, **kwargs):
try:
- pk = [v for (k,v) in kwargs.items() if k in ('pk', 'pk__exact', 'id', 'id__exact') or k.endswith('_ptr__pk')][0]
+ pk = [v for (k,v) in kwargs.items() if k in ('pk', 'pk__exact', 'id', 'id__exact'
+ ) or k.endswith('_ptr__pk') or k.endswith('_ptr__id')][0]
except:
pk = None
if obj is None:
obj = super(CachedManager, self).get(*args, **kwargs)
- cache.set(key, obj, 60 * 60)
+ self.cache_obj(obj)
+ else:
+ d = obj.__dict__
return obj
except:
return super(CachedManager, self).get_or_create(*args, **kwargs)
+denorm_update = django.dispatch.Signal(providing_args=["instance", "field", "old", "new"])
+
+class DenormalizedField(models.IntegerField):
+ __metaclass__ = models.SubfieldBase
+
+ def contribute_to_class(self, cls, name):
+ super (DenormalizedField, self).contribute_to_class(cls, name)
+ if not hasattr(cls, '_denormalizad_fields'):
+ cls._denormalizad_fields = []
+
+ cls._denormalizad_fields.append(name)
class BaseModel(models.Model):
objects = CachedManager()
if self._original_state.get(k, missing) == missing or self._original_state[k] != v])
def save(self, *args, **kwargs):
+ put_back = None
+
+ if hasattr(self.__class__, '_denormalizad_fields'):
+ dirty = self.get_dirty_fields()
+ put_back = [f for f in self.__class__._denormalizad_fields if f in dirty]
+
+ if put_back:
+ for n in put_back:
+ self.__dict__[n] = models.F(n) + (self.__dict__[n] - dirty[n])
+
super(BaseModel, self).save(*args, **kwargs)
+
+ if put_back:
+ try:
+ self.__dict__.update(
+ self.__class__.objects.filter(id=self.id).values(*put_back)[0]
+ )
+ for f in put_back:
+ denorm_update.send(sender=self.__class__, instance=self, field=f,
+ old=self._original_state[f], new=self.__dict__[f])
+ except:
+ #todo: log this properly
+ pass
+
self._original_state = dict(self.__dict__)
- cache.set(self.cache_key(self.pk), self, 86400)
+ self.__class__.objects.cache_obj(self)
def delete(self):
cache.delete(self.cache_key(self.pk))
class ActiveObjectManager(models.Manager):
+ use_for_related_fields = True
def get_query_set(self):
return super(ActiveObjectManager, self).get_query_set().filter(canceled=False)
def get_query_set(self):
return super(UndeletedObjectManager, self).get_query_set().filter(deleted=False)
-class GenericContent(BaseModel):
- """
- Base class for Vote, Comment and FlaggedItem
- """
+class GenericContent(models.Model):
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
content_object = generic.GenericForeignKey('content_type', 'object_id')
else:
return False
+mark_canceled = django.dispatch.Signal(providing_args=['instance'])
+
+class CancelableContent(models.Model):
+ canceled = models.BooleanField(default=False)
+
+ def cancel(self):
+ if not self.canceled:
+ self.canceled = True
+ self.save()
+ mark_canceled.send(sender=self.__class__, instance=self)
+ return True
+
+ return False
+
+ class Meta:
+ abstract = True
+ app_label = 'forum'
+
-from meta import Comment, Vote, FlaggedItem
from node import Node, NodeRevision
class QandA(Node):
self.wikified_at = datetime.datetime.now()
self.save()
- def save(self, *args, **kwargs):
- self.__dict__['score'] = self.__dict__['vote_up_count'] - self.__dict__['vote_down_count']
- super(QandA,self).save(*args, **kwargs)
-
- try:
- ping_google()
- except Exception:
- logging.debug('problem pinging google did you register you sitemap with google?')