]> git.openstreetmap.org Git - osqa.git/blob - forum/views/users.py
162ba2d214f8c484e3f5faca54de980dc7812e81
[osqa.git] / forum / views / users.py
1 from django.contrib.auth.decorators import login_required\r
2 from forum.models import User\r
3 from django.core.paginator import Paginator, EmptyPage, InvalidPage\r
4 from django.template.defaultfilters import slugify\r
5 from django.contrib.contenttypes.models import ContentType\r
6 from django.core.urlresolvers import reverse\r
7 from django.shortcuts import render_to_response, get_object_or_404\r
8 from django.template import RequestContext\r
9 from django.http import HttpResponse, HttpResponseForbidden, HttpResponseRedirect, Http404\r
10 from django.utils.translation import ugettext as _\r
11 from django.utils.http import urlquote_plus\r
12 from django.utils.html import strip_tags\r
13 from django.utils import simplejson\r
14 from django.core.urlresolvers import reverse\r
15 from forum.forms import *\r
16 from forum.utils.html import sanitize_html\r
17 from forum.authentication import user_updated \r
18 import time\r
19 from django.contrib.contenttypes.models import ContentType\r
20 \r
21 question_type = ContentType.objects.get_for_model(Question)\r
22 answer_type = ContentType.objects.get_for_model(Answer)\r
23 comment_type = ContentType.objects.get_for_model(Comment)\r
24 question_revision_type = ContentType.objects.get_for_model(QuestionRevision)\r
25 answer_revision_type = ContentType.objects.get_for_model(AnswerRevision)\r
26 repute_type = ContentType.objects.get_for_model(Repute)\r
27 question_type_id = question_type.id\r
28 answer_type_id = answer_type.id\r
29 comment_type_id = comment_type.id\r
30 question_revision_type_id = question_revision_type.id\r
31 answer_revision_type_id = answer_revision_type.id\r
32 repute_type_id = repute_type.id\r
33 \r
34 USERS_PAGE_SIZE = 35# refactor - move to some constants file\r
35 \r
36 def users(request):\r
37     is_paginated = True\r
38     sortby = request.GET.get('sort', 'reputation')\r
39     suser = request.REQUEST.get('q',  "")\r
40     try:\r
41         page = int(request.GET.get('page', '1'))\r
42     except ValueError:\r
43         page = 1\r
44 \r
45     if suser == "":\r
46         if sortby == "newest":\r
47             objects_list = Paginator(User.objects.all().order_by('-date_joined'), USERS_PAGE_SIZE)\r
48         elif sortby == "last":\r
49             objects_list = Paginator(User.objects.all().order_by('date_joined'), USERS_PAGE_SIZE)\r
50         elif sortby == "user":\r
51             objects_list = Paginator(User.objects.all().order_by('username'), USERS_PAGE_SIZE)\r
52         # default\r
53         else:\r
54             objects_list = Paginator(User.objects.all().order_by('-reputation'), USERS_PAGE_SIZE)\r
55         base_url = reverse('users') + '?sort=%s&' % sortby\r
56     else:\r
57         sortby = "reputation"\r
58         objects_list = Paginator(User.objects.filter(username__icontains=suser).order_by('-reputation'), USERS_PAGE_SIZE)\r
59         base_url = reverse('users') + '?name=%s&sort=%s&' % (suser, sortby)\r
60 \r
61     try:\r
62         users = objects_list.page(page)\r
63     except (EmptyPage, InvalidPage):\r
64         users = objects_list.page(objects_list.num_pages)\r
65 \r
66     return render_to_response('users.html', {\r
67                                 "users" : users,\r
68                                 "suser" : suser,\r
69                                 "keywords" : suser,\r
70                                 "tab_id" : sortby,\r
71                                 "context" : {\r
72                                     'is_paginated' : is_paginated,\r
73                                     'pages': objects_list.num_pages,\r
74                                     'page': page,\r
75                                     'has_previous': users.has_previous(),\r
76                                     'has_next': users.has_next(),\r
77                                     'previous': users.previous_page_number(),\r
78                                     'next': users.next_page_number(),\r
79                                     'base_url' : base_url\r
80                                 }\r
81 \r
82                                 }, context_instance=RequestContext(request))\r
83 \r
84 @login_required\r
85 def moderate_user(request, id):\r
86     """ajax handler of user moderation\r
87     """\r
88     if not request.user.is_superuser or request.method != 'POST':\r
89         raise Http404\r
90     if not request.is_ajax():\r
91         return HttpResponseForbidden(mimetype="application/json")\r
92 \r
93     user = get_object_or_404(User, id=id)\r
94     form = ModerateUserForm(request.POST, instance=user)\r
95 \r
96     if form.is_valid():\r
97         form.save()\r
98         logging.debug('data saved')\r
99         response = HttpResponse(simplejson.dumps(''), mimetype="application/json")\r
100     else:\r
101         response = HttpResponseForbidden(mimetype="application/json")\r
102     return response\r
103 \r
104 def set_new_email(user, new_email, nomessage=False):\r
105     if new_email != user.email:\r
106         user.email = new_email\r
107         user.email_isvalid = False\r
108         user.save()\r
109         #if settings.EMAIL_VALIDATION == 'on':\r
110         #    send_new_email_key(user,nomessage=nomessage)    \r
111 \r
112 @login_required\r
113 def edit_user(request, id):\r
114     user = get_object_or_404(User, id=id)\r
115     if request.user != user:\r
116         raise Http404\r
117     if request.method == "POST":\r
118         form = EditUserForm(user, request.POST)\r
119         if form.is_valid():\r
120             new_email = sanitize_html(form.cleaned_data['email'])\r
121 \r
122             set_new_email(user, new_email)\r
123 \r
124             #user.username = sanitize_html(form.cleaned_data['username'])\r
125             user.real_name = sanitize_html(form.cleaned_data['realname'])\r
126             user.website = sanitize_html(form.cleaned_data['website'])\r
127             user.location = sanitize_html(form.cleaned_data['city'])\r
128             user.date_of_birth = sanitize_html(form.cleaned_data['birthday'])\r
129             if len(user.date_of_birth) == 0:\r
130                 user.date_of_birth = '1900-01-01'\r
131             user.about = sanitize_html(form.cleaned_data['about'])\r
132 \r
133             user.save()\r
134             # send user updated singal if full fields have been updated\r
135             if user.email and user.real_name and user.website and user.location and \\r
136                 user.date_of_birth and user.about:\r
137                 user_updated.send(sender=user.__class__, instance=user, updated_by=user)\r
138             return HttpResponseRedirect(user.get_profile_url())\r
139     else:\r
140         form = EditUserForm(user)\r
141     return render_to_response('user_edit.html', {\r
142                                                 'form' : form,\r
143                                                 'gravatar_faq_url' : reverse('faq') + '#gravatar',\r
144                                     }, context_instance=RequestContext(request))\r
145 \r
146 def user_stats(request, user_id, user_view):\r
147     user = get_object_or_404(User, id=user_id)\r
148 \r
149     questions = Question.objects.filter(deleted=False, author=user).order_by('-added_at')\r
150 \r
151     answered_questions = Question.objects.filter(deleted=False, answers__author=user).distinct()\r
152 \r
153     """answered_questions = Question.objects.extra(\r
154         select={\r
155             'vote_up_count' : 'answer.vote_up_count',\r
156             'vote_down_count' : 'answer.vote_down_count',\r
157             'answer_id' : 'answer.id',\r
158             'accepted' : 'answer.accepted',\r
159             'vote_count' : 'answer.score',\r
160             'comment_count' : 'answer.comment_count'\r
161             },\r
162         tables=['question', 'answer'],\r
163         where=['NOT answer.deleted AND NOT question.deleted AND answer.author_id=%s AND answer.question_id=question.id'],\r
164         params=[user_id],\r
165         order_by=['-vote_count', '-answer_id'],\r
166         select_params=[user_id]\r
167     ).distinct().values('comment_count',\r
168                         'id',\r
169                         'answer_id',\r
170                         'title',\r
171                         'author_id',\r
172                         'accepted',\r
173                         'vote_count',\r
174                         'answer_count',\r
175                         'vote_up_count',\r
176                         'vote_down_count')[:100]"""\r
177 \r
178     up_votes = user.get_up_vote_count()\r
179     down_votes = user.get_down_vote_count()\r
180     votes_today = user.get_vote_count_today()\r
181     votes_total = int(settings.MAX_VOTES_PER_DAY)\r
182 \r
183     #question_id_set = set(map(lambda v: v['id'], list(questions))) \\r
184     #                    | set(map(lambda v: v['id'], list(answered_questions)))\r
185 \r
186     user_tags = Tag.objects.filter(questions__author=user)\r
187     try:\r
188         from django.db.models import Count\r
189         awards = Award.objects.extra(\r
190                                         select={'id': 'badge.id', \r
191                                                 'name':'badge.name', \r
192                                                 'description': 'badge.description', \r
193                                                 'type': 'badge.type'},\r
194                                         tables=['award', 'badge'],\r
195                                         order_by=['-awarded_at'],\r
196                                         where=['user_id=%s AND badge_id=badge.id'],\r
197                                         params=[user.id]\r
198                                     ).values('id', 'name', 'description', 'type')\r
199         total_awards = awards.count()\r
200         awards = awards.annotate(count = Count('badge__id'))\r
201         user_tags = user_tags.annotate(user_tag_usage_count=Count('name'))\r
202 \r
203     except ImportError:\r
204         awards = Award.objects.extra(\r
205                                         select={'id': 'badge.id', \r
206                                                 'count': 'count(badge_id)', \r
207                                                 'name':'badge.name', \r
208                                                 'description': 'badge.description', \r
209                                                 'type': 'badge.type'},\r
210                                         tables=['award', 'badge'],\r
211                                         order_by=['-awarded_at'],\r
212                                         where=['user_id=%s AND badge_id=badge.id'],\r
213                                         params=[user.id]\r
214                                     ).values('id', 'count', 'name', 'description', 'type')\r
215         total_awards = awards.count()\r
216         awards.query.group_by = ['badge_id']\r
217 \r
218         user_tags = user_tags.extra(\r
219             select={'user_tag_usage_count': 'COUNT(1)',},\r
220             order_by=['-user_tag_usage_count'],\r
221         )\r
222         user_tags.query.group_by = ['name']\r
223 \r
224     if request.user.is_superuser:\r
225         moderate_user_form = ModerateUserForm(instance=user)\r
226     else:\r
227         moderate_user_form = None\r
228 \r
229     return render_to_response(user_view.template_file,{\r
230                                 'moderate_user_form': moderate_user_form,\r
231                                 "tab_name" : user_view.id,\r
232                                 "tab_description" : user_view.tab_description,\r
233                                 "page_title" : user_view.page_title,\r
234                                 "view_user" : user,\r
235                                 "questions" : questions,\r
236                                 "answered_questions" : answered_questions,\r
237                                 "up_votes" : up_votes,\r
238                                 "down_votes" : down_votes,\r
239                                 "total_votes": up_votes + down_votes,\r
240                                 "votes_today_left": votes_total-votes_today,\r
241                                 "votes_total_per_day": votes_total,\r
242                                 "user_tags" : user_tags[:50],\r
243                                 "awards": awards,\r
244                                 "total_awards" : total_awards,\r
245                             }, context_instance=RequestContext(request))\r
246 \r
247 def user_recent(request, user_id, user_view):\r
248     user = get_object_or_404(User, id=user_id)\r
249     def get_type_name(type_id):\r
250         for item in TYPE_ACTIVITY:\r
251             if type_id in item:\r
252                 return item[1]\r
253 \r
254     class Event:\r
255         def __init__(self, time, type, title, summary, answer_id, question_id):\r
256             self.time = time\r
257             self.type = get_type_name(type)\r
258             self.type_id = type\r
259             self.title = title\r
260             self.summary = summary\r
261             slug_title = slugify(title)\r
262             self.title_link = reverse('question', kwargs={'id':question_id, 'slug':slug_title})\r
263             if int(answer_id) > 0:\r
264                 self.title_link += '#%s' % answer_id\r
265 \r
266     class AwardEvent:\r
267         def __init__(self, time, type, id):\r
268             self.time = time\r
269             self.type = get_type_name(type)\r
270             self.type_id = type\r
271             self.badge = get_object_or_404(Badge, id=id)\r
272 \r
273     activities = []\r
274     # ask questions\r
275     questions = Activity.objects.extra(\r
276         select={\r
277             'title' : 'question.title',\r
278             'question_id' : 'question.id',\r
279             'active_at' : 'activity.active_at',\r
280             'activity_type' : 'activity.activity_type'\r
281             },\r
282         tables=['activity', 'question'],\r
283         where=['activity.content_type_id = %s AND activity.object_id = ' +\r
284             'question.id AND NOT question.deleted AND activity.user_id = %s AND activity.activity_type = %s'],\r
285         params=[question_type_id, user_id, TYPE_ACTIVITY_ASK_QUESTION],\r
286         order_by=['-activity.active_at']\r
287     ).values(\r
288             'title',\r
289             'question_id',\r
290             'active_at',\r
291             'activity_type'\r
292             )\r
293     if len(questions) > 0:\r
294         questions = [(Event(q['active_at'], q['activity_type'], q['title'], '', '0', \\r
295                       q['question_id'])) for q in questions]\r
296         activities.extend(questions)\r
297 \r
298     # answers\r
299     answers = Activity.objects.extra(\r
300         select={\r
301             'title' : 'question.title',\r
302             'question_id' : 'question.id',\r
303             'answer_id' : 'answer.id',\r
304             'active_at' : 'activity.active_at',\r
305             'activity_type' : 'activity.activity_type'\r
306             },\r
307         tables=['activity', 'answer', 'question'],\r
308         where=['activity.content_type_id = %s AND activity.object_id = answer.id AND ' + \r
309             'answer.question_id=question.id AND NOT answer.deleted AND activity.user_id=%s AND '+\r
310             'activity.activity_type=%s AND NOT question.deleted'],\r
311         params=[answer_type_id, user_id, TYPE_ACTIVITY_ANSWER],\r
312         order_by=['-activity.active_at']\r
313     ).values(\r
314             'title',\r
315             'question_id',\r
316             'answer_id',\r
317             'active_at',\r
318             'activity_type'\r
319             )\r
320     if len(answers) > 0:\r
321         answers = [(Event(q['active_at'], q['activity_type'], q['title'], '', q['answer_id'], \\r
322                     q['question_id'])) for q in answers]\r
323         activities.extend(answers)\r
324 \r
325     # question comments\r
326     comments = Activity.objects.extra(\r
327         select={\r
328             'title' : 'question.title',\r
329             'question_id' : 'comment.object_id',\r
330             'added_at' : 'comment.added_at',\r
331             'activity_type' : 'activity.activity_type'\r
332             },\r
333         tables=['activity', 'question', 'comment'],\r
334 \r
335         where=['activity.content_type_id = %s AND activity.object_id = comment.id AND '+\r
336             'activity.user_id = comment.user_id AND comment.object_id=question.id AND '+\r
337             'comment.content_type_id=%s AND activity.user_id = %s AND activity.activity_type=%s AND ' +\r
338             'NOT question.deleted'],\r
339         params=[comment_type_id, question_type_id, user_id, TYPE_ACTIVITY_COMMENT_QUESTION],\r
340         order_by=['-comment.added_at']\r
341     ).values(\r
342             'title',\r
343             'question_id',\r
344             'added_at',\r
345             'activity_type'\r
346             )\r
347 \r
348     if len(comments) > 0:\r
349         comments = [(Event(q['added_at'], q['activity_type'], q['title'], '', '0', \\r
350                      q['question_id'])) for q in comments]\r
351         activities.extend(comments)\r
352 \r
353     # answer comments\r
354     comments = Activity.objects.extra(\r
355         select={\r
356             'title' : 'question.title',\r
357             'question_id' : 'question.id',\r
358             'answer_id' : 'answer.id',\r
359             'added_at' : 'comment.added_at',\r
360             'activity_type' : 'activity.activity_type'\r
361             },\r
362         tables=['activity', 'question', 'answer', 'comment'],\r
363 \r
364         where=['activity.content_type_id = %s AND activity.object_id = comment.id AND '+\r
365             'activity.user_id = comment.user_id AND comment.object_id=answer.id AND '+\r
366             'comment.content_type_id=%s AND question.id = answer.question_id AND '+\r
367             'activity.user_id = %s AND activity.activity_type=%s AND '+\r
368             'NOT answer.deleted AND NOT question.deleted'],\r
369         params=[comment_type_id, answer_type_id, user_id, TYPE_ACTIVITY_COMMENT_ANSWER],\r
370         order_by=['-comment.added_at']\r
371     ).values(\r
372             'title',\r
373             'question_id',\r
374             'answer_id',\r
375             'added_at',\r
376             'activity_type'\r
377             )\r
378 \r
379     if len(comments) > 0:\r
380         comments = [(Event(q['added_at'], q['activity_type'], q['title'], '', q['answer_id'], \\r
381                      q['question_id'])) for q in comments]\r
382         activities.extend(comments)\r
383 \r
384     # question revisions\r
385     revisions = Activity.objects.extra(\r
386         select={\r
387             'title' : 'question_revision.title',\r
388             'question_id' : 'question_revision.question_id',\r
389             'added_at' : 'activity.active_at',\r
390             'activity_type' : 'activity.activity_type',\r
391             'summary' : 'question_revision.summary'\r
392             },\r
393         tables=['activity', 'question_revision', 'question'],\r
394         where=['activity.content_type_id = %s AND activity.object_id = question_revision.id AND '+\r
395             'question_revision.id=question.id AND NOT question.deleted AND '+\r
396             'activity.user_id = question_revision.author_id AND activity.user_id = %s AND '+\r
397             'activity.activity_type=%s'],\r
398         params=[question_revision_type_id, user_id, TYPE_ACTIVITY_UPDATE_QUESTION],\r
399         order_by=['-activity.active_at']\r
400     ).values(\r
401             'title',\r
402             'question_id',\r
403             'added_at',\r
404             'activity_type',\r
405             'summary'\r
406             )\r
407 \r
408     if len(revisions) > 0:\r
409         revisions = [(Event(q['added_at'], q['activity_type'], q['title'], q['summary'], '0', \\r
410                       q['question_id'])) for q in revisions]\r
411         activities.extend(revisions)\r
412 \r
413     # answer revisions\r
414     revisions = Activity.objects.extra(\r
415         select={\r
416             'title' : 'question.title',\r
417             'question_id' : 'question.id',\r
418             'answer_id' : 'answer.id',\r
419             'added_at' : 'activity.active_at',\r
420             'activity_type' : 'activity.activity_type',\r
421             'summary' : 'answer_revision.summary'\r
422             },\r
423         tables=['activity', 'answer_revision', 'question', 'answer'],\r
424 \r
425         where=['activity.content_type_id = %s AND activity.object_id = answer_revision.id AND '+\r
426             'activity.user_id = answer_revision.author_id AND activity.user_id = %s AND '+\r
427             'answer_revision.answer_id=answer.id AND answer.question_id = question.id AND '+\r
428             'NOT question.deleted AND NOT answer.deleted AND '+\r
429             'activity.activity_type=%s'],\r
430         params=[answer_revision_type_id, user_id, TYPE_ACTIVITY_UPDATE_ANSWER],\r
431         order_by=['-activity.active_at']\r
432     ).values(\r
433             'title',\r
434             'question_id',\r
435             'added_at',\r
436             'answer_id',\r
437             'activity_type',\r
438             'summary'\r
439             )\r
440 \r
441     if len(revisions) > 0:\r
442         revisions = [(Event(q['added_at'], q['activity_type'], q['title'], q['summary'], \\r
443                       q['answer_id'], q['question_id'])) for q in revisions]\r
444         activities.extend(revisions)\r
445 \r
446     # accepted answers\r
447     accept_answers = Activity.objects.extra(\r
448         select={\r
449             'title' : 'question.title',\r
450             'question_id' : 'question.id',\r
451             'added_at' : 'activity.active_at',\r
452             'activity_type' : 'activity.activity_type',\r
453             },\r
454         tables=['activity', 'answer', 'question'],\r
455         where=['activity.content_type_id = %s AND activity.object_id = answer.id AND '+\r
456             'activity.user_id = question.author_id AND activity.user_id = %s AND '+\r
457             'NOT answer.deleted AND NOT question.deleted AND '+\r
458             'answer.question_id=question.id AND activity.activity_type=%s'],\r
459         params=[answer_type_id, user_id, TYPE_ACTIVITY_MARK_ANSWER],\r
460         order_by=['-activity.active_at']\r
461     ).values(\r
462             'title',\r
463             'question_id',\r
464             'added_at',\r
465             'activity_type',\r
466             )\r
467     if len(accept_answers) > 0:\r
468         accept_answers = [(Event(q['added_at'], q['activity_type'], q['title'], '', '0', \\r
469             q['question_id'])) for q in accept_answers]\r
470         activities.extend(accept_answers)\r
471     #award history\r
472     awards = Activity.objects.extra(\r
473         select={\r
474             'badge_id' : 'badge.id',\r
475             'awarded_at': 'award.awarded_at',\r
476             'activity_type' : 'activity.activity_type'\r
477             },\r
478         tables=['activity', 'award', 'badge'],\r
479         where=['activity.user_id = award.user_id AND activity.user_id = %s AND '+\r
480             'award.badge_id=badge.id AND activity.object_id=award.id AND activity.activity_type=%s'],\r
481         params=[user_id, TYPE_ACTIVITY_PRIZE],\r
482         order_by=['-activity.active_at']\r
483     ).values(\r
484             'badge_id',\r
485             'awarded_at',\r
486             'activity_type'\r
487             )\r
488     if len(awards) > 0:\r
489         awards = [(AwardEvent(q['awarded_at'], q['activity_type'], q['badge_id'])) for q in awards]\r
490         activities.extend(awards)\r
491 \r
492     activities.sort(lambda x,y: cmp(y.time, x.time))\r
493 \r
494     return render_to_response(user_view.template_file,{\r
495                                     "tab_name" : user_view.id,\r
496                                     "tab_description" : user_view.tab_description,\r
497                                     "page_title" : user_view.page_title,\r
498                                     "view_user" : user,\r
499                                     "activities" : activities[:user_view.data_size]\r
500                                 }, context_instance=RequestContext(request))\r
501 \r
502 def user_responses(request, user_id, user_view):\r
503     """\r
504     We list answers for question, comments, and answer accepted by others for this user.\r
505     """\r
506     class Response:\r
507         def __init__(self, type, title, question_id, answer_id, time, username, user_id, content):\r
508             self.type = type\r
509             self.title = title\r
510             self.titlelink = reverse('question', args=[question_id]) + u'%s#%s' % (slugify(title), answer_id)\r
511             self.time = time\r
512             self.userlink = reverse('users') + u'%s/%s/' % (user_id, username)\r
513             self.username = username\r
514             self.content = u'%s ...' % strip_tags(content)[:300]\r
515 \r
516         def __unicode__(self):\r
517             return u'%s %s' % (self.type, self.titlelink)\r
518 \r
519     user = get_object_or_404(User, id=user_id)\r
520     responses = []\r
521     answers = Answer.objects.extra(\r
522                                     select={\r
523                                         'title' : 'question.title',\r
524                                         'question_id' : 'question.id',\r
525                                         'answer_id' : 'answer.id',\r
526                                         'added_at' : 'answer.added_at',\r
527                                         'html' : 'answer.html',\r
528                                         'username' : 'auth_user.username',\r
529                                         'user_id' : 'auth_user.id'\r
530                                         },\r
531                                     select_params=[user_id],\r
532                                     tables=['answer', 'question', 'auth_user'],\r
533                                     where=['answer.question_id = question.id AND NOT answer.deleted AND NOT question.deleted AND '+\r
534                                         'question.author_id = %s AND answer.author_id <> %s AND answer.author_id=auth_user.id'],\r
535                                     params=[user_id, user_id],\r
536                                     order_by=['-answer.id']\r
537                                 ).values(\r
538                                         'title',\r
539                                         'question_id',\r
540                                         'answer_id',\r
541                                         'added_at',\r
542                                         'html',\r
543                                         'username',\r
544                                         'user_id'\r
545                                         )\r
546     if len(answers) > 0:\r
547         answers = [(Response(TYPE_RESPONSE['QUESTION_ANSWERED'], a['title'], a['question_id'],\r
548         a['answer_id'], a['added_at'], a['username'], a['user_id'], a['html'])) for a in answers]\r
549         responses.extend(answers)\r
550 \r
551 \r
552     # question comments\r
553     comments = Comment.active.extra(\r
554                                 select={\r
555                                     'title' : 'question.title',\r
556                                     'question_id' : 'comment.object_id',\r
557                                     'added_at' : 'comment.added_at',\r
558                                     'comment' : 'comment.comment',\r
559                                     'username' : 'auth_user.username',\r
560                                     'user_id' : 'auth_user.id'\r
561                                     },\r
562                                 tables=['question', 'auth_user', 'comment'],\r
563                                 where=['NOT question.deleted AND question.author_id = %s AND comment.object_id=question.id AND '+\r
564                                     'comment.content_type_id=%s AND comment.user_id <> %s AND comment.user_id = auth_user.id'],\r
565                                 params=[user_id, question_type_id, user_id],\r
566                                 order_by=['-comment.added_at']\r
567                             ).values(\r
568                                     'title',\r
569                                     'question_id',\r
570                                     'added_at',\r
571                                     'comment',\r
572                                     'username',\r
573                                     'user_id'\r
574                                     )\r
575 \r
576     if len(comments) > 0:\r
577         comments = [(Response(TYPE_RESPONSE['QUESTION_COMMENTED'], c['title'], c['question_id'],\r
578             '', c['added_at'], c['username'], c['user_id'], c['comment'])) for c in comments]\r
579         responses.extend(comments)\r
580 \r
581     # answer comments\r
582     comments = Comment.active.extra(\r
583         select={\r
584             'title' : 'question.title',\r
585             'question_id' : 'question.id',\r
586             'answer_id' : 'answer.id',\r
587             'added_at' : 'comment.added_at',\r
588             'comment' : 'comment.comment',\r
589             'username' : 'auth_user.username',\r
590             'user_id' : 'auth_user.id'\r
591             },\r
592         tables=['answer', 'auth_user', 'comment', 'question'],\r
593         where=['NOT answer.deleted AND answer.author_id = %s AND comment.object_id=answer.id AND '+\r
594             'comment.content_type_id=%s AND comment.user_id <> %s AND comment.user_id = auth_user.id '+\r
595             'AND question.id = answer.question_id'],\r
596         params=[user_id, answer_type_id, user_id],\r
597         order_by=['-comment.added_at']\r
598     ).values(\r
599             'title',\r
600             'question_id',\r
601             'answer_id',\r
602             'added_at',\r
603             'comment',\r
604             'username',\r
605             'user_id'\r
606             )\r
607 \r
608     if len(comments) > 0:\r
609         comments = [(Response(TYPE_RESPONSE['ANSWER_COMMENTED'], c['title'], c['question_id'],\r
610         c['answer_id'], c['added_at'], c['username'], c['user_id'], c['comment'])) for c in comments]\r
611         responses.extend(comments)\r
612 \r
613     # answer has been accepted\r
614     answers = Answer.objects.extra(\r
615         select={\r
616             'title' : 'question.title',\r
617             'question_id' : 'question.id',\r
618             'answer_id' : 'answer.id',\r
619             'added_at' : 'answer.accepted_at',\r
620             'html' : 'answer.html',\r
621             'username' : 'auth_user.username',\r
622             'user_id' : 'auth_user.id'\r
623             },\r
624         select_params=[user_id],\r
625         tables=['answer', 'question', 'auth_user'],\r
626         where=['answer.question_id = question.id AND NOT answer.deleted AND NOT question.deleted AND '+\r
627             'answer.author_id = %s AND answer.accepted=True AND question.author_id=auth_user.id'],\r
628         params=[user_id],\r
629         order_by=['-answer.id']\r
630     ).values(\r
631             'title',\r
632             'question_id',\r
633             'answer_id',\r
634             'added_at',\r
635             'html',\r
636             'username',\r
637             'user_id'\r
638             )\r
639     if len(answers) > 0:\r
640         answers = [(Response(TYPE_RESPONSE['ANSWER_ACCEPTED'], a['title'], a['question_id'],\r
641             a['answer_id'], a['added_at'], a['username'], a['user_id'], a['html'])) for a in answers]\r
642         responses.extend(answers)\r
643 \r
644     # sort posts by time\r
645     responses.sort(lambda x,y: cmp(y.time, x.time))\r
646 \r
647     return render_to_response(user_view.template_file,{\r
648         "tab_name" : user_view.id,\r
649         "tab_description" : user_view.tab_description,\r
650         "page_title" : user_view.page_title,\r
651         "view_user" : user,\r
652         "responses" : responses[:user_view.data_size],\r
653 \r
654     }, context_instance=RequestContext(request))\r
655 \r
656 def user_votes(request, user_id, user_view):\r
657     user = get_object_or_404(User, id=user_id)\r
658     if not request.user == user:\r
659         raise Http404\r
660     votes = []\r
661     question_votes = Vote.active.extra(\r
662         select={\r
663             'title' : 'question.title',\r
664             'question_id' : 'question.id',\r
665             'answer_id' : 0,\r
666             'voted_at' : 'vote.voted_at',\r
667             'vote' : 'vote',\r
668             },\r
669         select_params=[user_id],\r
670         tables=['vote', 'question', 'auth_user'],\r
671         where=['vote.content_type_id = %s AND vote.user_id = %s AND vote.object_id = question.id '+\r
672             'AND vote.user_id=auth_user.id'],\r
673         params=[question_type_id, user_id],\r
674         order_by=['-vote.id']\r
675     ).values(\r
676             'title',\r
677             'question_id',\r
678             'answer_id',\r
679             'voted_at',\r
680             'vote',\r
681             )\r
682     if(len(question_votes) > 0):\r
683         votes.extend(question_votes)\r
684 \r
685     answer_votes = Vote.active.extra(\r
686         select={\r
687             'title' : 'question.title',\r
688             'question_id' : 'question.id',\r
689             'answer_id' : 'answer.id',\r
690             'voted_at' : 'vote.voted_at',\r
691             'vote' : 'vote',\r
692             },\r
693         select_params=[user_id],\r
694         tables=['vote', 'answer', 'question', 'auth_user'],\r
695         where=['vote.content_type_id = %s AND vote.user_id = %s AND vote.object_id = answer.id '+\r
696             'AND answer.question_id = question.id AND vote.user_id=auth_user.id'],\r
697         params=[answer_type_id, user_id],\r
698         order_by=['-vote.id']\r
699     ).values(\r
700             'title',\r
701             'question_id',\r
702             'answer_id',\r
703             'voted_at',\r
704             'vote',\r
705             )\r
706 \r
707     if(len(answer_votes) > 0):\r
708         votes.extend(answer_votes)\r
709     votes.sort(lambda x,y: cmp(y['voted_at'], x['voted_at']))\r
710     return render_to_response(user_view.template_file,{\r
711         "tab_name" : user_view.id,\r
712         "tab_description" : user_view.tab_description,\r
713         "page_title" : user_view.page_title,\r
714         "view_user" : user,\r
715         "votes" : votes[:user_view.data_size]\r
716 \r
717     }, context_instance=RequestContext(request))\r
718 \r
719 def user_reputation(request, user_id, user_view):\r
720     user = get_object_or_404(User, id=user_id)\r
721 \r
722     reputation = user.reputes.order_by('-reputed_at')\r
723 \r
724     graph_data = simplejson.dumps([\r
725             (time.mktime(rep.reputed_at.timetuple()) * 1000, rep.reputation)\r
726             for rep in reputation\r
727     ])\r
728 \r
729     return render_to_response(user_view.template_file, {\r
730                               "tab_name": user_view.id,\r
731                               "tab_description": user_view.tab_description,\r
732                               "page_title": user_view.page_title,\r
733                               "view_user": user,\r
734                               "reputation": reputation,\r
735                               "graph_data": graph_data\r
736                               }, context_instance=RequestContext(request))\r
737 \r
738 def user_favorites(request, user_id, user_view):\r
739     user = get_object_or_404(User, id=user_id)\r
740     questions = Question.objects.extra(\r
741         select={\r
742             'vote_count' : 'question.vote_up_count + question.vote_down_count',\r
743             'favorited_myself' : 'SELECT count(*) FROM favorite_question f WHERE f.user_id = %s '+\r
744                 'AND f.question_id = question.id',\r
745             'la_user_id' : 'auth_user.id',\r
746             'la_username' : 'auth_user.username',\r
747             'la_user_gold' : 'forum_user.gold',\r
748             'la_user_silver' : 'forum_user.silver',\r
749             'la_user_bronze' : 'forum_user.bronze',\r
750             'la_user_reputation' : 'forum_user.reputation'\r
751             },\r
752         select_params=[user_id],\r
753         tables=['question', 'auth_user', 'favorite_question', 'forum_user'],\r
754         where=['NOT question.deleted AND question.last_activity_by_id = auth_user.id '+\r
755             'AND favorite_question.question_id = question.id AND favorite_question.user_id = %s AND forum_user.user_ptr_id = auth_user.id'],\r
756         params=[user_id],\r
757         order_by=['-vote_count', '-question.id']\r
758     ).values('vote_count',\r
759              'favorited_myself',\r
760              'id',\r
761              'title',\r
762              'author_id',\r
763              'added_at',\r
764              'answer_accepted',\r
765              'answer_count',\r
766              'comment_count',\r
767              'view_count',\r
768              'favourite_count',\r
769              'summary',\r
770              'tagnames',\r
771              'vote_up_count',\r
772              'vote_down_count',\r
773              'last_activity_at',\r
774              'la_user_id',\r
775              'la_username',\r
776              'la_user_gold',\r
777              'la_user_silver',\r
778              'la_user_bronze',\r
779              'la_user_reputation')\r
780     return render_to_response(user_view.template_file,{\r
781         "tab_name" : user_view.id,\r
782         "tab_description" : user_view.tab_description,\r
783         "page_title" : user_view.page_title,\r
784         "questions" : questions[:user_view.data_size],\r
785         "view_user" : user\r
786     }, context_instance=RequestContext(request))\r
787 \r
788 def user_subscription_settings(request, user_id, user_view):\r
789     user = get_object_or_404(User, id=user_id)\r
790 \r
791     if request.method == 'POST':\r
792         form = SubscriptionSettingsForm(request.POST)\r
793 \r
794         if 'notswitch' in request.POST:\r
795             user.subscription_settings.enable_notifications = not user.subscription_settings.enable_notifications\r
796             user.subscription_settings.save()\r
797 \r
798             if user.subscription_settings.enable_notifications:\r
799                 request.user.message_set.create(message=_('Notifications are now enabled'))\r
800             else:\r
801                 request.user.message_set.create(message=_('Notifications are now disabled'))\r
802         else:\r
803             form.is_valid()\r
804             for k,v in form.cleaned_data.items():\r
805                 setattr(user.subscription_settings, k, v)\r
806 \r
807             user.subscription_settings.save()\r
808             request.user.message_set.create(message=_('New subscription settings are now saved'))\r
809     else:\r
810         form = SubscriptionSettingsForm(user.subscription_settings.__dict__)\r
811 \r
812     notificatons_on = user.subscription_settings.enable_notifications\r
813 \r
814     return render_to_response(user_view.template_file,{\r
815         'tab_name':user_view.id,\r
816         'tab_description':user_view.tab_description,\r
817         'page_title':user_view.page_title,\r
818         'view_user':user,\r
819         'notificatons_on': notificatons_on,\r
820         'form':form,\r
821     }, context_instance=RequestContext(request))\r
822 \r
823 class UserView:\r
824     def __init__(self, id, tab_title, tab_description, page_title, view_func, template_file, data_size=0):\r
825         self.id = id\r
826         self.tab_title = tab_title\r
827         self.tab_description = tab_description\r
828         self.page_title = page_title\r
829         self.view_func = view_func \r
830         self.template_file = template_file\r
831         self.data_size = data_size\r
832         \r
833 USER_TEMPLATE_VIEWS = (\r
834     UserView(\r
835         id = 'stats',\r
836         tab_title = _('overview'),\r
837         tab_description = _('user profile'),\r
838         page_title = _('user profile overview'),\r
839         view_func = user_stats,\r
840         template_file = 'user_stats.html'\r
841     ),\r
842     UserView(\r
843         id = 'recent',\r
844         tab_title = _('recent activity'),\r
845         tab_description = _('recent user activity'),\r
846         page_title = _('profile - recent activity'),\r
847         view_func = user_recent,\r
848         template_file = 'user_recent.html',\r
849         data_size = 50\r
850     ),\r
851     UserView(\r
852         id = 'responses',\r
853         tab_title = _('responses'),\r
854         tab_description = _('comments and answers to others questions'),\r
855         page_title = _('profile - responses'),\r
856         view_func = user_responses,\r
857         template_file = 'user_responses.html',\r
858         data_size = 50\r
859     ),\r
860     UserView(\r
861         id = 'reputation',\r
862         tab_title = _('reputation'),\r
863         tab_description = _('user reputation in the community'),\r
864         page_title = _('profile - user reputation'),\r
865         view_func = user_reputation,\r
866         template_file = 'user_reputation.html'\r
867     ),\r
868     UserView(\r
869         id = 'favorites',\r
870         tab_title = _('favorite questions'),\r
871         tab_description = _('users favorite questions'),\r
872         page_title = _('profile - favorite questions'),\r
873         view_func = user_favorites,\r
874         template_file = 'user_favorites.html',\r
875         data_size = 50\r
876     ),\r
877     UserView(\r
878         id = 'votes',\r
879         tab_title = _('casted votes'),\r
880         tab_description = _('user vote record'),\r
881         page_title = _('profile - votes'),\r
882         view_func = user_votes,\r
883         template_file = 'user_votes.html',\r
884         data_size = 50\r
885     ),\r
886     UserView(\r
887         id = 'subscriptions',\r
888         tab_title = _('subscriptions'),\r
889         tab_description = _('subscription settings'),\r
890         page_title = _('profile - subscriptions'),\r
891         view_func = user_subscription_settings,\r
892         template_file = 'user_subscriptions.html'\r
893     )\r
894 )\r
895 \r
896 def user(request, id, slug=None):\r
897     sort = request.GET.get('sort', 'stats')\r
898     user_view = dict((v.id, v) for v in USER_TEMPLATE_VIEWS).get(sort, USER_TEMPLATE_VIEWS[0])\r
899     from forum.views import users\r
900     func = user_view.view_func\r
901     return func(request, id, user_view)\r
902 \r
903 @login_required\r
904 def account_settings(request):\r
905     """\r
906     index pages to changes some basic account settings :\r
907      - change password\r
908      - change email\r
909      - associate a new openid\r
910      - delete account\r
911 \r
912     url : /\r
913 \r
914     template : authopenid/settings.html\r
915     """\r
916     logging.debug('')\r
917     msg = request.GET.get('msg', '')\r
918     is_openid = False\r
919 \r
920     return render_to_response('account_settings.html', {\r
921         'msg': msg,\r
922         'is_openid': is_openid\r
923         }, context_instance=RequestContext(request))\r
924 \r