annotate forums/tools.py @ 661:15dbe0ccda95

Prevent exceptions when viewing downloads in the admin when the file doesn't exist on the filesystem. This is usually seen in development but can also happen in production if the file is missing.
author Brian Neal <bgneal@gmail.com>
date Tue, 14 May 2013 21:02:47 -0500
parents ee87ea74d46b
children b6d6c9e37fae
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()
bgneal@390 109
bgneal@390 110
bgneal@390 111 def auto_favorite(post):
bgneal@390 112 """
bgneal@390 113 Given a newly created post, perform an auto-favorite action if the post
bgneal@390 114 creator has that option set in their profile.
bgneal@390 115
bgneal@390 116 """
bgneal@390 117 profile = post.user.get_profile()
bgneal@390 118 if profile.auto_favorite:
bgneal@390 119 post.topic.bookmarkers.add(post.user)
bgneal@390 120
bgneal@390 121
bgneal@390 122 def auto_subscribe(post):
bgneal@390 123 """
bgneal@390 124 Given a newly created post, perform an auto-subscribe action if the post
bgneal@390 125 creator has that option set in their profile.
bgneal@390 126
bgneal@390 127 """
bgneal@390 128 profile = post.user.get_profile()
bgneal@390 129 if profile.auto_subscribe:
bgneal@390 130 post.topic.subscribers.add(post.user)