summaryrefslogtreecommitdiffstats
path: root/forum/views.py
diff options
context:
space:
mode:
Diffstat (limited to 'forum/views.py')
-rw-r--r--forum/views.py1204
1 files changed, 737 insertions, 467 deletions
diff --git a/forum/views.py b/forum/views.py
index 6c79bfbd..65b80d0e 100644
--- a/forum/views.py
+++ b/forum/views.py
@@ -2,20 +2,23 @@
import calendar
from django.conf import settings
from django.contrib.auth.decorators import login_required
-from django.contrib.contenttypes.models import ContentType
-from django.core.files.storage import default_storage
-from django.core.paginator import EmptyPage
-from django.core.paginator import InvalidPage
-from django.core.paginator import Paginator
-from django.http import Http404
-from django.http import HttpResponse
-from django.http import HttpResponseRedirect
-from django.shortcuts import get_object_or_404
-from django.shortcuts import render_to_response
-from django.template import RequestContext
-from django.utils import simplejson
+from django.http import HttpResponseRedirect, HttpResponse, HttpResponseForbidden, Http404
+from django.core.paginator import Paginator, EmptyPage, InvalidPage
+from django.template import RequestContext, loader
from django.utils.html import *
+from django.utils import simplejson
+from django.core import serializers
+from django.core.mail import mail_admins
+from django.db import transaction
+from django.db.models import Count, Q
+from django.contrib.contenttypes.models import ContentType
from django.utils.translation import ugettext as _
+from django.utils.datastructures import SortedDict
+from django.template.defaultfilters import slugify
+from django.core.exceptions import PermissionDenied
+
+from utils.html import sanitize_html
+from utils.decorators import ajax_method, ajax_login_required
from markdown2 import Markdown
import os.path
import random
@@ -29,7 +32,8 @@ from forum.diff import textDiff as htmldiff
from forum.forms import *
from forum.models import *
from forum.user import *
-from utils.html import sanitize_html
+from forum import auth
+from django_authopenid.util import get_next_url
# used in index page
INDEX_PAGE_SIZE = 20
@@ -65,42 +69,85 @@ def _get_tags_cache_json():
tags = simplejson.dumps(tags_list)
return tags
+def _get_and_remember_questions_sort_method(request, view_dic, default):
+ if default not in view_dic:
+ raise Exception('default value must be in view_dic')
+
+ q_sort_method = request.REQUEST.get('sort', None)
+ if q_sort_method == None:
+ q_sort_method = request.session.get('questions_sort_method', default)
+
+ if q_sort_method not in view_dic:
+ q_sort_method = default
+ request.session['questions_sort_method'] = q_sort_method
+ return q_sort_method, view_dic[q_sort_method]
+
def index(request):
- view_id = request.GET.get('sort', None)
view_dic = {
- "latest":"-last_activity_at",
- "hottest":"-answer_count",
- "mostvoted":"-score",
- "trans": "-last_activity_at"
- }
- try:
- orderby = view_dic[view_id]
- except KeyError:
- view_id = "latest"
- orderby = "-added_at"
- # group questions by author_id of 28,29
- if view_id == 'trans':
- questions = Question.objects.get_translation_questions(orderby, INDEX_PAGE_SIZE)
- else:
- questions = Question.objects.get_questions_by_pagesize(orderby, INDEX_PAGE_SIZE)
+ "latest":"-last_activity_at",
+ "hottest":"-answer_count",
+ "mostvoted":"-score",
+ }
+ view_id, orderby = _get_and_remember_questions_sort_method(request, view_dic, 'latest')
+
+ page_size = request.session.get('pagesize', QUESTIONS_PAGE_SIZE)
+ questions = Question.objects.exclude(deleted=True).order_by(orderby)[:page_size]
# RISK - inner join queries
questions = questions.select_related()
tags = Tag.objects.get_valid_tags(INDEX_TAGS_SIZE)
awards = Award.objects.get_recent_awards()
+ (interesting_tag_names, ignored_tag_names) = (None, None)
+ if request.user.is_authenticated():
+ pt = MarkedTag.objects.filter(user=request.user)
+ interesting_tag_names = pt.filter(reason='good').values_list('tag__name', flat=True)
+ ignored_tag_names = pt.filter(reason='bad').values_list('tag__name', flat=True)
+
+ tags_autocomplete = _get_tags_cache_json()
+
return render_to_response('index.html', {
- "questions": questions,
- "tab_id": view_id,
- "tags": tags,
- "awards": awards[:INDEX_AWARD_SIZE],
- }, context_instance=RequestContext(request))
+ 'interesting_tag_names': interesting_tag_names,
+ 'tags_autocomplete': tags_autocomplete,
+ 'ignored_tag_names': ignored_tag_names,
+ "questions" : questions,
+ "tab_id" : view_id,
+ "tags" : tags,
+ "awards" : awards[:INDEX_AWARD_SIZE],
+ }, context_instance=RequestContext(request))
def about(request):
return render_to_response('about.html', context_instance=RequestContext(request))
def faq(request):
- return render_to_response('faq.html', context_instance=RequestContext(request))
+ data = {
+ 'gravatar_faq_url': reverse('faq') + '#gravatar',
+ 'send_email_key_url': reverse('send_email_key'),
+ 'ask_question_url': reverse('ask'),
+ }
+ return render_to_response('faq.html', data, context_instance=RequestContext(request))
+
+def feedback(request):
+ data = {}
+ form = None
+ if request.method == "POST":
+ form = FeedbackForm(request.POST)
+ if form.is_valid():
+ if not request.user.is_authenticated:
+ data['email'] = form.cleaned_data.get('email',None)
+ data['message'] = form.cleaned_data['message']
+ data['name'] = form.cleaned_data.get('name',None)
+ message = render_to_response('feedback_email.txt',data,context_instance=RequestContext(request))
+ mail_admins(_('Q&A forum feedback'), message)
+ msg = _('Thanks for the feedback!')
+ request.user.message_set.create(message=msg)
+ return HttpResponseRedirect(get_next_url(request))
+ else:
+ form = FeedbackForm(initial={'next':get_next_url(request)})
+
+ data['form'] = form
+ return render_to_response('feedback.html', data, context_instance=RequestContext(request))
+feedback.CANCEL_MESSAGE=_('We look forward to hearing your feedback! Please, give it next time :)')
def privacy(request):
return render_to_response('privacy.html', context_instance=RequestContext(request))
@@ -113,7 +160,7 @@ def questions(request, tagname=None, unanswered=False):
List of Questions, Tagged questions, and Unanswered questions.
"""
# template file
- # "questions.html" or "unanswered.html"
+ # "questions.html" or maybe index.html in the future
template_file = "questions.html"
# get pagesize from session, if failed then get default value
pagesize = request.session.get("pagesize", 10)
@@ -122,27 +169,65 @@ def questions(request, tagname=None, unanswered=False):
except ValueError:
page = 1
- view_id = request.GET.get('sort', None)
- view_dic = {"latest":"-added_at", "active":"-last_activity_at", "hottest":"-answer_count", "mostvoted":"-score"}
- try:
- orderby = view_dic[view_id]
- except KeyError:
- view_id = "latest"
- orderby = "-added_at"
+ view_dic = {"latest":"-added_at", "active":"-last_activity_at", "hottest":"-answer_count", "mostvoted":"-score" }
+ view_id, orderby = _get_and_remember_questions_sort_method(request,view_dic,'latest')
# check if request is from tagged questions
+ qs = Question.objects.exclude(deleted=True)
+
if tagname is not None:
- objects = Question.objects.get_questions_by_tag(tagname, orderby)
- elif unanswered:
- #check if request is from unanswered questions
- template_file = "unanswered.html"
- objects = Question.objects.get_unanswered_questions(orderby)
- else:
- objects = Question.objects.get_questions(orderby)
+ qs = qs.filter(tags__name = unquote(tagname))
- # RISK - inner join queries
- objects = objects.select_related(depth=1);
- objects_list = Paginator(objects, pagesize)
+ if unanswered:
+ qs = qs.exclude(answer_accepted=True)
+
+ author_name = None
+ #user contributed questions & answers
+ if 'user' in request.GET:
+ try:
+ author_name = request.GET['user']
+ u = User.objects.get(username=author_name)
+ qs = qs.filter(Q(author=u) | Q(answers__author=u))
+ except User.DoesNotExist:
+ author_name = None
+
+ if request.user.is_authenticated():
+ uid_str = str(request.user.id)
+ qs = qs.extra(
+ select = SortedDict([
+ (
+ 'interesting_score',
+ 'SELECT COUNT(1) FROM forum_markedtag, question_tags '
+ + 'WHERE forum_markedtag.user_id = %s '
+ + 'AND forum_markedtag.tag_id = question_tags.tag_id '
+ + 'AND forum_markedtag.reason = "good" '
+ + 'AND question_tags.question_id = question.id'
+ ),
+ ]),
+ select_params = (uid_str,),
+ )
+ if request.user.hide_ignored_questions:
+ ignored_tags = Tag.objects.filter(user_selections__reason='bad',
+ user_selections__user = request.user)
+ qs = qs.exclude(tags__in=ignored_tags)
+ else:
+ qs = qs.extra(
+ select = SortedDict([
+ (
+ 'ignored_score',
+ 'SELECT COUNT(1) FROM forum_markedtag, question_tags '
+ + 'WHERE forum_markedtag.user_id = %s '
+ + 'AND forum_markedtag.tag_id = question_tags.tag_id '
+ + 'AND forum_markedtag.reason = "bad" '
+ + 'AND question_tags.question_id = question.id'
+ )
+ ]),
+ select_params = (uid_str, )
+ )
+
+ qs = qs.select_related(depth=1).order_by(orderby)
+
+ objects_list = Paginator(qs, pagesize)
questions = objects_list.page(page)
# Get related tags from this page objects
@@ -150,28 +235,41 @@ def questions(request, tagname=None, unanswered=False):
related_tags = Tag.objects.get_tags_by_questions(questions.object_list)
else:
related_tags = None
- return render_to_response(template_file, {
- "questions": questions,
- "tab_id": view_id,
- "questions_count": objects_list.count,
- "tags": related_tags,
- "searchtag": tagname,
- "is_unanswered": unanswered,
- "context": {
- 'is_paginated': True,
- 'pages': objects_list.num_pages,
- 'page': page,
- 'has_previous': questions.has_previous(),
- 'has_next': questions.has_next(),
- 'previous': questions.previous_page_number(),
- 'next': questions.next_page_number(),
- 'base_url': request.path + '?sort=%s&' % view_id,
- 'pagesize': pagesize
- }}, context_instance=RequestContext(request))
+ tags_autocomplete = _get_tags_cache_json()
+
+ # get the list of interesting and ignored tags
+ (interesting_tag_names, ignored_tag_names) = (None, None)
+ if request.user.is_authenticated():
+ pt = MarkedTag.objects.filter(user=request.user)
+ interesting_tag_names = pt.filter(reason='good').values_list('tag__name', flat=True)
+ ignored_tag_names = pt.filter(reason='bad').values_list('tag__name', flat=True)
-def create_new_answer(question=None, author=None, \
- added_at=None, wiki=False, \
- text='', email_notify=False):
+ return render_to_response(template_file, {
+ "questions" : questions,
+ "author_name" : author_name,
+ "tab_id" : view_id,
+ "questions_count" : objects_list.count,
+ "tags" : related_tags,
+ "tags_autocomplete" : tags_autocomplete,
+ "searchtag" : tagname,
+ "is_unanswered" : unanswered,
+ "interesting_tag_names": interesting_tag_names,
+ 'ignored_tag_names': ignored_tag_names,
+ "context" : {
+ 'is_paginated' : True,
+ 'pages': objects_list.num_pages,
+ 'page': page,
+ 'has_previous': questions.has_previous(),
+ 'has_next': questions.has_next(),
+ 'previous': questions.previous_page_number(),
+ 'next': questions.next_page_number(),
+ 'base_url' : request.path + '?sort=%s&' % view_id,
+ 'pagesize' : pagesize
+ }}, context_instance=RequestContext(request))
+
+def create_new_answer( question=None, author=None,\
+ added_at=None, wiki=False,\
+ text='', email_notify=False):
html = sanitize_html(markdowner.convert(text))
@@ -208,16 +306,12 @@ def create_new_answer(question=None, author=None, \
#set notification/delete
if email_notify:
- try:
- EmailFeed.objects.get(feed_id=question.id, subscriber_id=author.id, feed_content_type=question_type)
- except EmailFeed.DoesNotExist:
- feed = EmailFeed(content=question, subscriber=author)
- feed.save()
+ if author not in question.followed_by.all():
+ question.followed_by.add(author)
else:
#not sure if this is necessary. ajax should take care of this...
try:
- feed = Email.objects.get(feed_id=question.id, subscriber_id=author.id, feed_content_type=question_type)
- feed.delete()
+ question.followed_by.remove(author)
except:
pass
@@ -267,7 +361,7 @@ def ask(request):
if form.is_valid():
added_at = datetime.datetime.now()
- title = strip_tags(form.cleaned_data['title']).strip()
+ title = strip_tags(form.cleaned_data['title'].strip())
wiki = form.cleaned_data['wiki']
tagnames = form.cleaned_data['tags'].strip()
text = form.cleaned_data['text']
@@ -301,28 +395,42 @@ def ask(request):
ip_addr=request.META['REMOTE_ADDR'],
)
question.save()
- return HttpResponseRedirect('%s%s%s' % (_('/account/'), _('signin/'), ('newquestion/')))
+ return HttpResponseRedirect(reverse('user_signin_new_question'))
else:
form = AskForm()
tags = _get_tags_cache_json()
return render_to_response('ask.html', {
- 'form': form,
- 'tags': tags,
- }, context_instance=RequestContext(request))
+ 'form' : form,
+ 'tags' : tags,
+ 'email_validation_faq_url':reverse('faq') + '#validate',
+ }, context_instance=RequestContext(request))
def question(request, id):
try:
page = int(request.GET.get('page', '1'))
except ValueError:
page = 1
- view_id = request.GET.get('sort', 'votes')
- view_dic = {"latest":"-added_at", "oldest":"added_at", "votes":"-score"}
+
+ view_id = request.GET.get('sort', None)
+ view_dic = {"latest":"-added_at", "oldest":"added_at", "votes":"-score" }
try:
orderby = view_dic[view_id]
except KeyError:
- view_id = "votes"
- orderby = "-score"
+ qsm = request.session.get('questions_sort_method',None)
+ if qsm in ('mostvoted','latest'):
+ logging.debug('loaded from session ' + qsm)
+ if qsm == 'mostvoted':
+ view_id = 'votes'
+ orderby = '-score'
+ else:
+ view_id = 'latest'
+ orderby = '-added_at'
+ else:
+ view_id = "votes"
+ orderby = "-score"
+
+ logging.debug('view_id=' + str(view_id))
question = get_object_or_404(Question, id=id)
if question.deleted and not can_view_deleted_post(request.user, question):
@@ -345,8 +453,11 @@ def question(request, id):
vote_value = -1
if vote.is_upvote():
vote_value = 1
- user_answer_votes[vote.object_id] = vote_value
-
+ user_answer_votes[answer.id] = vote_value
+
+ if answers is not None:
+ answers = answers.order_by("-accepted", orderby)
+
filtered_answers = []
for answer in answers:
if answer.deleted == True:
@@ -357,8 +468,38 @@ def question(request, id):
objects_list = Paginator(filtered_answers, ANSWERS_PAGE_SIZE)
page_objects = objects_list.page(page)
- # update view count
- Question.objects.update_view_count(question)
+
+ #todo: merge view counts per user and per session
+ #1) view count per session
+ update_view_count = False
+ if 'question_view_times' not in request.session:
+ request.session['question_view_times'] = {}
+
+ last_seen = request.session['question_view_times'].get(question.id,None)
+ updated_when, updated_who = question.get_last_update_info()
+
+ if updated_who != request.user:
+ if last_seen:
+ if last_seen < updated_when:
+ update_view_count = True
+ else:
+ update_view_count = True
+
+ request.session['question_view_times'][question.id] = datetime.datetime.now()
+
+ if update_view_count:
+ question.view_count += 1
+ question.save()
+
+ #2) question view count per user
+ if request.user.is_authenticated():
+ try:
+ question_view = QuestionView.objects.get(who=request.user, question=question)
+ except QuestionView.DoesNotExist:
+ question_view = QuestionView(who=request.user, question=question)
+ question_view.when = datetime.datetime.now()
+ question_view.save()
+
return render_to_response('question.html', {
"question": question,
"question_vote": question_vote,
@@ -472,7 +613,6 @@ def _retag_question(request, question):
'tags': _get_tags_cache_json(),
}, context_instance=RequestContext(request))
-
def _edit_question(request, question):
latest_revision = question.get_latest_revision()
revision_form = None
@@ -617,6 +757,7 @@ QUESTION_REVISION_TEMPLATE = ('<h1>%(title)s</h1>\n'
def question_revisions(request, id):
post = get_object_or_404(Question, id=id)
revisions = list(post.revisions.all())
+ revisions.reverse()
for i, revision in enumerate(revisions):
revision.html = QUESTION_REVISION_TEMPLATE % {
'title': revision.title,
@@ -625,16 +766,15 @@ def question_revisions(request, id):
for tag in revision.tagnames.split(' ')]),
}
if i > 0:
- revisions[i - 1].diff = htmldiff(revision.html,
- revisions[i - 1].html)
+ revisions[i].diff = htmldiff(revisions[i-1].html, revision.html)
else:
- revisions[i - 1].diff = QUESTION_REVISION_TEMPLATE % {
+ revisions[i].diff = QUESTION_REVISION_TEMPLATE % {
'title': revisions[0].title,
'html': sanitize_html(markdowner.convert(revisions[0].text)),
'tags': ' '.join(['<a class="post-tag">%s</a>' % tag
for tag in revisions[0].tagnames.split(' ')]),
}
- revisions[i - 1].summary = None
+ revisions[i].summary = _('initial version')
return render_to_response('revisions_question.html', {
'post': post,
'revisions': revisions,
@@ -644,16 +784,16 @@ ANSWER_REVISION_TEMPLATE = ('<div class="text">%(html)s</div>')
def answer_revisions(request, id):
post = get_object_or_404(Answer, id=id)
revisions = list(post.revisions.all())
+ revisions.reverse()
for i, revision in enumerate(revisions):
revision.html = ANSWER_REVISION_TEMPLATE % {
'html': sanitize_html(markdowner.convert(revision.text))
}
if i > 0:
- revisions[i - 1].diff = htmldiff(revision.html,
- revisions[i - 1].html)
+ revisions[i].diff = htmldiff(revisions[i-1].html, revision.html)
else:
- revisions[i - 1].diff = revisions[i-1].text
- revisions[i - 1].summary = None
+ revisions[i].diff = revisions[i].text
+ revisions[i].summary = _('initial version')
return render_to_response('revisions_answer.html', {
'post': post,
'revisions': revisions,
@@ -691,8 +831,7 @@ def answer(request, id):
ip_addr=request.META['REMOTE_ADDR'],
)
anon.save()
- return HttpResponseRedirect('/%s%s%s%s' % ( _('account/'),
- _('signin/'),'?next=', question.get_absolute_url()))
+ return HttpResponseRedirect(reverse('user_signin_new_answer'))
return HttpResponseRedirect(question.get_absolute_url())
@@ -707,7 +846,7 @@ def tags(request):
if request.method == "GET":
stag = request.GET.get("q", "").strip()
- if len(stag) > 0:
+ if stag != '':
objects_list = Paginator(Tag.objects.filter(deleted=False).exclude(used_count=0).extra(where=['name like %s'], params=['%' + stag + '%']), DEFAULT_PAGE_SIZE)
else:
if sortby == "used":
@@ -721,22 +860,21 @@ def tags(request):
tags = objects_list.page(objects_list.num_pages)
return render_to_response('tags.html', {
- "tags": tags,
- "stag": stag,
- "tab_id": sortby,
- "keywords": stag,
- "context": {
- 'is_paginated': is_paginated,
- 'pages': objects_list.num_pages,
- 'page': page,
- 'has_previous': tags.has_previous(),
- 'has_next': tags.has_next(),
- 'previous': tags.previous_page_number(),
- 'next': tags.next_page_number(),
- 'base_url': '/tags/?sort=%s&' % sortby
- }
-
- }, context_instance=RequestContext(request))
+ "tags" : tags,
+ "stag" : stag,
+ "tab_id" : sortby,
+ "keywords" : stag,
+ "context" : {
+ 'is_paginated' : is_paginated,
+ 'pages': objects_list.num_pages,
+ 'page': page,
+ 'has_previous': tags.has_previous(),
+ 'has_next': tags.has_next(),
+ 'previous': tags.previous_page_number(),
+ 'next': tags.next_page_number(),
+ 'base_url' : reverse('tags') + '?sort=%s&' % sortby
+ }
+ }, context_instance=RequestContext(request))
def tag(request, tag):
return questions(request, tagname=tag)
@@ -925,7 +1063,8 @@ def vote(request, id):
if not can_delete_post(request.user, post):
response_data['allowed'] = -2
- elif post.deleted:
+ elif post.deleted == True:
+ logging.debug('debug restoring post in view')
onDeleteCanceled(post, request.user)
response_data['status'] = 1
else:
@@ -934,13 +1073,19 @@ def vote(request, id):
elif vote_type == '11':#subscribe q updates
user = request.user
if user.is_authenticated():
- try:
- EmailFeed.objects.get(feed_id=question.id, subscriber_id=user.id, feed_content_type=question_type)
- except EmailFeed.DoesNotExist:
- feed = EmailFeed(subscriber=user, content=question)
- feed.save()
+ if user not in question.followed_by.all():
+ question.followed_by.add(user)
if settings.EMAIL_VALIDATION == 'on' and user.email_isvalid == False:
- response_data['message'] = _('subscription saved, %(email)s needs validation') % {'email':user.email}
+ response_data['message'] = \
+ _('subscription saved, %(email)s needs validation, see %(details_url)s') \
+ % {'email':user.email,'details_url':reverse('faq') + '#validate'}
+ feed_setting = EmailFeedSetting.objects.get(subscriber=user,feed_type='q_sel')
+ if feed_setting.frequency == 'n':
+ feed_setting.frequency = 'd'
+ feed_setting.save()
+ if 'message' in response_data:
+ response_data['message'] += '<br/>'
+ response_data['message'] = _('email update frequency has been set to daily')
#response_data['status'] = 1
#responst_data['allowed'] = 1
else:
@@ -950,12 +1095,8 @@ def vote(request, id):
elif vote_type == '12':#unsubscribe q updates
user = request.user
if user.is_authenticated():
- try:
- feed = EmailFeed.objects.get(feed_id=question.id, subscriber_id=user.id)
- feed.delete()
- except EmailFeed.DoesNotExist:
- pass
-
+ if user in question.followed_by.all():
+ question.followed_by.remove(user)
else:
response_data['success'] = 0
response_data['message'] = u'Request mode is not supported. Please try again.'
@@ -967,6 +1108,42 @@ def vote(request, id):
data = simplejson.dumps(response_data)
return HttpResponse(data, mimetype="application/json")
+@ajax_login_required
+def mark_tag(request, tag=None, **kwargs):
+ action = kwargs['action']
+ ts = MarkedTag.objects.filter(user=request.user, tag__name=tag)
+ if action == 'remove':
+ logging.debug('deleting tag %s' % tag)
+ ts.delete()
+ else:
+ reason = kwargs['reason']
+ if len(ts) == 0:
+ try:
+ t = Tag.objects.get(name=tag)
+ mt = MarkedTag(user=request.user, reason=reason, tag=t)
+ mt.save()
+ except:
+ pass
+ else:
+ ts.update(reason=reason)
+ return HttpResponse(simplejson.dumps(''), mimetype="application/json")
+
+@ajax_login_required
+def ajax_toggle_ignored_questions(request):
+ if request.user.hide_ignored_questions:
+ new_hide_setting = False
+ else:
+ new_hide_setting = True
+ request.user.hide_ignored_questions = new_hide_setting
+ request.user.save()
+
+@ajax_method
+def ajax_command(request):
+ if 'command' not in request.POST:
+ return HttpResponseForbidden(mimetype="application/json")
+ if request.POST['command'] == 'toggle-ignored-questions':
+ return ajax_toggle_ignored_questions(request)
+
def users(request):
is_paginated = True
sortby = request.GET.get('sort', 'reputation')
@@ -986,11 +1163,11 @@ def users(request):
# default
else:
objects_list = Paginator(User.objects.all().order_by('-reputation'), USERS_PAGE_SIZE)
- base_url = '/%s?sort=%s&' % (_('users/'), sortby)
+ base_url = reverse('users') + '?sort=%s&' % sortby
else:
sortby = "reputation"
objects_list = Paginator(User.objects.extra(where=['username like %s'], params=['%' + suser + '%']).order_by('-reputation'), USERS_PAGE_SIZE)
- base_url = '/%s?name=%s&sort=%s&' % (_('users/'), suser, sortby)
+ base_url = reverse('users') + '?name=%s&sort=%s&' % (suser, sortby)
try:
users = objects_list.page(page)
@@ -998,22 +1175,22 @@ def users(request):
users = objects_list.page(objects_list.num_pages)
return render_to_response('users.html', {
- "users": users,
- "suser": suser,
- "keywords": suser,
- "tab_id": sortby,
- "context": {
- 'is_paginated': is_paginated,
- 'pages': objects_list.num_pages,
- 'page': page,
- 'has_previous': users.has_previous(),
- 'has_next': users.has_next(),
- 'previous': users.previous_page_number(),
- 'next': users.next_page_number(),
- 'base_url': base_url
- }
-
- }, context_instance=RequestContext(request))
+ "users" : users,
+ "suser" : suser,
+ "keywords" : suser,
+ "tab_id" : sortby,
+ "context" : {
+ 'is_paginated' : is_paginated,
+ 'pages': objects_list.num_pages,
+ 'page': page,
+ 'has_previous': users.has_previous(),
+ 'has_next': users.has_next(),
+ 'previous': users.previous_page_number(),
+ 'next': users.next_page_number(),
+ 'base_url' : base_url
+ }
+
+ }, context_instance=RequestContext(request))
def user(request, id):
sort = request.GET.get('sort', 'stats')
@@ -1023,6 +1200,26 @@ def user(request, id):
return func(request, id, user_view)
@login_required
+def moderate_user(request, id):
+ """ajax handler of user moderation
+ """
+ if not auth.can_moderate_users(request.user) or request.method != 'POST':
+ raise Http404
+ if not request.is_ajax():
+ return HttpResponseForbidden(mimetype="application/json")
+
+ user = get_object_or_404(User, id=id)
+ form = ModerateUserForm(request.POST, instance=user)
+
+ if form.is_valid():
+ form.save()
+ logging.debug('data saved')
+ response = HttpResponse(simplejson.dumps(''), mimetype="application/json")
+ else:
+ response = HttpResponseForbidden(mimetype="application/json")
+ return response
+
+@login_required
def edit_user(request, id):
user = get_object_or_404(User, id=id)
if request.user != user:
@@ -1035,6 +1232,7 @@ def edit_user(request, id):
from django_authopenid.views import set_new_email
set_new_email(user, new_email)
+ user.username = sanitize_html(form.cleaned_data['username'])
user.real_name = sanitize_html(form.cleaned_data['realname'])
user.website = sanitize_html(form.cleaned_data['website'])
user.location = sanitize_html(form.cleaned_data['city'])
@@ -1052,8 +1250,9 @@ def edit_user(request, id):
else:
form = EditUserForm(user)
return render_to_response('user_edit.html', {
- 'form': form,
- }, context_instance=RequestContext(request))
+ 'form' : form,
+ 'gravatar_faq_url' : reverse('faq') + '#gravatar',
+ }, context_instance=RequestContext(request))
def user_stats(request, user_id, user_view):
user = get_object_or_404(User, id=user_id)
@@ -1097,74 +1296,99 @@ def user_stats(request, user_id, user_view):
'la_user_reputation')[:100]
answered_questions = Question.objects.extra(
- select={
- 'vote_up_count': 'answer.vote_up_count',
- 'vote_down_count': 'answer.vote_down_count',
- 'answer_id': 'answer.id',
- 'accepted': 'answer.accepted',
- 'vote_count': 'answer.score',
- 'comment_count': 'answer.comment_count'
- },
- tables=['question', 'answer'],
- where=['answer.deleted=0 AND answer.author_id=%s AND answer.question_id=question.id'],
- params=[user_id],
- order_by=['-vote_count', '-answer_id'],
- select_params=[user_id]
- ).distinct().values('comment_count',
- 'id',
- 'answer_id',
- 'title',
- 'author_id',
- 'accepted',
- 'vote_count',
- 'answer_count',
- 'vote_up_count',
- 'vote_down_count')[:100]
+ select={
+ 'vote_up_count' : 'answer.vote_up_count',
+ 'vote_down_count' : 'answer.vote_down_count',
+ 'answer_id' : 'answer.id',
+ 'accepted' : 'answer.accepted',
+ 'vote_count' : 'answer.score',
+ 'comment_count' : 'answer.comment_count'
+ },
+ tables=['question', 'answer'],
+ where=['answer.deleted=0 AND question.deleted=0 AND answer.author_id=%s AND answer.question_id=question.id'],
+ params=[user_id],
+ order_by=['-vote_count', '-answer_id'],
+ select_params=[user_id]
+ ).distinct().values('comment_count',
+ 'id',
+ 'answer_id',
+ 'title',
+ 'author_id',
+ 'accepted',
+ 'vote_count',
+ 'answer_count',
+ 'vote_up_count',
+ 'vote_down_count')[:100]
+
up_votes = Vote.objects.get_up_vote_count_from_user(user)
down_votes = Vote.objects.get_down_vote_count_from_user(user)
votes_today = Vote.objects.get_votes_count_today_from_user(user)
votes_total = VOTE_RULES['scope_votes_per_user_per_day']
- tags = user.created_tags.all().order_by('-used_count')[:50]
+ question_id_set = set(map(lambda v: v['id'], list(questions))) \
+ | set(map(lambda v: v['id'], list(answered_questions)))
+
+ user_tags = Tag.objects.filter(questions__id__in = question_id_set)
try:
from django.db.models import Count
awards = Award.objects.extra(
- select={'id': 'badge.id', 'name':'badge.name', 'description': 'badge.description', 'type': 'badge.type'},
- tables=['award', 'badge'],
- order_by=['-awarded_at'],
- where=['user_id=%s AND badge_id=badge.id'],
- params=[user.id]
- ).values('id', 'name', 'description', 'type')
+ select={'id': 'badge.id',
+ 'name':'badge.name',
+ 'description': 'badge.description',
+ 'type': 'badge.type'},
+ tables=['award', 'badge'],
+ order_by=['-awarded_at'],
+ where=['user_id=%s AND badge_id=badge.id'],
+ params=[user.id]
+ ).values('id', 'name', 'description', 'type')
total_awards = awards.count()
- awards = awards.annotate(count=Count('badge__id'))
+ awards = awards.annotate(count = Count('badge__id'))
+ user_tags = user_tags.annotate(user_tag_usage_count=Count('name'))
+
except ImportError:
awards = Award.objects.extra(
- select={'id': 'badge.id', 'count': 'count(badge_id)', 'name':'badge.name', 'description': 'badge.description', 'type': 'badge.type'},
- tables=['award', 'badge'],
- order_by=['-awarded_at'],
- where=['user_id=%s AND badge_id=badge.id'],
- params=[user.id]
- ).values('id', 'count', 'name', 'description', 'type')
+ select={'id': 'badge.id',
+ 'count': 'count(badge_id)',
+ 'name':'badge.name',
+ 'description': 'badge.description',
+ 'type': 'badge.type'},
+ tables=['award', 'badge'],
+ order_by=['-awarded_at'],
+ where=['user_id=%s AND badge_id=badge.id'],
+ params=[user.id]
+ ).values('id', 'count', 'name', 'description', 'type')
total_awards = awards.count()
awards.query.group_by = ['badge_id']
+ user_tags = user_tags.extra(
+ select={'user_tag_usage_count': 'COUNT(1)',},
+ order_by=['-user_tag_usage_count'],
+ )
+ user_tags.query.group_by = ['name']
- return render_to_response(user_view.template_file, {
- "tab_name": user_view.id,
- "tab_description": user_view.tab_description,
- "page_title": user_view.page_title,
- "view_user": user,
- "questions": questions,
- "answered_questions": answered_questions,
- "up_votes": up_votes,
- "down_votes": down_votes,
- "total_votes": up_votes + down_votes,
- "votes_today_left": votes_total-votes_today,
- "votes_total_per_day": votes_total,
- "tags": tags,
- "awards": awards,
- "total_awards": total_awards,
- }, context_instance=RequestContext(request))
+ if auth.can_moderate_users(request.user):
+ moderate_user_form = ModerateUserForm(instance=user)
+ else:
+ moderate_user_form = None
+
+ return render_to_response(user_view.template_file,{
+ 'moderate_user_form': moderate_user_form,
+ "tab_name" : user_view.id,
+ "tab_description" : user_view.tab_description,
+ "page_title" : user_view.page_title,
+ "view_user" : user,
+ "questions" : questions,
+ "answered_questions" : answered_questions,
+ "up_votes" : up_votes,
+ "down_votes" : down_votes,
+ "total_votes": up_votes + down_votes,
+ "votes_today_left": votes_total-votes_today,
+ "votes_total_per_day": votes_total,
+ "user_tags" : user_tags[:50],
+ "tags" : tags,
+ "awards": awards,
+ "total_awards" : total_awards,
+ }, context_instance=RequestContext(request))
def user_recent(request, user_id, user_view):
user = get_object_or_404(User, id=user_id)
@@ -1180,8 +1404,10 @@ def user_recent(request, user_id, user_view):
self.type_id = type
self.title = title
self.summary = summary
- self.title_link = u'/questions/%s/%s#%s' % (question_id, title, answer_id)\
- if int(answer_id) > 0 else u'/questions/%s/%s' % (question_id, title)
+ slug_title = slugify(title)
+ self.title_link = reverse('question', kwargs={'id':question_id}) + u'%s' % slug_title
+ if int(answer_id) > 0:
+ self.title_link += '#%s' % answer_id
class AwardEvent:
def __init__(self, time, type, id):
@@ -1193,23 +1419,23 @@ def user_recent(request, user_id, user_view):
activities = []
# ask questions
questions = Activity.objects.extra(
- select={
- 'title': 'question.title',
- 'question_id': 'question.id',
- 'active_at': 'activity.active_at',
- 'activity_type': 'activity.activity_type'
- },
- tables=['activity', 'question'],
- where=['activity.content_type_id = %s AND activity.object_id = ' +
- 'question.id AND activity.user_id = %s AND activity.activity_type = %s'],
- params=[question_type_id, user_id, TYPE_ACTIVITY_ASK_QUESTION],
- order_by=['-activity.active_at']
- ).values(
- 'title',
- 'question_id',
- 'active_at',
- 'activity_type'
- )
+ select={
+ 'title' : 'question.title',
+ 'question_id' : 'question.id',
+ 'active_at' : 'activity.active_at',
+ 'activity_type' : 'activity.activity_type'
+ },
+ tables=['activity', 'question'],
+ where=['activity.content_type_id = %s AND activity.object_id = ' +
+ 'question.id AND question.deleted=0 AND activity.user_id = %s AND activity.activity_type = %s'],
+ params=[question_type_id, user_id, TYPE_ACTIVITY_ASK_QUESTION],
+ order_by=['-activity.active_at']
+ ).values(
+ 'title',
+ 'question_id',
+ 'active_at',
+ 'activity_type'
+ )
if len(questions) > 0:
questions = [(Event(q['active_at'], q['activity_type'], q['title'], '', '0', \
q['question_id'])) for q in questions]
@@ -1217,25 +1443,26 @@ def user_recent(request, user_id, user_view):
# answers
answers = Activity.objects.extra(
- select={
- 'title': 'question.title',
- 'question_id': 'question.id',
- 'answer_id': 'answer.id',
- 'active_at': 'activity.active_at',
- 'activity_type': 'activity.activity_type'
- },
- tables=['activity', 'answer', 'question'],
- where=['activity.content_type_id = %s AND activity.object_id = answer.id AND ' +
- 'answer.question_id=question.id AND activity.user_id=%s AND activity.activity_type=%s'],
- params=[answer_type_id, user_id, TYPE_ACTIVITY_ANSWER],
- order_by=['-activity.active_at']
- ).values(
- 'title',
- 'question_id',
- 'answer_id',
- 'active_at',
- 'activity_type'
- )
+ select={
+ 'title' : 'question.title',
+ 'question_id' : 'question.id',
+ 'answer_id' : 'answer.id',
+ 'active_at' : 'activity.active_at',
+ 'activity_type' : 'activity.activity_type'
+ },
+ tables=['activity', 'answer', 'question'],
+ where=['activity.content_type_id = %s AND activity.object_id = answer.id AND ' +
+ 'answer.question_id=question.id AND answer.deleted=0 AND activity.user_id=%s AND '+
+ 'activity.activity_type=%s AND question.deleted=0'],
+ params=[answer_type_id, user_id, TYPE_ACTIVITY_ANSWER],
+ order_by=['-activity.active_at']
+ ).values(
+ 'title',
+ 'question_id',
+ 'answer_id',
+ 'active_at',
+ 'activity_type'
+ )
if len(answers) > 0:
answers = [(Event(q['active_at'], q['activity_type'], q['title'], '', q['answer_id'], \
q['question_id'])) for q in answers]
@@ -1243,25 +1470,26 @@ def user_recent(request, user_id, user_view):
# question comments
comments = Activity.objects.extra(
- select={
- 'title': 'question.title',
- 'question_id': 'comment.object_id',
- 'added_at': 'comment.added_at',
- 'activity_type': 'activity.activity_type'
- },
- tables=['activity', 'question', 'comment'],
-
- where=['activity.content_type_id = %s AND activity.object_id = comment.id AND ' +
- 'activity.user_id = comment.user_id AND comment.object_id=question.id AND ' +
- 'comment.content_type_id=%s AND activity.user_id = %s AND activity.activity_type=%s'],
- params=[comment_type_id, question_type_id, user_id, TYPE_ACTIVITY_COMMENT_QUESTION],
- order_by=['-comment.added_at']
- ).values(
- 'title',
- 'question_id',
- 'added_at',
- 'activity_type'
- )
+ select={
+ 'title' : 'question.title',
+ 'question_id' : 'comment.object_id',
+ 'added_at' : 'comment.added_at',
+ 'activity_type' : 'activity.activity_type'
+ },
+ tables=['activity', 'question', 'comment'],
+
+ where=['activity.content_type_id = %s AND activity.object_id = comment.id AND '+
+ 'activity.user_id = comment.user_id AND comment.object_id=question.id AND '+
+ 'comment.content_type_id=%s AND activity.user_id = %s AND activity.activity_type=%s AND ' +
+ 'question.deleted=0'],
+ params=[comment_type_id, question_type_id, user_id, TYPE_ACTIVITY_COMMENT_QUESTION],
+ order_by=['-comment.added_at']
+ ).values(
+ 'title',
+ 'question_id',
+ 'added_at',
+ 'activity_type'
+ )
if len(comments) > 0:
comments = [(Event(q['added_at'], q['activity_type'], q['title'], '', '0', \
@@ -1270,28 +1498,29 @@ def user_recent(request, user_id, user_view):
# answer comments
comments = Activity.objects.extra(
- select={
- 'title': 'question.title',
- 'question_id': 'question.id',
- 'answer_id': 'answer.id',
- 'added_at': 'comment.added_at',
- 'activity_type': 'activity.activity_type'
- },
- tables=['activity', 'question', 'answer', 'comment'],
-
- where=['activity.content_type_id = %s AND activity.object_id = comment.id AND ' +
- 'activity.user_id = comment.user_id AND comment.object_id=answer.id AND ' +
- 'comment.content_type_id=%s AND question.id = answer.question_id AND ' +
- 'activity.user_id = %s AND activity.activity_type=%s'],
- params=[comment_type_id, answer_type_id, user_id, TYPE_ACTIVITY_COMMENT_ANSWER],
- order_by=['-comment.added_at']
- ).values(
- 'title',
- 'question_id',
- 'answer_id',
- 'added_at',
- 'activity_type'
- )
+ select={
+ 'title' : 'question.title',
+ 'question_id' : 'question.id',
+ 'answer_id' : 'answer.id',
+ 'added_at' : 'comment.added_at',
+ 'activity_type' : 'activity.activity_type'
+ },
+ tables=['activity', 'question', 'answer', 'comment'],
+
+ where=['activity.content_type_id = %s AND activity.object_id = comment.id AND '+
+ 'activity.user_id = comment.user_id AND comment.object_id=answer.id AND '+
+ 'comment.content_type_id=%s AND question.id = answer.question_id AND '+
+ 'activity.user_id = %s AND activity.activity_type=%s AND '+
+ 'answer.deleted=0 AND question.deleted=0'],
+ params=[comment_type_id, answer_type_id, user_id, TYPE_ACTIVITY_COMMENT_ANSWER],
+ order_by=['-comment.added_at']
+ ).values(
+ 'title',
+ 'question_id',
+ 'answer_id',
+ 'added_at',
+ 'activity_type'
+ )
if len(comments) > 0:
comments = [(Event(q['added_at'], q['activity_type'], q['title'], '', q['answer_id'], \
@@ -1300,26 +1529,27 @@ def user_recent(request, user_id, user_view):
# question revisions
revisions = Activity.objects.extra(
- select={
- 'title': 'question_revision.title',
- 'question_id': 'question_revision.question_id',
- 'added_at': 'activity.active_at',
- 'activity_type': 'activity.activity_type',
- 'summary': 'question_revision.summary'
- },
- tables=['activity', 'question_revision'],
- where=['activity.content_type_id = %s AND activity.object_id = question_revision.id AND ' +
- 'activity.user_id = question_revision.author_id AND activity.user_id = %s AND ' +
- 'activity.activity_type=%s'],
- params=[question_revision_type_id, user_id, TYPE_ACTIVITY_UPDATE_QUESTION],
- order_by=['-activity.active_at']
- ).values(
- 'title',
- 'question_id',
- 'added_at',
- 'activity_type',
- 'summary'
- )
+ select={
+ 'title' : 'question_revision.title',
+ 'question_id' : 'question_revision.question_id',
+ 'added_at' : 'activity.active_at',
+ 'activity_type' : 'activity.activity_type',
+ 'summary' : 'question_revision.summary'
+ },
+ tables=['activity', 'question_revision', 'question'],
+ where=['activity.content_type_id = %s AND activity.object_id = question_revision.id AND '+
+ 'question_revision.id=question.id AND question.deleted=0 AND '+
+ 'activity.user_id = question_revision.author_id AND activity.user_id = %s AND '+
+ 'activity.activity_type=%s'],
+ params=[question_revision_type_id, user_id, TYPE_ACTIVITY_UPDATE_QUESTION],
+ order_by=['-activity.active_at']
+ ).values(
+ 'title',
+ 'question_id',
+ 'added_at',
+ 'activity_type',
+ 'summary'
+ )
if len(revisions) > 0:
revisions = [(Event(q['added_at'], q['activity_type'], q['title'], q['summary'], '0', \
@@ -1328,30 +1558,31 @@ def user_recent(request, user_id, user_view):
# answer revisions
revisions = Activity.objects.extra(
- select={
- 'title': 'question.title',
- 'question_id': 'question.id',
- 'answer_id': 'answer.id',
- 'added_at': 'activity.active_at',
- 'activity_type': 'activity.activity_type',
- 'summary': 'answer_revision.summary'
- },
- tables=['activity', 'answer_revision', 'question', 'answer'],
-
- where=['activity.content_type_id = %s AND activity.object_id = answer_revision.id AND ' +
- 'activity.user_id = answer_revision.author_id AND activity.user_id = %s AND ' +
- 'answer_revision.answer_id=answer.id AND answer.question_id = question.id AND ' +
- 'activity.activity_type=%s'],
- params=[answer_revision_type_id, user_id, TYPE_ACTIVITY_UPDATE_ANSWER],
- order_by=['-activity.active_at']
- ).values(
- 'title',
- 'question_id',
- 'added_at',
- 'answer_id',
- 'activity_type',
- 'summary'
- )
+ select={
+ 'title' : 'question.title',
+ 'question_id' : 'question.id',
+ 'answer_id' : 'answer.id',
+ 'added_at' : 'activity.active_at',
+ 'activity_type' : 'activity.activity_type',
+ 'summary' : 'answer_revision.summary'
+ },
+ tables=['activity', 'answer_revision', 'question', 'answer'],
+
+ where=['activity.content_type_id = %s AND activity.object_id = answer_revision.id AND '+
+ 'activity.user_id = answer_revision.author_id AND activity.user_id = %s AND '+
+ 'answer_revision.answer_id=answer.id AND answer.question_id = question.id AND '+
+ 'question.deleted=0 AND answer.deleted=0 AND '+
+ 'activity.activity_type=%s'],
+ params=[answer_revision_type_id, user_id, TYPE_ACTIVITY_UPDATE_ANSWER],
+ order_by=['-activity.active_at']
+ ).values(
+ 'title',
+ 'question_id',
+ 'added_at',
+ 'answer_id',
+ 'activity_type',
+ 'summary'
+ )
if len(revisions) > 0:
revisions = [(Event(q['added_at'], q['activity_type'], q['title'], q['summary'], \
@@ -1360,24 +1591,25 @@ def user_recent(request, user_id, user_view):
# accepted answers
accept_answers = Activity.objects.extra(
- select={
- 'title': 'question.title',
- 'question_id': 'question.id',
- 'added_at': 'activity.active_at',
- 'activity_type': 'activity.activity_type',
- },
- tables=['activity', 'answer', 'question'],
- where=['activity.content_type_id = %s AND activity.object_id = answer.id AND ' +
- 'activity.user_id = question.author_id AND activity.user_id = %s AND ' +
- 'answer.question_id=question.id AND activity.activity_type=%s'],
- params=[answer_type_id, user_id, TYPE_ACTIVITY_MARK_ANSWER],
- order_by=['-activity.active_at']
- ).values(
- 'title',
- 'question_id',
- 'added_at',
- 'activity_type',
- )
+ select={
+ 'title' : 'question.title',
+ 'question_id' : 'question.id',
+ 'added_at' : 'activity.active_at',
+ 'activity_type' : 'activity.activity_type',
+ },
+ tables=['activity', 'answer', 'question'],
+ where=['activity.content_type_id = %s AND activity.object_id = answer.id AND '+
+ 'activity.user_id = question.author_id AND activity.user_id = %s AND '+
+ 'answer.deleted=0 AND question.deleted=0 AND '+
+ 'answer.question_id=question.id AND activity.activity_type=%s'],
+ params=[answer_type_id, user_id, TYPE_ACTIVITY_MARK_ANSWER],
+ order_by=['-activity.active_at']
+ ).values(
+ 'title',
+ 'question_id',
+ 'added_at',
+ 'activity_type',
+ )
if len(accept_answers) > 0:
accept_answers = [(Event(q['added_at'], q['activity_type'], q['title'], '', '0', \
q['question_id'])) for q in accept_answers]
@@ -1405,13 +1637,13 @@ def user_recent(request, user_id, user_view):
activities.sort(lambda x, y: cmp(y.time, x.time))
- return render_to_response(user_view.template_file, {
- "tab_name": user_view.id,
- "tab_description": user_view.tab_description,
- "page_title": user_view.page_title,
- "view_user": user,
- "activities": activities[:user_view.data_size]
- }, context_instance=RequestContext(request))
+ return render_to_response(user_view.template_file,{
+ "tab_name" : user_view.id,
+ "tab_description" : user_view.tab_description,
+ "page_title" : user_view.page_title,
+ "view_user" : user,
+ "activities" : activities[:user_view.data_size]
+ }, context_instance=RequestContext(request))
def user_responses(request, user_id, user_view):
"""
@@ -1421,9 +1653,9 @@ def user_responses(request, user_id, user_view):
def __init__(self, type, title, question_id, answer_id, time, username, user_id, content):
self.type = type
self.title = title
- self.titlelink = u'/%s%s/%s#%s' % (_('questions/'), question_id, slugify(title), answer_id)
+ self.titlelink = reverse('question', args=[question_id]) + u'%s#%s' % (slugify(title), answer_id)
self.time = time
- self.userlink = u'/%s%s/%s/' % (_('users/'), user_id, username)
+ self.userlink = reverse('users') + u'%s/%s/' % (user_id, username)
self.username = username
self.content = u'%s ...' % strip_tags(content)[:300]
@@ -1433,30 +1665,31 @@ def user_responses(request, user_id, user_view):
user = get_object_or_404(User, id=user_id)
responses = []
answers = Answer.objects.extra(
- select={
- 'title': 'question.title',
- 'question_id': 'question.id',
- 'answer_id': 'answer.id',
- 'added_at': 'answer.added_at',
- 'html': 'answer.html',
- 'username': 'auth_user.username',
- 'user_id': 'auth_user.id'
- },
- select_params=[user_id],
- tables=['answer', 'question', 'auth_user'],
- where=['answer.question_id = question.id AND answer.deleted=0 AND question.deleted = 0 AND ' +
- 'question.author_id = %s AND answer.author_id <> %s AND answer.author_id=auth_user.id'],
- params=[user_id, user_id],
- order_by=['-answer.id']
- ).values(
- 'title',
- 'question_id',
- 'answer_id',
- 'added_at',
- 'html',
- 'username',
- 'user_id'
- )
+ select={
+ 'title' : 'question.title',
+ 'question_id' : 'question.id',
+ 'answer_id' : 'answer.id',
+ 'added_at' : 'answer.added_at',
+ 'html' : 'answer.html',
+ 'username' : 'auth_user.username',
+ 'user_id' : 'auth_user.id'
+ },
+ select_params=[user_id],
+ tables=['answer', 'question', 'auth_user'],
+ where=['answer.question_id = question.id AND answer.deleted=0 AND question.deleted = 0 AND '+
+ 'question.author_id = %s AND answer.author_id <> %s AND answer.author_id=auth_user.id'],
+ params=[user_id, user_id],
+ order_by=['-answer.id']
+ ).values(
+ 'title',
+ 'question_id',
+ 'answer_id',
+ 'added_at',
+ 'html',
+ 'username',
+ 'user_id'
+ )
+
if len(answers) > 0:
answers = [(Response(TYPE_RESPONSE['QUESTION_ANSWERED'], a['title'], a['question_id'],
a['answer_id'], a['added_at'], a['username'], a['user_id'], a['html'])) for a in answers]
@@ -1465,27 +1698,27 @@ def user_responses(request, user_id, user_view):
# question comments
comments = Comment.objects.extra(
- select={
- 'title': 'question.title',
- 'question_id': 'comment.object_id',
- 'added_at': 'comment.added_at',
- 'comment': 'comment.comment',
- 'username': 'auth_user.username',
- 'user_id': 'auth_user.id'
- },
- tables=['question', 'auth_user', 'comment'],
- where=['question.deleted = 0 AND question.author_id = %s AND comment.object_id=question.id AND ' +
- 'comment.content_type_id=%s AND comment.user_id <> %s AND comment.user_id = auth_user.id'],
- params=[user_id, question_type_id, user_id],
- order_by=['-comment.added_at']
- ).values(
- 'title',
- 'question_id',
- 'added_at',
- 'comment',
- 'username',
- 'user_id'
- )
+ select={
+ 'title' : 'question.title',
+ 'question_id' : 'comment.object_id',
+ 'added_at' : 'comment.added_at',
+ 'comment' : 'comment.comment',
+ 'username' : 'auth_user.username',
+ 'user_id' : 'auth_user.id'
+ },
+ tables=['question', 'auth_user', 'comment'],
+ where=['question.deleted = 0 AND question.author_id = %s AND comment.object_id=question.id AND '+
+ 'comment.content_type_id=%s AND comment.user_id <> %s AND comment.user_id = auth_user.id'],
+ params=[user_id, question_type_id, user_id],
+ order_by=['-comment.added_at']
+ ).values(
+ 'title',
+ 'question_id',
+ 'added_at',
+ 'comment',
+ 'username',
+ 'user_id'
+ )
if len(comments) > 0:
comments = [(Response(TYPE_RESPONSE['QUESTION_COMMENTED'], c['title'], c['question_id'],
@@ -1719,88 +1952,117 @@ def user_favorites(request, user_id, user_view):
"view_user": user
}, context_instance=RequestContext(request))
-
-def user_preferences(request, user_id, user_view):
+def user_email_subscriptions(request, user_id, user_view):
user = get_object_or_404(User, id=user_id)
- return render_to_response(user_view.template_file, {
- "tab_name": user_view.id,
- "tab_description": user_view.tab_description,
- "page_title": user_view.page_title,
- "view_user": user,
- }, context_instance=RequestContext(request))
+ if request.method == 'POST':
+ email_feeds_form = EditUserEmailFeedsForm(request.POST)
+ tag_filter_form = TagFilterSelectionForm(request.POST, instance=user)
+ if email_feeds_form.is_valid() and tag_filter_form.is_valid():
+
+ action_status = None
+ tag_filter_saved = tag_filter_form.save()
+ if tag_filter_saved:
+ action_status = _('changes saved')
+ if 'save' in request.POST:
+ feeds_saved = email_feeds_form.save(user)
+ if feeds_saved:
+ action_status = _('changes saved')
+ elif 'stop_email' in request.POST:
+ email_stopped = email_feeds_form.reset().save(user)
+ initial_values = EditUserEmailFeedsForm.NO_EMAIL_INITIAL
+ email_feeds_form = EditUserEmailFeedsForm(initial=initial_values)
+ if email_stopped:
+ action_status = _('email updates canceled')
+ else:
+ email_feeds_form = EditUserEmailFeedsForm()
+ email_feeds_form.set_initial_values(user)
+ tag_filter_form = TagFilterSelectionForm(instance=user)
+ action_status = None
+ return render_to_response(user_view.template_file,{
+ 'tab_name':user_view.id,
+ 'tab_description':user_view.tab_description,
+ 'page_title':user_view.page_title,
+ 'view_user':user,
+ 'email_feeds_form':email_feeds_form,
+ 'tag_filter_selection_form':tag_filter_form,
+ 'action_status':action_status,
+ }, context_instance=RequestContext(request))
def question_comments(request, id):
question = get_object_or_404(Question, id=id)
user = request.user
- return __comments(request, question, 'question', user)
+ return __comments(request, question, 'question')
def answer_comments(request, id):
answer = get_object_or_404(Answer, id=id)
user = request.user
- return __comments(request, answer, 'answer', user)
+ return __comments(request, answer, 'answer')
-def __comments(request, obj, type, user):
+def __comments(request, obj, type):
# only support get comments by ajax now
+ user = request.user
if request.is_ajax():
if request.method == "GET":
- return __generate_comments_json(obj, type, user)
+ response = __generate_comments_json(obj, type, user)
elif request.method == "POST":
- comment_data = request.POST.get('comment')
- comment = Comment(content_object=obj, comment=comment_data, user=request.user)
- comment.save()
- obj.comment_count = obj.comment_count + 1
- obj.save()
- return __generate_comments_json(obj, type, user)
+ if auth.can_add_comments(user,obj):
+ comment_data = request.POST.get('comment')
+ comment = Comment(content_object=obj, comment=comment_data, user=request.user)
+ comment.save()
+ obj.comment_count = obj.comment_count + 1
+ obj.save()
+ response = __generate_comments_json(obj, type, user)
+ else:
+ response = HttpResponseForbidden(mimetype="application/json")
+ return response
def __generate_comments_json(obj, type, user):
- comments = obj.comments.all().order_by('-id')
+ comments = obj.comments.all().order_by('id')
# {"Id":6,"PostId":38589,"CreationDate":"an hour ago","Text":"hello there!","UserDisplayName":"Jarrod Dixon","UserUrl":"/users/3/jarrod-dixon","DeleteUrl":null}
json_comments = []
+ from forum.templatetags.extra_tags import diff_date
for comment in comments:
comment_user = comment.user
delete_url = ""
if user != None and auth.can_delete_comment(user, comment):
#/posts/392845/comments/219852/delete
- delete_url = "/" + type + "s/%s/comments/%s/delete/" % (obj.id, comment.id)
- json_comments.append({"id": comment.id,
- "object_id": obj.id,
- "add_date": comment.added_at.strftime('%Y-%m-%d'),
- "text": comment.comment,
- "user_display_name": comment_user.username,
- "user_url": "/users/%s/%s" % (comment_user.id, comment_user.username),
- "delete_url": delete_url
- })
+ #todo translate this url
+ delete_url = reverse(index) + type + "s/%s/comments/%s/delete/" % (obj.id, comment.id)
+ json_comments.append({"id" : comment.id,
+ "object_id" : obj.id,
+ "comment_age" : diff_date(comment.added_at),
+ "text" : comment.comment,
+ "user_display_name" : comment_user.username,
+ "user_url" : comment_user.get_profile_url(),
+ "delete_url" : delete_url
+ })
data = simplejson.dumps(json_comments)
return HttpResponse(data, mimetype="application/json")
-def delete_question_comment(request, question_id, comment_id):
- if request.is_ajax():
- question = get_object_or_404(Question, id=question_id)
- comment = get_object_or_404(Comment, id=comment_id)
-
- question.comments.remove(comment)
- question.comment_count = question.comment_count - 1
- question.save()
- user = request.user
- return __generate_comments_json(question, 'question', user)
+def delete_comment(request, object_id='', comment_id='', commented_object_type=None):
+ response = None
+ commented_object = None
+ if commented_object_type == 'question':
+ commented_object = Question
+ elif commented_object_type == 'answer':
+ commented_object = Answer
-def delete_answer_comment(request, answer_id, comment_id):
if request.is_ajax():
- answer = get_object_or_404(Answer, id=answer_id)
comment = get_object_or_404(Comment, id=comment_id)
-
- answer.comments.remove(comment)
- answer.comment_count = answer.comment_count - 1
- answer.save()
- user = request.user
- return __generate_comments_json(answer, 'answer', user)
+ if auth.can_delete_comment(request.user, comment):
+ obj = get_object_or_404(commented_object, id=object_id)
+ obj.comments.remove(comment)
+ obj.comment_count = obj.comment_count - 1
+ obj.save()
+ user = request.user
+ return __generate_comments_json(obj, commented_object_type, user)
+ raise PermissionDenied()
def logout(request):
- url = request.GET.get('next')
return render_to_response('logout.html', {
- 'next': url,
- }, context_instance=RequestContext(request))
+ 'next' : get_next_url(request),
+ }, context_instance=RequestContext(request))
def badges(request):
badges = Badge.objects.all().order_by('type')
@@ -1810,9 +2072,10 @@ def badges(request):
my_badges.query.group_by = ['badge_id']
return render_to_response('badges.html', {
- 'badges': badges,
- 'mybadges': my_badges,
- }, context_instance=RequestContext(request))
+ 'badges' : badges,
+ 'mybadges' : my_badges,
+ 'feedback_faq_url' : reverse('feedback'),
+ }, context_instance=RequestContext(request))
def badge(request, id):
badge = get_object_or_404(Badge, id=id)
@@ -1863,8 +2126,8 @@ def upload(request):
if not file_name_suffix in settings.ALLOW_FILE_TYPES:
raise FileTypeNotAllow
- # genetate new file name
- new_file_name = str(time.time()).replace('.', str(random.randint(0, 100000))) + file_name_suffix
+ # generate new file name
+ new_file_name = str(time.time()).replace('.', str(random.randint(0,100000))) + file_name_suffix
# use default storage to store file
default_storage.save(new_file_name, f)
# check file size
@@ -1887,7 +2150,7 @@ def upload(request):
return HttpResponse(result, mimetype="application/xml")
def books(request):
- return HttpResponseRedirect("/books/mysql-zhaoyang")
+ return HttpResponseRedirect(reverse('books') + '/mysql-zhaoyang')
def book(request, short_name, unanswered=False):
"""
@@ -2010,9 +2273,10 @@ def ask_book(request, short_name):
tags = _get_tags_cache_json()
return render_to_response('ask.html', {
- 'form': form,
- 'tags': tags,
- }, context_instance=RequestContext(request))
+ 'form' : form,
+ 'tags' : tags,
+ 'email_validation_faq_url': reverse('faq') + '#validate',
+ }, context_instance=RequestContext(request))
def search(request):
"""
@@ -2027,11 +2291,11 @@ def search(request):
except ValueError:
page = 1
if keywords is None:
- return HttpResponseRedirect('/')
+ return HttpResponseRedirect(reverse(index))
if search_type == 'tag':
- return HttpResponseRedirect('/%s?q=%s&page=%s' % (_('tags/'), keywords.strip(), page))
+ return HttpResponseRedirect(reverse('tags') + '?q=%s&page=%s' % (keywords.strip(), page))
elif search_type == "user":
- return HttpResponseRedirect('/%s?q=%s&page=%s' % (_('users/'), keywords.strip(), page))
+ return HttpResponseRedirect(reverse('users') + '?q=%s&page=%s' % (keywords.strip(), page))
elif search_type == "question":
template_file = "questions.html"
@@ -2070,10 +2334,16 @@ def search(request):
view_id = "latest"
orderby = "-added_at"
- objects = Question.objects.filter(deleted=False).extra(where=['title like %s'], params=['%' + keywords + '%']).order_by(orderby)
+ if settings.USE_SPHINX_SEARCH == True:
+ #search index is now free of delete questions and answers
+ #so there is not "antideleted" filtering here
+ objects = Question.search.query(keywords)
+ #no related selection either because we're relying on full text search here
+ else:
+ objects = Question.objects.filter(deleted=False).extra(where=['title like %s'], params=['%' + keywords + '%']).order_by(orderby)
+ # RISK - inner join queries
+ objects = objects.select_related();
- # RISK - inner join queries
- objects = objects.select_related();
objects_list = Paginator(objects, pagesize)
questions = objects_list.page(page)