# coding: utf-8 import json, math, hashlib from django.http import HttpResponse, Http404 from django.shortcuts import render_to_response, redirect, get_object_or_404 from django.contrib import auth from django.contrib.auth.decorators import login_required from django.template import RequestContext from django.utils import timezone from django.conf import settings from forum.models import ForumUser, Topic, Favorite, Vote, Reply, Node, Notification, Plane from forum.forms.topic import ReplyForm, CreateForm from common import find_mentions def get_index(request): user = request.user if user.is_authenticated(): counter = { 'topics': user.topic_author.all().count(), 'replies': user.reply_author.all().count(), 'favorites': user.fav_user.all().count() } notifications_count = user.notify_user.filter(status=0).count() status_counter = { 'users': ForumUser.objects.all().count(), 'nodes': Node.objects.all().count(), 'topics': Topic.objects.all().count(), 'replies': Reply.objects.all().count(), } try: current_page = int(request.GET.get('p', '1')) except ValueError: current_page = 1 topics, topic_page = Topic.objects.get_all_topic(current_page=current_page) planes = Plane.objects.all().prefetch_related('node_set') # hot_nodes = Node.objects.get_all_hot_nodes() hot_nodes = Node.objects.all() active_page = 'topic' return render_to_response('topic/topics.html', locals(), context_instance=RequestContext(request)) def get_view(request, topic_id, errors=None): try: topic = Topic.objects.get_topic_by_topic_id(topic_id) except Topic.DoesNotExist: raise Http404 user = request.user if user.is_authenticated(): counter = { 'topics': user.topic_author.all().count(), 'replies': user.reply_author.all().count(), 'favorites': user.fav_user.all().count() } notifications_count = user.notify_user.filter(status=0).count() topic_favorited = Favorite.objects.filter(involved_topic=topic, owner_user=user).exists() reply_num = 106 reply_count = topic.reply_count reply_last_page = (reply_count // reply_num + (reply_count % reply_num and 1)) or 1 try: current_page = int(request.GET.get('p', reply_last_page)) except ValueError: current_page = reply_last_page replies, reply_page = Reply.objects.get_all_replies_by_topic_id(topic.id, current_page=current_page, num = reply_num) active_page = 'topic' floor = reply_num * (current_page - 1) topic.reply_count = reply_page.total topic.hits = (topic.hits or 0) + 1 topic.save() return render_to_response('topic/view.html', locals(), context_instance=RequestContext(request)) @login_required def post_view(request, topic_id): try: topic = Topic.objects.select_related('author').get(pk=topic_id) except Topic.DoesNotExist: raise Http404 form = ReplyForm(request.POST) if not form.is_valid(): return get_view(request, topic_id, errors=form.errors) user = request.user try: last_reply = topic.reply_set.all().order_by('-created')[0] except IndexError: last_reply = None if last_reply: last_replied_fingerprint = hashlib.sha1(str(topic.id) + str(last_reply.author_id) + last_reply.content).hexdigest() new_replied_fingerprint = hashlib.sha1(str(topic.id) + str(user.id) + form.cleaned_data.get('content')).hexdigest() if last_replied_fingerprint == new_replied_fingerprint: errors = {'duplicated_reply': [u'回复重复提交']} return get_view(request, topic.id, errors=errors) now = timezone.now() reply = Reply( topic = topic, author = user, content = form.cleaned_data.get('content'), created = now, ) reply.save() Topic.objects.filter(pk=topic.id).update(last_replied_by=user, last_replied_time=now, last_touched=now) notifications = [] if user.id != topic.author.id: notification = Notification( content = form.cleaned_data.get('content'), status = 0, involved_type = 1, # 0: mention, 1: reply involved_user = topic.author, involved_topic = topic, trigger_user = user, occurrence_time = now, ) notifications.append(notification) mentions = find_mentions(form.cleaned_data.get('content')) if user.username in mentions: mentions.remove(user.username) if topic.author.username in mentions: mentions.remove(topic.author.username) if mentions: mention_users = ForumUser.objects.filter(username__in=mentions) if mention_users: for mention_user in mention_users: notification = Notification( content = form.cleaned_data.get('content'), status = 0, involved_type = 0, # 0: mention, 1: reply involved_user = mention_user, involved_topic = topic, trigger_user = user, occurrence_time = now, ) notifications.append(notification) if notifications: Notification.objects.bulk_create(notifications) if user.id != topic.author.id: topic_time_diff = timezone.now() - topic.created reputation = topic.author.reputation or 0 reputation = reputation + 2 * math.log(user.reputation or 0 + topic_time_diff.days + 10, 10) ForumUser.objects.filter(pk=topic.author.id).update(reputation=reputation) return get_view(request, topic_id, errors=form.errors) @login_required def get_create(request, slug=None, errors=None): node = get_object_or_404(Node, slug=slug) user = request.user counter = { 'topics': user.topic_author.all().count(), 'replies': user.reply_author.all().count(), 'favorites': user.fav_user.all().count() } notifications_count = user.notify_user.filter(status=0).count() node_slug = node.slug active_page = 'topic' return render_to_response('topic/create.html', locals(), context_instance=RequestContext(request)) @login_required def post_create(request, slug=None): node = get_object_or_404(Node, slug=slug) form = CreateForm(request.POST) if not form.is_valid(): return get_create(request, slug=slug, errors=form.errors) user = request.user try: last_created = user.topic_author.all().order_by('-created')[0] except IndexError: last_created = None if last_created: # 如果用户最后一篇的标题内容与提交的相同 last_created_fingerprint = hashlib.sha1(last_created.title + \ last_created.content + str(last_created.node_id)).hexdigest() new_created_fingerprint = hashlib.sha1(form.cleaned_data.get('title') + \ form.cleaned_data.get('content') + str(node.id)).hexdigest() if last_created_fingerprint == new_created_fingerprint: errors = {'duplicated_topic': [u'帖子重复提交']} return get_create(request, slug=slug, errors=errors) now = timezone.now() topic = Topic( title = form.cleaned_data.get('title'), content = form.cleaned_data.get('content'), created = now, node = node, author = user, reply_count = 0, last_touched = now, ) topic.save() reputation = user.reputation or 0 reputation = reputation - 5 # 每次发布话题扣除用户威望5点 reputation = 0 if reputation < 0 else reputation ForumUser.objects.filter(pk=user.id).update(reputation=reputation) return redirect('/') @login_required def get_edit(request, topic_id, errors=None): topic = get_object_or_404(Topic, pk=topic_id) user = request.user counter = { 'topics': user.topic_author.all().count(), 'replies': user.reply_author.all().count(), 'favorites': user.fav_user.all().count() } notifications_count = user.notify_user.filter(status=0).count() active_page = 'topic' return render_to_response('topic/edit.html', locals(), context_instance=RequestContext(request)) @login_required def post_edit(request, topic_id): topic = get_object_or_404(Topic, pk=topic_id) form = CreateForm(request.POST) if not form.is_valid(): return get_edit(request, topic_id, errors=form.errors) user = request.user if topic.author_id != user.id: errors = {'invalid_permission': [u'没有权限修改该主题']} return get_edit(request, topic_id, errors=errors) now = timezone.now() Topic.objects.filter(pk=topic.id).update(updated=now, last_touched=now, **form.cleaned_data) reputation = user.reputation or 0 reputation = reputation - 2 # 每次修改回复扣除用户威望2点 reputation = 0 if reputation < 0 else reputation ForumUser.objects.filter(pk=user.id).update(reputation=reputation) return redirect('/t/%s/' % topic.id) @login_required def get_reply_edit(request, reply_id, errors=None): reply = get_object_or_404(Reply, pk=reply_id) user = request.user counter = { 'topics': user.topic_author.all().count(), 'replies': user.reply_author.all().count(), 'favorites': user.fav_user.all().count() } notifications_count = user.notify_user.filter(status=0).count() active_page = 'topic' return render_to_response('topic/reply_edit.html', locals(), context_instance=RequestContext(request)) @login_required def post_reply_edit(request, reply_id): reply = get_object_or_404(Reply, pk=reply_id) form = ReplyForm(request.POST) if not form.is_valid(): return get_reply_edit(request, reply_id, errors=form.errors) user = request.user if reply.author_id != user.id: errors = {'invalid_permission': [u'没有权限修改该回复']} return get_reply_edit(request, reply_id, errors=errors) Reply.objects.filter(pk=reply.id).update(updated=timezone.now(), **form.cleaned_data) reputation = user.reputation or 0 reputation = reputation - 2 # 每次修改回复扣除用户威望2点 reputation = 0 if reputation < 0 else reputation ForumUser.objects.filter(pk=user.id).update(reputation=reputation) return redirect('/t/%s/' % reply.topic_id) def get_node_topics(request, slug): node = get_object_or_404(Node, slug=slug) user = request.user if user.is_authenticated(): counter = { 'topics': user.topic_author.all().count(), 'replies': user.reply_author.all().count(), 'favorites': user.fav_user.all().count() } notifications_count = user.notify_user.filter(status=0).count() try: current_page = int(request.GET.get('p', '1')) except ValueError: current_page = 1 topics, topic_page = Topic.objects.get_all_topics_by_node_slug(node_slug=slug, current_page=current_page) active_page = 'topic' return render_to_response('topic/node_topics.html', locals(), context_instance=RequestContext(request)) def get_user_topics(request, uid): try: if uid.isdigit(): user_info = ForumUser.objects.get(pk=uid) else: user_info = ForumUser.objects.get(username=uid) except ForumUser.DoesNotExist: raise Http404 try: current_page = int(request.GET.get('p', '1')) except ValueError: current_page = 1 counter = { 'topics': user_info.topic_author.all().count(), 'replies': user_info.reply_author.all().count(), 'favorites': user_info.fav_user.all().count() } user = request.user if user.is_authenticated(): notifications_count = user.notify_user.filter(status=0).count() topics, topic_page = Topic.objects.get_user_all_topics(user_info.id, current_page=current_page) active_page = 'topic' return render_to_response('topic/user_topics.html', locals(), context_instance=RequestContext(request)) def get_user_replies(request, uid): try: if uid.isdigit(): user_info = ForumUser.objects.get(pk=uid) else: user_info = ForumUser.objects.get(username=uid) except ForumUser.DoesNotExist: raise Http404 try: current_page = int(request.GET.get('p', '1')) except ValueError: current_page = 1 counter = { 'topics': user_info.topic_author.all().count(), 'replies': user_info.reply_author.all().count(), 'favorites': user_info.fav_user.all().count() } user = request.user if user.is_authenticated(): notifications_count = user.notify_user.filter(status=0).count() replies, reply_page = Reply.objects.get_user_all_replies(user_info.id, current_page=current_page) active_page = 'topic' return render_to_response('topic/user_replies.html', locals(), context_instance=RequestContext(request)) def get_user_favorites(request, uid): try: if uid.isdigit(): user_info = ForumUser.objects.get(pk=uid) else: user_info = ForumUser.objects.get(username=uid) except ForumUser.DoesNotExist: raise Http404 try: current_page = int(request.GET.get('p', '1')) except ValueError: current_page = 1 counter = { 'topics': user_info.topic_author.all().count(), 'replies': user_info.reply_author.all().count(), 'favorites': user_info.fav_user.all().count() } user = request.user if user.is_authenticated(): notifications_count = user.notify_user.filter(status=0).count() favorites, favorite_page = Favorite.objects.get_user_all_favorites(user_info.id, current_page=current_page) active_page = 'topic' return render_to_response('topic/user_favorites.html', locals(), context_instance=RequestContext(request)) def get_profile(request, uid): try: if uid.isdigit(): user_info = ForumUser.objects.get(pk=uid) else: user_info = ForumUser.objects.get(username=uid) except ForumUser.DoesNotExist: raise Http404 try: current_page = int(request.GET.get('p', '1')) except ValueError: current_page = 1 counter = { 'topics': user_info.topic_author.all().count(), 'replies': user_info.reply_author.all().count(), 'favorites': user_info.fav_user.all().count() } user = request.user if user.is_authenticated(): notifications_count = user.notify_user.filter(status=0).count() topics, topic_page = Topic.objects.get_user_all_topics(user_info.id, current_page=current_page) replies, reply_page = Reply.objects.get_user_all_replies(user_info.id, current_page=current_page) active_page = '_blank' return render_to_response('topic/profile.html', locals(), context_instance=RequestContext(request)) def get_vote(request): user = request.user if not user.is_authenticated(): return HttpResponse(json.dumps({ 'success': 0, 'message': 'user_not_login' }), content_type='application/json') try: topic_id = int(request.GET.get('topic_id')) except (TypeError, ValueError): topic_id = None topic = None if topic_id: try: topic = Topic.objects.select_related('author').get(pk=topic_id) except Topic.DoesNotExist: pass if not (topic_id and topic): return HttpResponse(json.dumps({ 'success': 0, 'message': 'topic_not_exist' }), content_type='application/json') if user.id == topic.author.id: return HttpResponse(json.dumps({ 'success': 0, 'message': 'can_not_vote_your_topic' }), content_type='application/json') if Vote.objects.filter(trigger_user=user, involved_topic=topic).exists(): return HttpResponse(json.dumps({ 'success': 0, 'message': 'already_voted' }), content_type='application/json') vote = Vote(trigger_user=user, involved_type=0, involved_topic=topic, \ involved_user=topic.author, status=0, occurrence_time=timezone.now()) vote.save() # 更新话题作者声誉 topic_time_diff = timezone.now() - topic.created reputation = topic.author.reputation or 0 reputation = reputation + 2 * math.log((user.reputation or 0) + topic_time_diff.days + 10, 10) ForumUser.objects.filter(pk=topic.author.id).update(reputation=reputation) return HttpResponse(json.dumps({ 'success': 1, 'message': 'thanks_for_your_vote' }), content_type='application/json') def get_favorite(request): user = request.user if not user.is_authenticated(): return HttpResponse(json.dumps({ 'success': 0, 'message': 'user_not_login' }), content_type='application/json') try: topic_id = int(request.GET.get('topic_id')) except (TypeError, ValueError): topic_id = None topic = None if topic_id: try: topic = Topic.objects.select_related('author').get(pk=topic_id) except Topic.DoesNotExist: pass if not (topic_id and topic): return HttpResponse(json.dumps({ 'success': 0, 'message': 'topic_not_exist' }), content_type='application/json') if user.id == topic.author.id: return HttpResponse(json.dumps({ 'success': 0, 'message': 'can_not_favorite_your_topic' }), content_type='application/json') if Favorite.objects.filter(owner_user=user, involved_topic=topic).exists(): return HttpResponse(json.dumps({ 'success': 0, 'message': 'already_favorited' }), content_type='application/json') favorite = Favorite(owner_user=user, involved_type=0, involved_topic=topic, created=timezone.now()) favorite.save() # 更新话题作者声誉 topic_time_diff = timezone.now() - topic.created reputation = topic.author.reputation or 0 reputation = reputation + 2 * math.log((user.reputation or 0) + topic_time_diff.days + 10, 10) ForumUser.objects.filter(pk=topic.author.id).update(reputation=reputation) return HttpResponse(json.dumps({ 'success': 1, 'message': 'cancel_favorite_success' }), content_type='application/json') def get_cancel_favorite(request): user = request.user if not user.is_authenticated(): return HttpResponse(json.dumps({ 'success': 0, 'message': 'user_not_login' }), content_type='application/json') try: topic_id = int(request.GET.get('topic_id')) except (TypeError, ValueError): topic_id = None topic = None if topic_id: try: topic = Topic.objects.select_related('author').get(pk=topic_id) except Topic.DoesNotExist: pass if not (topic_id and topic): return HttpResponse(json.dumps({ 'success': 0, 'message': 'topic_not_exist' }), content_type='application/json') try: favorite = Favorite.objects.get(owner_user=user, involved_topic=topic) except Favorite.DoesNotExist: favorite = None if not favorite: return HttpResponse(json.dumps({ 'success': 0, 'message': 'not_been_favorited' }), content_type='application/json') favorite.delete() # 更新话题作者声誉 topic_time_diff = timezone.now() - topic.created reputation = topic.author.reputation or 0 reputation = reputation - math.log(user.reputation or 0 + topic_time_diff.days + 10, 15) ForumUser.objects.filter(pk=topic.author.id).update(reputation=reputation) return HttpResponse(json.dumps({ 'success': 1, 'message': 'cancel_favorite_success' }), content_type='application/json') def get_members(request): user = request.user if user.is_authenticated(): counter = { 'topics': user.topic_author.all().count(), 'replies': user.reply_author.all().count(), 'favorites': user.fav_user.all().count() } notifications_count = user.notify_user.filter(status=0).count() members = ForumUser.objects.all().order_by('-id')[:49] active_members = ForumUser.objects.all().order_by('-last_login')[:49] active_page = 'members' return render_to_response('topic/members.html', locals(), context_instance=RequestContext(request))