annotate gpp/forums/tools.py @ 348:d1b11096595b

Fix #168; when nailing a spammer, clear their profile text fields. Guard against topics and forums that don't exist when deleting posts in the signal handler. Make the forum stats template tag only display the latest active users.
author Brian Neal <bgneal@gmail.com>
date Wed, 02 Mar 2011 02:18:28 +0000
parents 767cedc7d12a
children e0523e17ea43
rev   line source
bgneal@147 1 """
bgneal@147 2 This module contains misc. utility functions for forum management.
bgneal@147 3 """
bgneal@228 4 import logging
bgneal@228 5
bgneal@147 6 from forums.models import Post, Topic, Forum, ForumLastVisit, TopicLastVisit
bgneal@147 7
bgneal@147 8
bgneal@147 9 def delete_user_posts(user):
bgneal@147 10 """
bgneal@147 11 This function deletes all the posts for a given user.
bgneal@147 12 It also cleans up any last visit database records for the user.
bgneal@147 13 This function adjusts the last post foreign keys before deleting
bgneal@147 14 the posts to avoid the cascading delete behavior.
bgneal@147 15 """
bgneal@147 16 posts = Post.objects.filter(user=user).select_related()
bgneal@147 17
bgneal@285 18 # delete attachments
bgneal@285 19 for post in posts:
bgneal@285 20 post.attachments.clear()
bgneal@285 21
bgneal@147 22 # build a set of topics and forums affected by the post deletions
bgneal@147 23
bgneal@147 24 topics = set(post.topic for post in posts)
bgneal@147 25 forums = set(topic.forum for topic in topics)
bgneal@147 26
bgneal@147 27 post_ids = [post.pk for post in posts]
bgneal@147 28 pending_delete = []
bgneal@147 29
bgneal@147 30 for topic in topics:
bgneal@147 31 if topic.last_post.pk in post_ids:
bgneal@147 32 topic_posts = Post.objects.filter(topic=topic).exclude(
bgneal@147 33 pk__in=post_ids)
bgneal@147 34 topic.post_count = topic_posts.count()
bgneal@147 35 if topic.post_count > 0:
bgneal@147 36 topic.last_post = topic_posts.latest()
bgneal@147 37 topic.update_date = topic.last_post.creation_date
bgneal@147 38 topic.save()
bgneal@147 39 else:
bgneal@147 40 # Topic should be deleted, it has no posts;
bgneal@147 41 # We can't delete it now as it could cascade and take out a
bgneal@147 42 # forum. Remember it for later deletion.
bgneal@147 43 pending_delete.append(topic)
bgneal@147 44
bgneal@147 45 for forum in forums:
bgneal@147 46 if forum.last_post.pk in post_ids:
bgneal@147 47 forum_posts = Post.objects.filter(topic__forum=forum).exclude(
bgneal@147 48 pk__in=post_ids)
bgneal@147 49 forum.post_count = forum_posts.count()
bgneal@147 50 if forum.post_count > 0:
bgneal@147 51 forum.last_post = forum_posts.latest()
bgneal@147 52 else:
bgneal@147 53 forum.last_post = None
bgneal@147 54 forum.save()
bgneal@348 55
bgneal@147 56 # Delete pending topics now because forums have just adjusted their
bgneal@147 57 # foreign keys into Post
bgneal@147 58 if pending_delete:
bgneal@147 59 topic_ids = [topic.pk for topic in pending_delete]
bgneal@147 60 Topic.objects.filter(pk__in=topic_ids).delete()
bgneal@147 61
bgneal@147 62 # Topics have been deleted, re-compute topic counts for forums
bgneal@147 63 for forum in forums:
bgneal@147 64 forum.topic_count = Topic.objects.filter(forum=forum).count()
bgneal@147 65 forum.save()
bgneal@348 66
bgneal@147 67 # All foreign keys are accounted for, we can now delete the posts in bulk.
bgneal@147 68 # Since some posts in our original queryset may have been deleted already,
bgneal@147 69 # run a new query (although it may be ok)
bgneal@147 70 Post.objects.filter(pk__in=post_ids).delete()
bgneal@147 71
bgneal@147 72 # delete all the last visit records for this user
bgneal@147 73 TopicLastVisit.objects.filter(user=user).delete()
bgneal@147 74 ForumLastVisit.objects.filter(user=user).delete()
bgneal@147 75
bgneal@228 76
bgneal@228 77 def create_topic(forum_slug, user, topic_name, post_body, ip='', sticky=False,
bgneal@228 78 locked=False):
bgneal@228 79 """Programmatically create a topic & first post in a given forum.
bgneal@228 80
bgneal@228 81 This function creates a new topic in the forum that has the slug
bgneal@228 82 specified by the 'forum_slug' argument. Other arguments are as follows:
bgneal@228 83 'user' - create the topic and post with this user as the owner
bgneal@228 84 'topic_name' - topic name (title)
bgneal@228 85 'post_body' - topic post body (as markup, not HTML)
bgneal@228 86 'ip' - IP address for the post (as a string)
bgneal@228 87 'sticky' - if True, the post will be stickied
bgneal@228 88 'locked' - if True, the post will be locked
bgneal@228 89
bgneal@228 90 """
bgneal@228 91 try:
bgneal@228 92 forum = Forum.objects.get(slug=forum_slug)
bgneal@228 93 except Forum.DoesNotExist:
bgneal@316 94 logging.error('could not create_topic for forum_slug=%s', forum_slug)
bgneal@228 95 raise
bgneal@228 96
bgneal@228 97 topic = Topic(forum=forum,
bgneal@228 98 name=topic_name,
bgneal@228 99 user=user,
bgneal@228 100 sticky=sticky,
bgneal@228 101 locked=locked)
bgneal@228 102 topic.save()
bgneal@228 103
bgneal@228 104 post = Post(topic=topic,
bgneal@228 105 user=user,
bgneal@228 106 body=post_body,
bgneal@228 107 user_ip=ip)
bgneal@228 108 post.save()