]> git.openstreetmap.org Git - osqa.git/blob - forum/views/users.py
initial import
[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     questions = Question.objects.extra(\r
149         select={\r
150             'vote_count' : 'question.score',\r
151             'favorited_myself' : 'SELECT count(*) FROM favorite_question f WHERE f.user_id = %s AND f.question_id = question.id',\r
152             'la_user_id' : 'auth_user.id',\r
153             'la_username' : 'auth_user.username',\r
154             'la_user_gold' : 'forum_user.gold',\r
155             'la_user_silver' : 'forum_user.silver',\r
156             'la_user_bronze' : 'forum_user.bronze',\r
157             'la_user_reputation' : 'forum_user.reputation'\r
158             },\r
159         select_params=[user_id],\r
160         tables=['question', 'auth_user', 'forum_user'],\r
161         where=['NOT question.deleted AND question.author_id=%s AND question.last_activity_by_id = auth_user.id AND forum_user.user_ptr_id = auth_user.id'],\r
162         params=[user_id],\r
163         order_by=['-vote_count', '-last_activity_at']\r
164     ).values('vote_count',\r
165              'favorited_myself',\r
166              'id',\r
167              'title',\r
168              'author_id',\r
169              'added_at',\r
170              'answer_accepted',\r
171              'answer_count',\r
172              'comment_count',\r
173              'view_count',\r
174              'favourite_count',\r
175              'summary',\r
176              'tagnames',\r
177              'vote_up_count',\r
178              'vote_down_count',\r
179              'last_activity_at',\r
180              'la_user_id',\r
181              'la_username',\r
182              'la_user_gold',\r
183              'la_user_silver',\r
184              'la_user_bronze',\r
185              'la_user_reputation')[:100]\r
186 \r
187     answered_questions = Question.objects.extra(\r
188         select={\r
189             'vote_up_count' : 'answer.vote_up_count',\r
190             'vote_down_count' : 'answer.vote_down_count',\r
191             'answer_id' : 'answer.id',\r
192             'accepted' : 'answer.accepted',\r
193             'vote_count' : 'answer.score',\r
194             'comment_count' : 'answer.comment_count'\r
195             },\r
196         tables=['question', 'answer'],\r
197         where=['NOT answer.deleted AND NOT question.deleted AND answer.author_id=%s AND answer.question_id=question.id'],\r
198         params=[user_id],\r
199         order_by=['-vote_count', '-answer_id'],\r
200         select_params=[user_id]\r
201     ).distinct().values('comment_count',\r
202                         'id',\r
203                         'answer_id',\r
204                         'title',\r
205                         'author_id',\r
206                         'accepted',\r
207                         'vote_count',\r
208                         'answer_count',\r
209                         'vote_up_count',\r
210                         'vote_down_count')[:100]\r
211 \r
212     up_votes = user.get_up_vote_count()\r
213     down_votes = user.get_down_vote_count()\r
214     votes_today = user.get_vote_count_today()\r
215     votes_total = int(settings.MAX_VOTES_PER_DAY)\r
216 \r
217     question_id_set = set(map(lambda v: v['id'], list(questions))) \\r
218                         | set(map(lambda v: v['id'], list(answered_questions)))\r
219 \r
220     user_tags = Tag.objects.filter(questions__id__in = question_id_set)\r
221     try:\r
222         from django.db.models import Count\r
223         awards = Award.objects.extra(\r
224                                         select={'id': 'badge.id', \r
225                                                 'name':'badge.name', \r
226                                                 'description': 'badge.description', \r
227                                                 'type': 'badge.type'},\r
228                                         tables=['award', 'badge'],\r
229                                         order_by=['-awarded_at'],\r
230                                         where=['user_id=%s AND badge_id=badge.id'],\r
231                                         params=[user.id]\r
232                                     ).values('id', 'name', 'description', 'type')\r
233         total_awards = awards.count()\r
234         awards = awards.annotate(count = Count('badge__id'))\r
235         user_tags = user_tags.annotate(user_tag_usage_count=Count('name'))\r
236 \r
237     except ImportError:\r
238         awards = Award.objects.extra(\r
239                                         select={'id': 'badge.id', \r
240                                                 'count': 'count(badge_id)', \r
241                                                 'name':'badge.name', \r
242                                                 'description': 'badge.description', \r
243                                                 'type': 'badge.type'},\r
244                                         tables=['award', 'badge'],\r
245                                         order_by=['-awarded_at'],\r
246                                         where=['user_id=%s AND badge_id=badge.id'],\r
247                                         params=[user.id]\r
248                                     ).values('id', 'count', 'name', 'description', 'type')\r
249         total_awards = awards.count()\r
250         awards.query.group_by = ['badge_id']\r
251 \r
252         user_tags = user_tags.extra(\r
253             select={'user_tag_usage_count': 'COUNT(1)',},\r
254             order_by=['-user_tag_usage_count'],\r
255         )\r
256         user_tags.query.group_by = ['name']\r
257 \r
258     if request.user.is_superuser:\r
259         moderate_user_form = ModerateUserForm(instance=user)\r
260     else:\r
261         moderate_user_form = None\r
262 \r
263     return render_to_response(user_view.template_file,{\r
264                                 'moderate_user_form': moderate_user_form,\r
265                                 "tab_name" : user_view.id,\r
266                                 "tab_description" : user_view.tab_description,\r
267                                 "page_title" : user_view.page_title,\r
268                                 "view_user" : user,\r
269                                 "questions" : questions,\r
270                                 "answered_questions" : answered_questions,\r
271                                 "up_votes" : up_votes,\r
272                                 "down_votes" : down_votes,\r
273                                 "total_votes": up_votes + down_votes,\r
274                                 "votes_today_left": votes_total-votes_today,\r
275                                 "votes_total_per_day": votes_total,\r
276                                 "user_tags" : user_tags[:50],\r
277                                 "awards": awards,\r
278                                 "total_awards" : total_awards,\r
279                             }, context_instance=RequestContext(request))\r
280 \r
281 def user_recent(request, user_id, user_view):\r
282     user = get_object_or_404(User, id=user_id)\r
283     def get_type_name(type_id):\r
284         for item in TYPE_ACTIVITY:\r
285             if type_id in item:\r
286                 return item[1]\r
287 \r
288     class Event:\r
289         def __init__(self, time, type, title, summary, answer_id, question_id):\r
290             self.time = time\r
291             self.type = get_type_name(type)\r
292             self.type_id = type\r
293             self.title = title\r
294             self.summary = summary\r
295             slug_title = slugify(title)\r
296             self.title_link = reverse('question', kwargs={'id':question_id, 'slug':slug_title})\r
297             if int(answer_id) > 0:\r
298                 self.title_link += '#%s' % answer_id\r
299 \r
300     class AwardEvent:\r
301         def __init__(self, time, type, id):\r
302             self.time = time\r
303             self.type = get_type_name(type)\r
304             self.type_id = type\r
305             self.badge = get_object_or_404(Badge, id=id)\r
306 \r
307     activities = []\r
308     # ask questions\r
309     questions = Activity.objects.extra(\r
310         select={\r
311             'title' : 'question.title',\r
312             'question_id' : 'question.id',\r
313             'active_at' : 'activity.active_at',\r
314             'activity_type' : 'activity.activity_type'\r
315             },\r
316         tables=['activity', 'question'],\r
317         where=['activity.content_type_id = %s AND activity.object_id = ' +\r
318             'question.id AND NOT question.deleted AND activity.user_id = %s AND activity.activity_type = %s'],\r
319         params=[question_type_id, user_id, TYPE_ACTIVITY_ASK_QUESTION],\r
320         order_by=['-activity.active_at']\r
321     ).values(\r
322             'title',\r
323             'question_id',\r
324             'active_at',\r
325             'activity_type'\r
326             )\r
327     if len(questions) > 0:\r
328         questions = [(Event(q['active_at'], q['activity_type'], q['title'], '', '0', \\r
329                       q['question_id'])) for q in questions]\r
330         activities.extend(questions)\r
331 \r
332     # answers\r
333     answers = Activity.objects.extra(\r
334         select={\r
335             'title' : 'question.title',\r
336             'question_id' : 'question.id',\r
337             'answer_id' : 'answer.id',\r
338             'active_at' : 'activity.active_at',\r
339             'activity_type' : 'activity.activity_type'\r
340             },\r
341         tables=['activity', 'answer', 'question'],\r
342         where=['activity.content_type_id = %s AND activity.object_id = answer.id AND ' + \r
343             'answer.question_id=question.id AND NOT answer.deleted AND activity.user_id=%s AND '+\r
344             'activity.activity_type=%s AND NOT question.deleted'],\r
345         params=[answer_type_id, user_id, TYPE_ACTIVITY_ANSWER],\r
346         order_by=['-activity.active_at']\r
347     ).values(\r
348             'title',\r
349             'question_id',\r
350             'answer_id',\r
351             'active_at',\r
352             'activity_type'\r
353             )\r
354     if len(answers) > 0:\r
355         answers = [(Event(q['active_at'], q['activity_type'], q['title'], '', q['answer_id'], \\r
356                     q['question_id'])) for q in answers]\r
357         activities.extend(answers)\r
358 \r
359     # question comments\r
360     comments = Activity.objects.extra(\r
361         select={\r
362             'title' : 'question.title',\r
363             'question_id' : 'comment.object_id',\r
364             'added_at' : 'comment.added_at',\r
365             'activity_type' : 'activity.activity_type'\r
366             },\r
367         tables=['activity', 'question', 'comment'],\r
368 \r
369         where=['activity.content_type_id = %s AND activity.object_id = comment.id AND '+\r
370             'activity.user_id = comment.user_id AND comment.object_id=question.id AND '+\r
371             'comment.content_type_id=%s AND activity.user_id = %s AND activity.activity_type=%s AND ' +\r
372             'NOT question.deleted'],\r
373         params=[comment_type_id, question_type_id, user_id, TYPE_ACTIVITY_COMMENT_QUESTION],\r
374         order_by=['-comment.added_at']\r
375     ).values(\r
376             'title',\r
377             'question_id',\r
378             'added_at',\r
379             'activity_type'\r
380             )\r
381 \r
382     if len(comments) > 0:\r
383         comments = [(Event(q['added_at'], q['activity_type'], q['title'], '', '0', \\r
384                      q['question_id'])) for q in comments]\r
385         activities.extend(comments)\r
386 \r
387     # answer comments\r
388     comments = Activity.objects.extra(\r
389         select={\r
390             'title' : 'question.title',\r
391             'question_id' : 'question.id',\r
392             'answer_id' : 'answer.id',\r
393             'added_at' : 'comment.added_at',\r
394             'activity_type' : 'activity.activity_type'\r
395             },\r
396         tables=['activity', 'question', 'answer', 'comment'],\r
397 \r
398         where=['activity.content_type_id = %s AND activity.object_id = comment.id AND '+\r
399             'activity.user_id = comment.user_id AND comment.object_id=answer.id AND '+\r
400             'comment.content_type_id=%s AND question.id = answer.question_id AND '+\r
401             'activity.user_id = %s AND activity.activity_type=%s AND '+\r
402             'NOT answer.deleted AND NOT question.deleted'],\r
403         params=[comment_type_id, answer_type_id, user_id, TYPE_ACTIVITY_COMMENT_ANSWER],\r
404         order_by=['-comment.added_at']\r
405     ).values(\r
406             'title',\r
407             'question_id',\r
408             'answer_id',\r
409             'added_at',\r
410             'activity_type'\r
411             )\r
412 \r
413     if len(comments) > 0:\r
414         comments = [(Event(q['added_at'], q['activity_type'], q['title'], '', q['answer_id'], \\r
415                      q['question_id'])) for q in comments]\r
416         activities.extend(comments)\r
417 \r
418     # question revisions\r
419     revisions = Activity.objects.extra(\r
420         select={\r
421             'title' : 'question_revision.title',\r
422             'question_id' : 'question_revision.question_id',\r
423             'added_at' : 'activity.active_at',\r
424             'activity_type' : 'activity.activity_type',\r
425             'summary' : 'question_revision.summary'\r
426             },\r
427         tables=['activity', 'question_revision', 'question'],\r
428         where=['activity.content_type_id = %s AND activity.object_id = question_revision.id AND '+\r
429             'question_revision.id=question.id AND NOT question.deleted AND '+\r
430             'activity.user_id = question_revision.author_id AND activity.user_id = %s AND '+\r
431             'activity.activity_type=%s'],\r
432         params=[question_revision_type_id, user_id, TYPE_ACTIVITY_UPDATE_QUESTION],\r
433         order_by=['-activity.active_at']\r
434     ).values(\r
435             'title',\r
436             'question_id',\r
437             'added_at',\r
438             'activity_type',\r
439             'summary'\r
440             )\r
441 \r
442     if len(revisions) > 0:\r
443         revisions = [(Event(q['added_at'], q['activity_type'], q['title'], q['summary'], '0', \\r
444                       q['question_id'])) for q in revisions]\r
445         activities.extend(revisions)\r
446 \r
447     # answer revisions\r
448     revisions = Activity.objects.extra(\r
449         select={\r
450             'title' : 'question.title',\r
451             'question_id' : 'question.id',\r
452             'answer_id' : 'answer.id',\r
453             'added_at' : 'activity.active_at',\r
454             'activity_type' : 'activity.activity_type',\r
455             'summary' : 'answer_revision.summary'\r
456             },\r
457         tables=['activity', 'answer_revision', 'question', 'answer'],\r
458 \r
459         where=['activity.content_type_id = %s AND activity.object_id = answer_revision.id AND '+\r
460             'activity.user_id = answer_revision.author_id AND activity.user_id = %s AND '+\r
461             'answer_revision.answer_id=answer.id AND answer.question_id = question.id AND '+\r
462             'NOT question.deleted AND NOT answer.deleted AND '+\r
463             'activity.activity_type=%s'],\r
464         params=[answer_revision_type_id, user_id, TYPE_ACTIVITY_UPDATE_ANSWER],\r
465         order_by=['-activity.active_at']\r
466     ).values(\r
467             'title',\r
468             'question_id',\r
469             'added_at',\r
470             'answer_id',\r
471             'activity_type',\r
472             'summary'\r
473             )\r
474 \r
475     if len(revisions) > 0:\r
476         revisions = [(Event(q['added_at'], q['activity_type'], q['title'], q['summary'], \\r
477                       q['answer_id'], q['question_id'])) for q in revisions]\r
478         activities.extend(revisions)\r
479 \r
480     # accepted answers\r
481     accept_answers = Activity.objects.extra(\r
482         select={\r
483             'title' : 'question.title',\r
484             'question_id' : 'question.id',\r
485             'added_at' : 'activity.active_at',\r
486             'activity_type' : 'activity.activity_type',\r
487             },\r
488         tables=['activity', 'answer', 'question'],\r
489         where=['activity.content_type_id = %s AND activity.object_id = answer.id AND '+\r
490             'activity.user_id = question.author_id AND activity.user_id = %s AND '+\r
491             'NOT answer.deleted AND NOT question.deleted AND '+\r
492             'answer.question_id=question.id AND activity.activity_type=%s'],\r
493         params=[answer_type_id, user_id, TYPE_ACTIVITY_MARK_ANSWER],\r
494         order_by=['-activity.active_at']\r
495     ).values(\r
496             'title',\r
497             'question_id',\r
498             'added_at',\r
499             'activity_type',\r
500             )\r
501     if len(accept_answers) > 0:\r
502         accept_answers = [(Event(q['added_at'], q['activity_type'], q['title'], '', '0', \\r
503             q['question_id'])) for q in accept_answers]\r
504         activities.extend(accept_answers)\r
505     #award history\r
506     awards = Activity.objects.extra(\r
507         select={\r
508             'badge_id' : 'badge.id',\r
509             'awarded_at': 'award.awarded_at',\r
510             'activity_type' : 'activity.activity_type'\r
511             },\r
512         tables=['activity', 'award', 'badge'],\r
513         where=['activity.user_id = award.user_id AND activity.user_id = %s AND '+\r
514             'award.badge_id=badge.id AND activity.object_id=award.id AND activity.activity_type=%s'],\r
515         params=[user_id, TYPE_ACTIVITY_PRIZE],\r
516         order_by=['-activity.active_at']\r
517     ).values(\r
518             'badge_id',\r
519             'awarded_at',\r
520             'activity_type'\r
521             )\r
522     if len(awards) > 0:\r
523         awards = [(AwardEvent(q['awarded_at'], q['activity_type'], q['badge_id'])) for q in awards]\r
524         activities.extend(awards)\r
525 \r
526     activities.sort(lambda x,y: cmp(y.time, x.time))\r
527 \r
528     return render_to_response(user_view.template_file,{\r
529                                     "tab_name" : user_view.id,\r
530                                     "tab_description" : user_view.tab_description,\r
531                                     "page_title" : user_view.page_title,\r
532                                     "view_user" : user,\r
533                                     "activities" : activities[:user_view.data_size]\r
534                                 }, context_instance=RequestContext(request))\r
535 \r
536 def user_responses(request, user_id, user_view):\r
537     """\r
538     We list answers for question, comments, and answer accepted by others for this user.\r
539     """\r
540     class Response:\r
541         def __init__(self, type, title, question_id, answer_id, time, username, user_id, content):\r
542             self.type = type\r
543             self.title = title\r
544             self.titlelink = reverse('question', args=[question_id]) + u'%s#%s' % (slugify(title), answer_id)\r
545             self.time = time\r
546             self.userlink = reverse('users') + u'%s/%s/' % (user_id, username)\r
547             self.username = username\r
548             self.content = u'%s ...' % strip_tags(content)[:300]\r
549 \r
550         def __unicode__(self):\r
551             return u'%s %s' % (self.type, self.titlelink)\r
552 \r
553     user = get_object_or_404(User, id=user_id)\r
554     responses = []\r
555     answers = Answer.objects.extra(\r
556                                     select={\r
557                                         'title' : 'question.title',\r
558                                         'question_id' : 'question.id',\r
559                                         'answer_id' : 'answer.id',\r
560                                         'added_at' : 'answer.added_at',\r
561                                         'html' : 'answer.html',\r
562                                         'username' : 'auth_user.username',\r
563                                         'user_id' : 'auth_user.id'\r
564                                         },\r
565                                     select_params=[user_id],\r
566                                     tables=['answer', 'question', 'auth_user'],\r
567                                     where=['answer.question_id = question.id AND NOT answer.deleted AND NOT question.deleted AND '+\r
568                                         'question.author_id = %s AND answer.author_id <> %s AND answer.author_id=auth_user.id'],\r
569                                     params=[user_id, user_id],\r
570                                     order_by=['-answer.id']\r
571                                 ).values(\r
572                                         'title',\r
573                                         'question_id',\r
574                                         'answer_id',\r
575                                         'added_at',\r
576                                         'html',\r
577                                         'username',\r
578                                         'user_id'\r
579                                         )\r
580     if len(answers) > 0:\r
581         answers = [(Response(TYPE_RESPONSE['QUESTION_ANSWERED'], a['title'], a['question_id'],\r
582         a['answer_id'], a['added_at'], a['username'], a['user_id'], a['html'])) for a in answers]\r
583         responses.extend(answers)\r
584 \r
585 \r
586     # question comments\r
587     comments = Comment.active.extra(\r
588                                 select={\r
589                                     'title' : 'question.title',\r
590                                     'question_id' : 'comment.object_id',\r
591                                     'added_at' : 'comment.added_at',\r
592                                     'comment' : 'comment.comment',\r
593                                     'username' : 'auth_user.username',\r
594                                     'user_id' : 'auth_user.id'\r
595                                     },\r
596                                 tables=['question', 'auth_user', 'comment'],\r
597                                 where=['NOT question.deleted AND question.author_id = %s AND comment.object_id=question.id AND '+\r
598                                     'comment.content_type_id=%s AND comment.user_id <> %s AND comment.user_id = auth_user.id'],\r
599                                 params=[user_id, question_type_id, user_id],\r
600                                 order_by=['-comment.added_at']\r
601                             ).values(\r
602                                     'title',\r
603                                     'question_id',\r
604                                     'added_at',\r
605                                     'comment',\r
606                                     'username',\r
607                                     'user_id'\r
608                                     )\r
609 \r
610     if len(comments) > 0:\r
611         comments = [(Response(TYPE_RESPONSE['QUESTION_COMMENTED'], c['title'], c['question_id'],\r
612             '', c['added_at'], c['username'], c['user_id'], c['comment'])) for c in comments]\r
613         responses.extend(comments)\r
614 \r
615     # answer comments\r
616     comments = Comment.active.extra(\r
617         select={\r
618             'title' : 'question.title',\r
619             'question_id' : 'question.id',\r
620             'answer_id' : 'answer.id',\r
621             'added_at' : 'comment.added_at',\r
622             'comment' : 'comment.comment',\r
623             'username' : 'auth_user.username',\r
624             'user_id' : 'auth_user.id'\r
625             },\r
626         tables=['answer', 'auth_user', 'comment', 'question'],\r
627         where=['NOT answer.deleted AND answer.author_id = %s AND comment.object_id=answer.id AND '+\r
628             'comment.content_type_id=%s AND comment.user_id <> %s AND comment.user_id = auth_user.id '+\r
629             'AND question.id = answer.question_id'],\r
630         params=[user_id, answer_type_id, user_id],\r
631         order_by=['-comment.added_at']\r
632     ).values(\r
633             'title',\r
634             'question_id',\r
635             'answer_id',\r
636             'added_at',\r
637             'comment',\r
638             'username',\r
639             'user_id'\r
640             )\r
641 \r
642     if len(comments) > 0:\r
643         comments = [(Response(TYPE_RESPONSE['ANSWER_COMMENTED'], c['title'], c['question_id'],\r
644         c['answer_id'], c['added_at'], c['username'], c['user_id'], c['comment'])) for c in comments]\r
645         responses.extend(comments)\r
646 \r
647     # answer has been accepted\r
648     answers = Answer.objects.extra(\r
649         select={\r
650             'title' : 'question.title',\r
651             'question_id' : 'question.id',\r
652             'answer_id' : 'answer.id',\r
653             'added_at' : 'answer.accepted_at',\r
654             'html' : 'answer.html',\r
655             'username' : 'auth_user.username',\r
656             'user_id' : 'auth_user.id'\r
657             },\r
658         select_params=[user_id],\r
659         tables=['answer', 'question', 'auth_user'],\r
660         where=['answer.question_id = question.id AND NOT answer.deleted AND NOT question.deleted AND '+\r
661             'answer.author_id = %s AND answer.accepted=True AND question.author_id=auth_user.id'],\r
662         params=[user_id],\r
663         order_by=['-answer.id']\r
664     ).values(\r
665             'title',\r
666             'question_id',\r
667             'answer_id',\r
668             'added_at',\r
669             'html',\r
670             'username',\r
671             'user_id'\r
672             )\r
673     if len(answers) > 0:\r
674         answers = [(Response(TYPE_RESPONSE['ANSWER_ACCEPTED'], a['title'], a['question_id'],\r
675             a['answer_id'], a['added_at'], a['username'], a['user_id'], a['html'])) for a in answers]\r
676         responses.extend(answers)\r
677 \r
678     # sort posts by time\r
679     responses.sort(lambda x,y: cmp(y.time, x.time))\r
680 \r
681     return render_to_response(user_view.template_file,{\r
682         "tab_name" : user_view.id,\r
683         "tab_description" : user_view.tab_description,\r
684         "page_title" : user_view.page_title,\r
685         "view_user" : user,\r
686         "responses" : responses[:user_view.data_size],\r
687 \r
688     }, context_instance=RequestContext(request))\r
689 \r
690 def user_votes(request, user_id, user_view):\r
691     user = get_object_or_404(User, id=user_id)\r
692     if not request.user == user:\r
693         raise Http404\r
694     votes = []\r
695     question_votes = Vote.active.extra(\r
696         select={\r
697             'title' : 'question.title',\r
698             'question_id' : 'question.id',\r
699             'answer_id' : 0,\r
700             'voted_at' : 'vote.voted_at',\r
701             'vote' : 'vote',\r
702             },\r
703         select_params=[user_id],\r
704         tables=['vote', 'question', 'auth_user'],\r
705         where=['vote.content_type_id = %s AND vote.user_id = %s AND vote.object_id = question.id '+\r
706             'AND vote.user_id=auth_user.id'],\r
707         params=[question_type_id, user_id],\r
708         order_by=['-vote.id']\r
709     ).values(\r
710             'title',\r
711             'question_id',\r
712             'answer_id',\r
713             'voted_at',\r
714             'vote',\r
715             )\r
716     if(len(question_votes) > 0):\r
717         votes.extend(question_votes)\r
718 \r
719     answer_votes = Vote.active.extra(\r
720         select={\r
721             'title' : 'question.title',\r
722             'question_id' : 'question.id',\r
723             'answer_id' : 'answer.id',\r
724             'voted_at' : 'vote.voted_at',\r
725             'vote' : 'vote',\r
726             },\r
727         select_params=[user_id],\r
728         tables=['vote', 'answer', 'question', 'auth_user'],\r
729         where=['vote.content_type_id = %s AND vote.user_id = %s AND vote.object_id = answer.id '+\r
730             'AND answer.question_id = question.id AND vote.user_id=auth_user.id'],\r
731         params=[answer_type_id, user_id],\r
732         order_by=['-vote.id']\r
733     ).values(\r
734             'title',\r
735             'question_id',\r
736             'answer_id',\r
737             'voted_at',\r
738             'vote',\r
739             )\r
740 \r
741     if(len(answer_votes) > 0):\r
742         votes.extend(answer_votes)\r
743     votes.sort(lambda x,y: cmp(y['voted_at'], x['voted_at']))\r
744     return render_to_response(user_view.template_file,{\r
745         "tab_name" : user_view.id,\r
746         "tab_description" : user_view.tab_description,\r
747         "page_title" : user_view.page_title,\r
748         "view_user" : user,\r
749         "votes" : votes[:user_view.data_size]\r
750 \r
751     }, context_instance=RequestContext(request))\r
752 \r
753 def user_reputation(request, user_id, user_view):\r
754     user = get_object_or_404(User, id=user_id)\r
755 \r
756     reputation = user.reputes.order_by('-reputed_at')\r
757 \r
758     graph_data = simplejson.dumps([\r
759             (time.mktime(rep.reputed_at.timetuple()) * 1000, rep.reputation)\r
760             for rep in reputation\r
761     ])\r
762 \r
763     return render_to_response(user_view.template_file, {\r
764                               "tab_name": user_view.id,\r
765                               "tab_description": user_view.tab_description,\r
766                               "page_title": user_view.page_title,\r
767                               "view_user": user,\r
768                               "reputation": reputation,\r
769                               "graph_data": graph_data\r
770                               }, context_instance=RequestContext(request))\r
771 \r
772 def user_favorites(request, user_id, user_view):\r
773     user = get_object_or_404(User, id=user_id)\r
774     questions = Question.objects.extra(\r
775         select={\r
776             'vote_count' : 'question.vote_up_count + question.vote_down_count',\r
777             'favorited_myself' : 'SELECT count(*) FROM favorite_question f WHERE f.user_id = %s '+\r
778                 'AND f.question_id = question.id',\r
779             'la_user_id' : 'auth_user.id',\r
780             'la_username' : 'auth_user.username',\r
781             'la_user_gold' : 'forum_user.gold',\r
782             'la_user_silver' : 'forum_user.silver',\r
783             'la_user_bronze' : 'forum_user.bronze',\r
784             'la_user_reputation' : 'forum_user.reputation'\r
785             },\r
786         select_params=[user_id],\r
787         tables=['question', 'auth_user', 'favorite_question', 'forum_user'],\r
788         where=['NOT question.deleted AND question.last_activity_by_id = auth_user.id '+\r
789             'AND favorite_question.question_id = question.id AND favorite_question.user_id = %s AND forum_user.user_ptr_id = auth_user.id'],\r
790         params=[user_id],\r
791         order_by=['-vote_count', '-question.id']\r
792     ).values('vote_count',\r
793              'favorited_myself',\r
794              'id',\r
795              'title',\r
796              'author_id',\r
797              'added_at',\r
798              'answer_accepted',\r
799              'answer_count',\r
800              'comment_count',\r
801              'view_count',\r
802              'favourite_count',\r
803              'summary',\r
804              'tagnames',\r
805              'vote_up_count',\r
806              'vote_down_count',\r
807              'last_activity_at',\r
808              'la_user_id',\r
809              'la_username',\r
810              'la_user_gold',\r
811              'la_user_silver',\r
812              'la_user_bronze',\r
813              'la_user_reputation')\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         "questions" : questions[:user_view.data_size],\r
819         "view_user" : user\r
820     }, context_instance=RequestContext(request))\r
821 \r
822 def user_subscription_settings(request, user_id, user_view):\r
823     user = get_object_or_404(User, id=user_id)\r
824 \r
825     if request.method == 'POST':\r
826         form = SubscriptionSettingsForm(request.POST)\r
827 \r
828         if 'notswitch' in request.POST:\r
829             user.subscription_settings.enable_notifications = not user.subscription_settings.enable_notifications\r
830             user.subscription_settings.save()\r
831 \r
832             if user.subscription_settings.enable_notifications:\r
833                 request.user.message_set.create(message=_('Notifications are now enabled'))\r
834             else:\r
835                 request.user.message_set.create(message=_('Notifications are now disabled'))\r
836         else:\r
837             form.is_valid()\r
838             for k,v in form.cleaned_data.items():\r
839                 setattr(user.subscription_settings, k, v)\r
840 \r
841             user.subscription_settings.save()\r
842             request.user.message_set.create(message=_('New subscription settings are now saved'))\r
843     else:\r
844         form = SubscriptionSettingsForm(user.subscription_settings.__dict__)\r
845 \r
846     notificatons_on = user.subscription_settings.enable_notifications\r
847 \r
848     return render_to_response(user_view.template_file,{\r
849         'tab_name':user_view.id,\r
850         'tab_description':user_view.tab_description,\r
851         'page_title':user_view.page_title,\r
852         'view_user':user,\r
853         'notificatons_on': notificatons_on,\r
854         'form':form,\r
855     }, context_instance=RequestContext(request))\r
856 \r
857 class UserView:\r
858     def __init__(self, id, tab_title, tab_description, page_title, view_func, template_file, data_size=0):\r
859         self.id = id\r
860         self.tab_title = tab_title\r
861         self.tab_description = tab_description\r
862         self.page_title = page_title\r
863         self.view_func = view_func \r
864         self.template_file = template_file\r
865         self.data_size = data_size\r
866         \r
867 USER_TEMPLATE_VIEWS = (\r
868     UserView(\r
869         id = 'stats',\r
870         tab_title = _('overview'),\r
871         tab_description = _('user profile'),\r
872         page_title = _('user profile overview'),\r
873         view_func = user_stats,\r
874         template_file = 'user_stats.html'\r
875     ),\r
876     UserView(\r
877         id = 'recent',\r
878         tab_title = _('recent activity'),\r
879         tab_description = _('recent user activity'),\r
880         page_title = _('profile - recent activity'),\r
881         view_func = user_recent,\r
882         template_file = 'user_recent.html',\r
883         data_size = 50\r
884     ),\r
885     UserView(\r
886         id = 'responses',\r
887         tab_title = _('responses'),\r
888         tab_description = _('comments and answers to others questions'),\r
889         page_title = _('profile - responses'),\r
890         view_func = user_responses,\r
891         template_file = 'user_responses.html',\r
892         data_size = 50\r
893     ),\r
894     UserView(\r
895         id = 'reputation',\r
896         tab_title = _('reputation'),\r
897         tab_description = _('user reputation in the community'),\r
898         page_title = _('profile - user reputation'),\r
899         view_func = user_reputation,\r
900         template_file = 'user_reputation.html'\r
901     ),\r
902     UserView(\r
903         id = 'favorites',\r
904         tab_title = _('favorite questions'),\r
905         tab_description = _('users favorite questions'),\r
906         page_title = _('profile - favorite questions'),\r
907         view_func = user_favorites,\r
908         template_file = 'user_favorites.html',\r
909         data_size = 50\r
910     ),\r
911     UserView(\r
912         id = 'votes',\r
913         tab_title = _('casted votes'),\r
914         tab_description = _('user vote record'),\r
915         page_title = _('profile - votes'),\r
916         view_func = user_votes,\r
917         template_file = 'user_votes.html',\r
918         data_size = 50\r
919     ),\r
920     UserView(\r
921         id = 'subscriptions',\r
922         tab_title = _('subscriptions'),\r
923         tab_description = _('subscription settings'),\r
924         page_title = _('profile - subscriptions'),\r
925         view_func = user_subscription_settings,\r
926         template_file = 'user_subscriptions.html'\r
927     )\r
928 )\r
929 \r
930 def user(request, id, slug=None):\r
931     sort = request.GET.get('sort', 'stats')\r
932     user_view = dict((v.id, v) for v in USER_TEMPLATE_VIEWS).get(sort, USER_TEMPLATE_VIEWS[0])\r
933     from forum.views import users\r
934     func = user_view.view_func\r
935     return func(request, id, user_view)\r
936 \r
937 @login_required\r
938 def account_settings(request):\r
939     """\r
940     index pages to changes some basic account settings :\r
941      - change password\r
942      - change email\r
943      - associate a new openid\r
944      - delete account\r
945 \r
946     url : /\r
947 \r
948     template : authopenid/settings.html\r
949     """\r
950     logging.debug('')\r
951     msg = request.GET.get('msg', '')\r
952     is_openid = False\r
953 \r
954     return render_to_response('account_settings.html', {\r
955         'msg': msg,\r
956         'is_openid': is_openid\r
957         }, context_instance=RequestContext(request))\r
958 \r