diff options
-rw-r--r-- | askbot/models/__init__.py | 12 | ||||
-rw-r--r-- | askbot/models/content.py | 27 | ||||
-rw-r--r-- | askbot/models/meta.py | 26 | ||||
-rw-r--r-- | askbot/tasks.py | 59 | ||||
-rw-r--r-- | askbot/tests/skin_tests.py | 1 |
5 files changed, 104 insertions, 21 deletions
diff --git a/askbot/models/__init__.py b/askbot/models/__init__.py index 6ef9e4a1..a4d21caa 100644 --- a/askbot/models/__init__.py +++ b/askbot/models/__init__.py @@ -2078,9 +2078,9 @@ def record_post_update_activity( if newly_mentioned_users is None: newly_mentioned_users = list() - from askbot.tasks import record_post_update_task + from askbot import tasks - record_post_update_task.delay( + tasks.record_post_update_celery_task.delay( post_id = post.id, post_content_type_id = ContentType.objects.get_for_model(post).id, newly_mentioned_user_id_list = [u.id for u in newly_mentioned_users], @@ -2088,6 +2088,14 @@ def record_post_update_activity( timestamp = timestamp, created = created, ) + #non-celery version + #tasks.record_post_update( + # post = post, + # newly_mentioned_users = newly_mentioned_users, + # updated_by = updated_by, + # timestamp = timestamp, + # created = created, + #) def record_award_event(instance, created, **kwargs): diff --git a/askbot/models/content.py b/askbot/models/content.py index b320f541..84bd2421 100644 --- a/askbot/models/content.py +++ b/askbot/models/content.py @@ -215,11 +215,28 @@ class Content(models.Model): receive instant notifications for a given post this method works for questions and answers - parameter "potential_subscribers" is not used here, - but left for the uniformity of the interface (Comment method does use it) - - comment class has it's own variant which does have quite a bit - of duplicated code at the moment + Arguments: + + * ``potential_subscribers`` is not used here! todo: why? - clean this out + parameter is left for the uniformity of the interface + (Comment method does use it) + normally these methods would determine the list + :meth:`~askbot.models.question.Question.get_response_recipients` + :meth:`~askbot.models.question.Answer.get_response_recipients` + - depending on the type of the post + * ``mentioned_users`` - users, mentioned in the post for the first time + * ``exclude_list`` - users who must be excluded from the subscription + + Users who receive notifications are: + + * of ``mentioned_users`` - those who subscribe for the instant + updates on the @name mentions + * those who follow the parent question + * global subscribers (any personalized tag filters are applied) + * author of the question who subscribe to instant updates + on questions that they asked + * authors or any answers who subsribe to instant updates + on the questions which they answered """ #print '------------------' #print 'in content function' diff --git a/askbot/models/meta.py b/askbot/models/meta.py index f9df0619..290f5ef0 100644 --- a/askbot/models/meta.py +++ b/askbot/models/meta.py @@ -164,17 +164,17 @@ class Comment(base.MetaContent, base.UserContent): return const.TYPE_ACTIVITY_COMMENT_ANSWER, self def get_response_receivers(self, exclude_list = None): - """get list of users who authored comments on a post - and the post itself + """Response receivers are commenters of the + same post and the authors of the post itself. """ assert(exclude_list is not None) users = set() + #get authors of parent object and all associated comments users.update( - #get authors of parent object and all associated comments - self.content_object.get_author_list( - include_comments = True, - ) + self.content_object.get_author_list( + include_comments = True, ) + ) users -= set(exclude_list) return list(users) @@ -184,10 +184,20 @@ class Comment(base.MetaContent, base.UserContent): mentioned_users = None, exclude_list = None ): - """get list of users who want instant notifications - about this comment + """get list of users who want instant notifications about comments argument potential_subscribers is required as it saves on db hits + + Here is the list of people who will receive the notifications: + + * mentioned users + * of response receivers + (see :meth:`~askbot.models.meta.Comment.get_response_receivers`) - + those who subscribe for the instant + updates on comments and @mentions + * all who follow the question explicitly + * all global subscribers + (tag filtered, and subject to personalized settings) """ #print 'in meta function' #print 'potential subscribers: ', potential_subscribers diff --git a/askbot/tasks.py b/askbot/tasks.py index e230be31..8dfea5b4 100644 --- a/askbot/tasks.py +++ b/askbot/tasks.py @@ -1,3 +1,22 @@ +"""Definitions of Celery tasks in Askbot +in this module there are two types of functions: + +* those wrapped with a @task decorator and a ``_celery_task`` suffix - celery tasks +* those with the same base name, but without the decorator and the name suffix + the actual work units run by the task + +Celery tasks are special functions in a way that they require all the parameters +be serializable - so instead of ORM objects we pass object id's and +instead of query sets - lists of ORM object id's. + +That is the reason for having two types of methods here: + +* the base methods (those without the decorator and the + ``_celery_task`` in the end of the name + are work units that are called from the celery tasks. +* celery tasks - shells that reconstitute the necessary ORM + objects and call the base methods +""" from django.contrib.contenttypes.models import ContentType from celery.decorators import task from askbot.models import Activity @@ -5,7 +24,7 @@ from askbot.models import User from askbot.models import send_instant_notifications_about_activity_in_post @task(ignore_results = True) -def record_post_update_task( +def record_post_update_celery_task( post_id, post_content_type_id, newly_mentioned_user_id_list = None, @@ -13,10 +32,42 @@ def record_post_update_task( timestamp = None, created = False, ): - + #reconstitute objects from the database updated_by = User.objects.get(id = updated_by_id) post_content_type = ContentType.objects.get(id = post_content_type_id) post = post_content_type.get_object_for_this_type(id = post_id) + newly_mentioned_users = User.objects.filter( + id__in = newly_mentioned_user_id_list + ) + + + record_post_update( + post = post, + updated_by = updated_by, + newly_mentioned_users = newly_mentioned_users, + timestamp = timestamp, + created = created, + ) + +def record_post_update( + post = None, + updated_by = None, + newly_mentioned_users = None, + timestamp = None, + created = False + ): + """Called when a post is updated. Arguments: + + * ``newly_mentioned_users`` - users who are mentioned in the + post for the first time + * ``created`` - a boolean. True when ``post`` has just been created + * remaining arguments are self - explanatory + + The method does two things: + + * records "red envelope" recipients of the post + * sends email alerts to all subscribers to the post + """ #todo: take into account created == True case (activity_type, update_object) = post.get_updated_activity_data(created) @@ -42,10 +93,6 @@ def record_post_update_task( assert(updated_by not in recipients) - newly_mentioned_users = User.objects.filter( - id__in = newly_mentioned_user_id_list - ) - for user in set(recipients) | set(newly_mentioned_users): user.increment_response_count() user.save() diff --git a/askbot/tests/skin_tests.py b/askbot/tests/skin_tests.py index 978f45b1..660daa4e 100644 --- a/askbot/tests/skin_tests.py +++ b/askbot/tests/skin_tests.py @@ -36,6 +36,7 @@ class SkinTests(TestCase): 'test_skin' ) shutil.rmtree(test_skin_dir) + askbot_settings.update('ASKBOT_DEFAULT_SKIN', 'default') def assert_default_logo_in_skin(self, skin_name): url = skin_utils.get_media_url(askbot_settings.SITE_LOGO_URL) |