annotate forums/tools.py @ 1192:980123d47763

Fix link to queues fork.
author Brian Neal <bgneal@gmail.com>
date Sun, 13 Mar 2022 15:53:41 -0500
parents c6c3ba5cf6eb
children
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@781 7 from forums.signals import notify_new_topic, notify_new_post
bgneal@147 8
bgneal@147 9
bgneal@147 10 def delete_user_posts(user):
bgneal@147 11 """
bgneal@147 12 This function deletes all the posts for a given user.
bgneal@147 13 It also cleans up any last visit database records for the user.
bgneal@147 14 This function adjusts the last post foreign keys before deleting
bgneal@147 15 the posts to avoid the cascading delete behavior.
bgneal@147 16 """
bgneal@147 17 posts = Post.objects.filter(user=user).select_related()
bgneal@147 18
bgneal@285 19 # delete attachments
bgneal@285 20 for post in posts:
bgneal@285 21 post.attachments.clear()
bgneal@285 22
bgneal@147 23 # build a set of topics and forums affected by the post deletions
bgneal@147 24
bgneal@147 25 topics = set(post.topic for post in posts)
bgneal@147 26 forums = set(topic.forum for topic in topics)
bgneal@147 27
bgneal@147 28 post_ids = [post.pk for post in posts]
bgneal@147 29 pending_delete = []
bgneal@147 30
bgneal@147 31 for topic in topics:
bgneal@147 32 if topic.last_post.pk in post_ids:
bgneal@147 33 topic_posts = Post.objects.filter(topic=topic).exclude(
bgneal@147 34 pk__in=post_ids)
bgneal@147 35 topic.post_count = topic_posts.count()
bgneal@147 36 if topic.post_count > 0:
bgneal@147 37 topic.last_post = topic_posts.latest()
bgneal@147 38 topic.update_date = topic.last_post.creation_date
bgneal@147 39 topic.save()
bgneal@147 40 else:
bgneal@147 41 # Topic should be deleted, it has no posts;
bgneal@147 42 # We can't delete it now as it could cascade and take out a
bgneal@147 43 # forum. Remember it for later deletion.
bgneal@147 44 pending_delete.append(topic)
bgneal@147 45
bgneal@147 46 for forum in forums:
bgneal@147 47 if forum.last_post.pk in post_ids:
bgneal@147 48 forum_posts = Post.objects.filter(topic__forum=forum).exclude(
bgneal@147 49 pk__in=post_ids)
bgneal@147 50 forum.post_count = forum_posts.count()
bgneal@147 51 if forum.post_count > 0:
bgneal@147 52 forum.last_post = forum_posts.latest()
bgneal@147 53 else:
bgneal@147 54 forum.last_post = None
bgneal@147 55 forum.save()
bgneal@348 56
bgneal@147 57 # Delete pending topics now because forums have just adjusted their
bgneal@147 58 # foreign keys into Post
bgneal@147 59 if pending_delete:
bgneal@147 60 topic_ids = [topic.pk for topic in pending_delete]
bgneal@147 61 Topic.objects.filter(pk__in=topic_ids).delete()
bgneal@147 62
bgneal@147 63 # Topics have been deleted, re-compute topic counts for forums
bgneal@147 64 for forum in forums:
bgneal@147 65 forum.topic_count = Topic.objects.filter(forum=forum).count()
bgneal@147 66 forum.save()
bgneal@348 67
bgneal@147 68 # All foreign keys are accounted for, we can now delete the posts in bulk.
bgneal@147 69 # Since some posts in our original queryset may have been deleted already,
bgneal@147 70 # run a new query (although it may be ok)
bgneal@147 71 Post.objects.filter(pk__in=post_ids).delete()
bgneal@147 72
bgneal@147 73 # delete all the last visit records for this user
bgneal@147 74 TopicLastVisit.objects.filter(user=user).delete()
bgneal@147 75 ForumLastVisit.objects.filter(user=user).delete()
bgneal@147 76
bgneal@228 77
bgneal@228 78 def create_topic(forum_slug, user, topic_name, post_body, ip='', sticky=False,
bgneal@228 79 locked=False):
bgneal@228 80 """Programmatically create a topic & first post in a given forum.
bgneal@228 81
bgneal@228 82 This function creates a new topic in the forum that has the slug
bgneal@228 83 specified by the 'forum_slug' argument. Other arguments are as follows:
bgneal@228 84 'user' - create the topic and post with this user as the owner
bgneal@228 85 'topic_name' - topic name (title)
bgneal@228 86 'post_body' - topic post body (as markup, not HTML)
bgneal@228 87 'ip' - IP address for the post (as a string)
bgneal@228 88 'sticky' - if True, the post will be stickied
bgneal@228 89 'locked' - if True, the post will be locked
bgneal@228 90
bgneal@1001 91 The new topic is returned.
bgneal@228 92 """
bgneal@228 93 try:
bgneal@228 94 forum = Forum.objects.get(slug=forum_slug)
bgneal@228 95 except Forum.DoesNotExist:
bgneal@316 96 logging.error('could not create_topic for forum_slug=%s', forum_slug)
bgneal@228 97 raise
bgneal@228 98
bgneal@228 99 topic = Topic(forum=forum,
bgneal@228 100 name=topic_name,
bgneal@228 101 user=user,
bgneal@228 102 sticky=sticky,
bgneal@228 103 locked=locked)
bgneal@228 104 topic.save()
bgneal@228 105
bgneal@228 106 post = Post(topic=topic,
bgneal@228 107 user=user,
bgneal@228 108 body=post_body,
bgneal@228 109 user_ip=ip)
bgneal@228 110 post.save()
bgneal@390 111
bgneal@781 112 notify_new_topic(topic)
bgneal@781 113 notify_new_post(post)
bgneal@1001 114 return topic
bgneal@781 115
bgneal@390 116
bgneal@390 117 def auto_favorite(post):
bgneal@390 118 """
bgneal@390 119 Given a newly created post, perform an auto-favorite action if the post
bgneal@390 120 creator has that option set in their profile.
bgneal@390 121
bgneal@390 122 """
bgneal@789 123 profile = post.user.profile
bgneal@390 124 if profile.auto_favorite:
bgneal@390 125 post.topic.bookmarkers.add(post.user)
bgneal@390 126
bgneal@390 127
bgneal@390 128 def auto_subscribe(post):
bgneal@390 129 """
bgneal@390 130 Given a newly created post, perform an auto-subscribe action if the post
bgneal@390 131 creator has that option set in their profile.
bgneal@390 132
bgneal@390 133 """
bgneal@789 134 profile = post.user.profile
bgneal@390 135 if profile.auto_subscribe:
bgneal@390 136 post.topic.subscribers.add(post.user)