annotate gpp/forums/tools.py @ 265:1ba2c6bf6eb7

Closing #98. Animated GIFs were losing their transparency and animated properties when saved as avatars. Reworked the avatar save process to only run the avatar through PIL if it is too big. This preserves the original uploaded file if it is within the desired size settings. This may still mangle big animated gifs. If this becomes a problem, then maybe look into calling the PIL Image.resize() method directly. Moved the PIL image specific functions from bio.forms to a new module: core.image for better reusability in the future.
author Brian Neal <bgneal@gmail.com>
date Fri, 24 Sep 2010 02:12:09 +0000
parents d77e0dc772ad
children 8fd4984d5c3b
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@147 18 # build a set of topics and forums affected by the post deletions
bgneal@147 19
bgneal@147 20 topics = set(post.topic for post in posts)
bgneal@147 21 forums = set(topic.forum for topic in topics)
bgneal@147 22
bgneal@147 23 post_ids = [post.pk for post in posts]
bgneal@147 24 pending_delete = []
bgneal@147 25
bgneal@147 26 for topic in topics:
bgneal@147 27 if topic.last_post.pk in post_ids:
bgneal@147 28 topic_posts = Post.objects.filter(topic=topic).exclude(
bgneal@147 29 pk__in=post_ids)
bgneal@147 30 topic.post_count = topic_posts.count()
bgneal@147 31 if topic.post_count > 0:
bgneal@147 32 topic.last_post = topic_posts.latest()
bgneal@147 33 topic.update_date = topic.last_post.creation_date
bgneal@147 34 topic.save()
bgneal@147 35 else:
bgneal@147 36 # Topic should be deleted, it has no posts;
bgneal@147 37 # We can't delete it now as it could cascade and take out a
bgneal@147 38 # forum. Remember it for later deletion.
bgneal@147 39 pending_delete.append(topic)
bgneal@147 40
bgneal@147 41 for forum in forums:
bgneal@147 42 if forum.last_post.pk in post_ids:
bgneal@147 43 forum_posts = Post.objects.filter(topic__forum=forum).exclude(
bgneal@147 44 pk__in=post_ids)
bgneal@147 45 forum.post_count = forum_posts.count()
bgneal@147 46 if forum.post_count > 0:
bgneal@147 47 forum.last_post = forum_posts.latest()
bgneal@147 48 else:
bgneal@147 49 forum.last_post = None
bgneal@147 50 forum.save()
bgneal@147 51
bgneal@147 52 # Delete pending topics now because forums have just adjusted their
bgneal@147 53 # foreign keys into Post
bgneal@147 54 if pending_delete:
bgneal@147 55 topic_ids = [topic.pk for topic in pending_delete]
bgneal@147 56 Topic.objects.filter(pk__in=topic_ids).delete()
bgneal@147 57
bgneal@147 58 # Topics have been deleted, re-compute topic counts for forums
bgneal@147 59 for forum in forums:
bgneal@147 60 forum.topic_count = Topic.objects.filter(forum=forum).count()
bgneal@147 61 forum.save()
bgneal@147 62
bgneal@147 63 # All foreign keys are accounted for, we can now delete the posts in bulk.
bgneal@147 64 # Since some posts in our original queryset may have been deleted already,
bgneal@147 65 # run a new query (although it may be ok)
bgneal@147 66 Post.objects.filter(pk__in=post_ids).delete()
bgneal@147 67
bgneal@147 68 # delete all the last visit records for this user
bgneal@147 69 TopicLastVisit.objects.filter(user=user).delete()
bgneal@147 70 ForumLastVisit.objects.filter(user=user).delete()
bgneal@147 71
bgneal@228 72
bgneal@228 73 def create_topic(forum_slug, user, topic_name, post_body, ip='', sticky=False,
bgneal@228 74 locked=False):
bgneal@228 75 """Programmatically create a topic & first post in a given forum.
bgneal@228 76
bgneal@228 77 This function creates a new topic in the forum that has the slug
bgneal@228 78 specified by the 'forum_slug' argument. Other arguments are as follows:
bgneal@228 79 'user' - create the topic and post with this user as the owner
bgneal@228 80 'topic_name' - topic name (title)
bgneal@228 81 'post_body' - topic post body (as markup, not HTML)
bgneal@228 82 'ip' - IP address for the post (as a string)
bgneal@228 83 'sticky' - if True, the post will be stickied
bgneal@228 84 'locked' - if True, the post will be locked
bgneal@228 85
bgneal@228 86 """
bgneal@228 87 try:
bgneal@228 88 forum = Forum.objects.get(slug=forum_slug)
bgneal@228 89 except Forum.DoesNotExist:
bgneal@228 90 logging.error('could not create_topic for forum_slug=%s' % forum_slug)
bgneal@228 91 raise
bgneal@228 92
bgneal@228 93 topic = Topic(forum=forum,
bgneal@228 94 name=topic_name,
bgneal@228 95 user=user,
bgneal@228 96 sticky=sticky,
bgneal@228 97 locked=locked)
bgneal@228 98 topic.save()
bgneal@228 99
bgneal@228 100 post = Post(topic=topic,
bgneal@228 101 user=user,
bgneal@228 102 body=post_body,
bgneal@228 103 user_ip=ip)
bgneal@228 104 post.save()