bgneal@81: """ bgneal@81: Views for the forums application. bgneal@81: """ bgneal@83: from django.contrib.auth.decorators import login_required bgneal@82: from django.http import Http404 bgneal@98: from django.http import HttpResponse bgneal@89: from django.http import HttpResponseBadRequest bgneal@90: from django.http import HttpResponseForbidden bgneal@83: from django.http import HttpResponseRedirect bgneal@83: from django.core.urlresolvers import reverse bgneal@91: from django.core.paginator import InvalidPage bgneal@82: from django.shortcuts import get_object_or_404 bgneal@81: from django.shortcuts import render_to_response bgneal@97: from django.template.loader import render_to_string bgneal@81: from django.template import RequestContext bgneal@89: from django.views.decorators.http import require_POST bgneal@81: bgneal@90: from core.paginator import DiggPaginator bgneal@98: from core.functions import email_admins bgneal@81: from forums.models import Forum bgneal@83: from forums.models import Topic bgneal@91: from forums.models import Post bgneal@98: from forums.models import FlaggedPost bgneal@83: from forums.forms import NewTopicForm bgneal@86: from forums.forms import PostForm bgneal@81: bgneal@90: ####################################################################### bgneal@90: bgneal@93: TOPICS_PER_PAGE = 50 bgneal@90: POSTS_PER_PAGE = 2 bgneal@90: bgneal@93: def create_topic_paginator(topics): bgneal@93: return DiggPaginator(topics, TOPICS_PER_PAGE, body=5, tail=2, margin=3, padding=2) bgneal@93: bgneal@93: def create_post_paginator(posts): bgneal@93: return DiggPaginator(posts, POSTS_PER_PAGE, body=5, tail=2, margin=3, padding=2) bgneal@90: bgneal@90: ####################################################################### bgneal@81: bgneal@81: def index(request): bgneal@82: """ bgneal@82: This view displays all the forums available, ordered in each category. bgneal@82: """ bgneal@81: forums = Forum.objects.all().select_related() bgneal@81: cats = {} bgneal@81: for forum in forums: bgneal@81: cat = cats.setdefault(forum.category.id, { bgneal@81: 'cat': forum.category, bgneal@81: 'forums': [], bgneal@81: }) bgneal@81: cat['forums'].append(forum) bgneal@81: bgneal@81: cmpdef = lambda a, b: cmp(a['cat'].position, b['cat'].position) bgneal@81: cats = sorted(cats.values(), cmpdef) bgneal@81: bgneal@81: return render_to_response('forums/index.html', { bgneal@81: 'cats': cats, bgneal@81: }, bgneal@81: context_instance=RequestContext(request)) bgneal@81: bgneal@82: bgneal@81: def forum_index(request, slug): bgneal@82: """ bgneal@82: Displays all the topics in a forum. bgneal@82: """ bgneal@82: forum = get_object_or_404(Forum, slug=slug) bgneal@82: topics = forum.topics.select_related() bgneal@93: paginator = create_topic_paginator(topics) bgneal@93: page_num = int(request.GET.get('page', 1)) bgneal@93: try: bgneal@93: page = paginator.page(page_num) bgneal@93: except InvalidPage: bgneal@93: raise Http404 bgneal@97: bgneal@97: # we do this for the template since it is rendered twice bgneal@97: page_nav = render_to_string('forums/pagination.html', {'page': page}) bgneal@82: bgneal@82: return render_to_response('forums/forum_index.html', { bgneal@82: 'forum': forum, bgneal@93: 'page': page, bgneal@97: 'page_nav': page_nav, bgneal@82: }, bgneal@82: context_instance=RequestContext(request)) bgneal@82: bgneal@82: bgneal@82: def topic_index(request, id): bgneal@82: """ bgneal@82: Displays all the posts in a topic. bgneal@82: """ bgneal@86: topic = get_object_or_404(Topic, pk=id) bgneal@86: topic.view_count += 1 bgneal@86: topic.save() bgneal@86: bgneal@86: posts = topic.posts.select_related() bgneal@93: paginator = create_post_paginator(posts) bgneal@93: page_num = int(request.GET.get('page', 1)) bgneal@90: try: bgneal@90: page = paginator.page(page_num) bgneal@90: except InvalidPage: bgneal@90: raise Http404 bgneal@90: bgneal@90: last_page = page_num == paginator.num_pages bgneal@86: bgneal@97: # we do this for the template since it is rendered twice bgneal@97: page_nav = render_to_string('forums/pagination.html', {'page': page}) bgneal@97: bgneal@86: return render_to_response('forums/topic.html', { bgneal@86: 'forum': topic.forum, bgneal@86: 'topic': topic, bgneal@90: 'page': page, bgneal@97: 'page_nav': page_nav, bgneal@87: 'last_page': last_page, bgneal@89: 'form': PostForm(initial={'topic_id': topic.id}), bgneal@86: }, bgneal@86: context_instance=RequestContext(request)) bgneal@83: bgneal@83: bgneal@83: @login_required bgneal@83: def new_topic(request, slug): bgneal@83: """ bgneal@83: This view handles the creation of new topics. bgneal@83: """ bgneal@83: forum = get_object_or_404(Forum, slug=slug) bgneal@83: if request.method == 'POST': bgneal@83: form = NewTopicForm(request.POST) bgneal@83: if form.is_valid(): bgneal@83: topic = form.save(forum, request.user, request.META.get("REMOTE_ADDR")) bgneal@83: return HttpResponseRedirect(reverse('forums-new_topic_thanks', bgneal@83: kwargs={'tid': topic.pk})) bgneal@83: else: bgneal@83: form = NewTopicForm() bgneal@83: bgneal@83: return render_to_response('forums/new_topic.html', { bgneal@83: 'forum': forum, bgneal@83: 'form': form, bgneal@83: }, bgneal@83: context_instance=RequestContext(request)) bgneal@83: bgneal@83: bgneal@83: @login_required bgneal@83: def new_topic_thanks(request, tid): bgneal@83: """ bgneal@83: This view displays the success page for a newly created topic. bgneal@83: """ bgneal@83: topic = get_object_or_404(Topic, pk=tid) bgneal@83: return render_to_response('forums/new_topic_thanks.html', { bgneal@83: 'forum': topic.forum, bgneal@83: 'topic': topic, bgneal@83: }, bgneal@83: context_instance=RequestContext(request)) bgneal@89: bgneal@89: bgneal@89: @require_POST bgneal@89: def quick_reply_ajax(request): bgneal@89: """ bgneal@89: This function handles the quick reply to a thread function. This bgneal@89: function is meant to be the target of an AJAX post, and returns bgneal@89: the HTML for the new post, which the client-side script appends bgneal@89: to the document. bgneal@89: """ bgneal@90: if not request.user.is_authenticated(): bgneal@90: return HttpResponseForbidden() bgneal@90: bgneal@89: form = PostForm(request.POST) bgneal@89: if form.is_valid(): bgneal@89: post = form.save(request.user, request.META.get("REMOTE_ADDR")) bgneal@89: return render_to_response('forums/display_post.html', { bgneal@89: 'post': post, bgneal@89: }, bgneal@89: context_instance=RequestContext(request)) bgneal@89: bgneal@89: return HttpResponseBadRequest(); bgneal@89: bgneal@91: bgneal@91: def goto_post(request, post_id): bgneal@91: """ bgneal@91: This function calculates what page a given post is on, then redirects bgneal@91: to that URL. This function is the target of get_absolute_url() for bgneal@91: Post objects. bgneal@91: """ bgneal@91: post = get_object_or_404(Post, pk=post_id) bgneal@91: count = post.topic.posts.filter(creation_date__lt=post.creation_date).count() bgneal@91: page = count / POSTS_PER_PAGE + 1 bgneal@91: url = reverse('forums-topic_index', kwargs={'id': post.topic.id}) + \ bgneal@91: '?page=%s#p%s' % (page, post.id) bgneal@91: return HttpResponseRedirect(url) bgneal@91: bgneal@98: bgneal@98: @require_POST bgneal@98: def flag_post(request): bgneal@98: """ bgneal@98: This function handles the flagging of posts by users. This function should bgneal@98: be the target of an AJAX post. bgneal@98: """ bgneal@98: if not request.user.is_authenticated(): bgneal@98: return HttpResponse('Please login or register to flag a post.') bgneal@98: bgneal@98: id = request.POST.get('id') bgneal@98: if id is None: bgneal@98: return HttpResponseBadRequest('No post id') bgneal@98: bgneal@98: try: bgneal@98: post = Post.objects.get(pk=id) bgneal@98: except Post.DoesNotExist: bgneal@98: return HttpResponseBadRequest('No post with id %s' % id) bgneal@98: bgneal@98: flag = FlaggedPost(user=request.user, post=post) bgneal@98: flag.save() bgneal@98: email_admins('A Post Has Been Flagged', """Hello, bgneal@98: bgneal@98: A user has flagged a forum post for review. bgneal@98: """) bgneal@98: return HttpResponse('The post was flagged. A moderator will review the post shortly. ' \ bgneal@98: 'Thanks for helping to improve the discussions on this site.')