Browse Source

Lazily keep user profiles stats in sync.

Ralfp 12 years ago
parent
commit
618bba58a2

+ 6 - 1
misago/apps/profiles/template.py

@@ -16,7 +16,7 @@ def RequestContext(request, context=None):
     if request.user.is_authenticated() and request.user.pk != context['profile'].pk:
     if request.user.is_authenticated() and request.user.pk != context['profile'].pk:
         context['follows'] = request.user.is_following(context['profile'])
         context['follows'] = request.user.is_following(context['profile'])
         context['ignores'] = request.user.is_ignoring(context['profile'])
         context['ignores'] = request.user.is_ignoring(context['profile'])
-        
+    
     # Find out if this user allows us to see his activity
     # Find out if this user allows us to see his activity
     if request.user.pk != context['profile'].pk:
     if request.user.pk != context['profile'].pk:
         if context['profile'].hide_activity == 2:
         if context['profile'].hide_activity == 2:
@@ -36,6 +36,11 @@ def RequestContext(request, context=None):
         # Fake "right now" time
         # Fake "right now" time
         context['online'] = {'last': timezone.now()}
         context['online'] = {'last': timezone.now()}
 
 
+    # Sync member
+    if context['profile'].sync_profile():
+        print 'SYNCED!'
+        context['profile'].save(force_update=True)
+
     context['tabs'] = []
     context['tabs'] = []
     for extension in settings.PROFILE_EXTENSIONS:
     for extension in settings.PROFILE_EXTENSIONS:
         profile_module = import_module(extension + '.profile')
         profile_module = import_module(extension + '.profile')

+ 11 - 1
misago/models/karmamodel.py

@@ -1,6 +1,7 @@
 from django.db import models
 from django.db import models
+from django.db.models import Sum
 from misago.signals import (merge_post, merge_thread, move_forum_content,
 from misago.signals import (merge_post, merge_thread, move_forum_content,
-                            move_post, move_thread, rename_user)
+                            move_post, move_thread, rename_user, sync_user_profile)
 
 
 class Karma(models.Model):
 class Karma(models.Model):
     forum = models.ForeignKey('Forum')
     forum = models.ForeignKey('Forum')
@@ -57,3 +58,12 @@ def merge_posts_handler(sender, **kwargs):
     kwargs['new_post'].downvotes += sender.downvotes
     kwargs['new_post'].downvotes += sender.downvotes
 
 
 merge_post.connect(merge_posts_handler, dispatch_uid="merge_posts_karmas")
 merge_post.connect(merge_posts_handler, dispatch_uid="merge_posts_karmas")
+
+
+def sync_user_handler(sender, **kwargs):
+    sender.karma_given_p = sender.karma_set.filter(score__gt=0).count()
+    sender.karma_given_n = sender.karma_set.filter(score__lt=0).count()
+    sender.karma_p = sender.post_set.all().aggregate(Sum('upvotes'))['upvotes__sum']
+    sender.karma_n = sender.post_set.all().aggregate(Sum('downvotes'))['downvotes__sum']
+
+sync_user_profile.connect(sync_user_handler, dispatch_uid="sync_user_karmas")

+ 8 - 1
misago/models/postmodel.py

@@ -3,7 +3,8 @@ from django.db.models import F
 from django.utils import timezone
 from django.utils import timezone
 from django.utils.translation import ugettext_lazy as _
 from django.utils.translation import ugettext_lazy as _
 from misago.signals import (delete_user_content, merge_post, merge_thread,
 from misago.signals import (delete_user_content, merge_post, merge_thread,
-                            move_forum_content, move_post, move_thread, rename_user)
+                            move_forum_content, move_post, move_thread,
+                            rename_user, sync_user_profile)
 
 
 class PostManager(models.Manager):
 class PostManager(models.Manager):
     def filter_stats(self, start, end):
     def filter_stats(self, start, end):
@@ -154,3 +155,9 @@ def merge_thread_handler(sender, **kwargs):
     Post.objects.filter(thread=sender).update(thread=kwargs['new_thread'], merge=F('merge') + kwargs['merge'])
     Post.objects.filter(thread=sender).update(thread=kwargs['new_thread'], merge=F('merge') + kwargs['merge'])
 
 
 merge_thread.connect(merge_thread_handler, dispatch_uid="merge_threads_posts")
 merge_thread.connect(merge_thread_handler, dispatch_uid="merge_threads_posts")
+
+
+def sync_user_handler(sender, **kwargs):
+    sender.posts = sender.post_set.count()
+
+sync_user_profile.connect(sync_user_handler, dispatch_uid="sync_user_posts")

+ 7 - 1
misago/models/threadmodel.py

@@ -5,7 +5,7 @@ from django.db.models.signals import pre_delete
 from django.utils import timezone
 from django.utils import timezone
 from django.utils.translation import ugettext_lazy as _
 from django.utils.translation import ugettext_lazy as _
 from misago.signals import (delete_user_content, merge_thread, move_forum_content,
 from misago.signals import (delete_user_content, merge_thread, move_forum_content,
-                            move_thread, rename_user)
+                            move_thread, rename_user, sync_user_profile)
 from misago.utils.strings import slugify
 from misago.utils.strings import slugify
 
 
 class ThreadManager(models.Manager):
 class ThreadManager(models.Manager):
@@ -206,3 +206,9 @@ def delete_user_handler(sender, instance, using, **kwargs):
                 thread.delete()
                 thread.delete()
 
 
 pre_delete.connect(delete_user_handler, dispatch_uid="delete_user_participations")
 pre_delete.connect(delete_user_handler, dispatch_uid="delete_user_participations")
+
+
+def sync_user_handler(sender, **kwargs):
+    sender.threads = sender.thread_set.count()
+
+sync_user_profile.connect(sync_user_handler, dispatch_uid="sync_user_threads")

+ 18 - 3
misago/models/usermodel.py

@@ -1,4 +1,5 @@
 import hashlib
 import hashlib
+from datetime import timedelta
 import math
 import math
 from random import choice
 from random import choice
 from path import path
 from path import path
@@ -14,7 +15,7 @@ from django.utils import timezone as tz_util
 from django.utils.translation import ugettext_lazy as _
 from django.utils.translation import ugettext_lazy as _
 from misago.acl.builder import build_acl
 from misago.acl.builder import build_acl
 from misago.monitor import Monitor
 from misago.monitor import Monitor
-from misago.signals import delete_user_content, rename_user
+from misago.signals import delete_user_content, rename_user, sync_user_profile
 from misago.utils.avatars import avatar_size
 from misago.utils.avatars import avatar_size
 from misago.utils.strings import random_string, slugify
 from misago.utils.strings import random_string, slugify
 from misago.validators import validate_username, validate_password, validate_email
 from misago.validators import validate_username, validate_password, validate_email
@@ -508,8 +509,13 @@ class User(models.Model):
     def get_date(self):
     def get_date(self):
         return self.join_date
         return self.join_date
 
 
-    def sync_user(self):
-        pass
+    def sync_profile(self):
+        if (settings.PROFILES_SYNC_FREQUENCY > 0 and
+                self.last_sync <= tz_util.now() - timedelta(days=settings.PROFILES_SYNC_FREQUENCY)):
+            sync_user_profile.send(sender=self)
+            self.last_sync = tz_util.now()
+            return True
+        return False
 
 
 
 
 class Guest(object):
 class Guest(object):
@@ -555,3 +561,12 @@ class Crawler(Guest):
     def is_crawler(self):
     def is_crawler(self):
         return True
         return True
 
 
+
+"""
+Signals handlers
+"""
+def sync_user_handler(sender, **kwargs):
+    sender.following = sender.follows.count()
+    sender.followers = sender.follows_set.count()
+
+sync_user_profile.connect(sync_user_handler, dispatch_uid="sync_user_follows")

+ 5 - 1
misago/settings_base.py

@@ -42,12 +42,16 @@ LOCALE_PATHS = (
 # If DEBUG_MODE is on, all emails will be sent to this address instead of real recipient.
 # If DEBUG_MODE is on, all emails will be sent to this address instead of real recipient.
 CATCH_ALL_EMAIL_ADDRESS = ''
 CATCH_ALL_EMAIL_ADDRESS = ''
 
 
-# Forums and threads read tracker length (days
+# Forums and threads read tracker length (days)
 # Enter 0 to turn tracking off
 # Enter 0 to turn tracking off
 # The bigger the number, then longer tracker keeps threads reads
 # The bigger the number, then longer tracker keeps threads reads
 # information and the more costful it is to track reads
 # information and the more costful it is to track reads
 READS_TRACKER_LENGTH = 7
 READS_TRACKER_LENGTH = 7
 
 
+# Min. number of days between synchronisating member profiles
+# Allows you to keep your member profiles up to date, enter 0 to never sync
+PROFILES_SYNC_FREQUENCY = 7
+
 # Heartbeat Path for crons
 # Heartbeat Path for crons
 # Use this path if you wish to keep Misago alive using separate cron
 # Use this path if you wish to keep Misago alive using separate cron
 # By quering this path from your cron you'll keep Misago's base clean
 # By quering this path from your cron you'll keep Misago's base clean

+ 2 - 1
misago/signals.py

@@ -7,4 +7,5 @@ merge_thread = django.dispatch.Signal(providing_args=["new_thread", "merge"])
 move_forum_content = django.dispatch.Signal(providing_args=["move_to"])
 move_forum_content = django.dispatch.Signal(providing_args=["move_to"])
 move_post = django.dispatch.Signal(providing_args=["move_to"])
 move_post = django.dispatch.Signal(providing_args=["move_to"])
 move_thread = django.dispatch.Signal(providing_args=["move_to"])
 move_thread = django.dispatch.Signal(providing_args=["move_to"])
-rename_user = django.dispatch.Signal()
+rename_user = django.dispatch.Signal()
+sync_user_profile = django.dispatch.Signal()