summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTomasz Zielinski <tomasz.zielinski@pyconsultant.eu>2011-12-29 14:17:37 +0100
committerTomasz Zielinski <tomasz.zielinski@pyconsultant.eu>2011-12-29 14:17:37 +0100
commit9e6221283bde3f3d4b4115cd725fb4145996d53c (patch)
tree2b59c6bbd444f5798b821c971f0f8a5ade65c632
parent7b14a2037436b24da70203fac3ee3ee1e48b114b (diff)
downloadaskbot-9e6221283bde3f3d4b4115cd725fb4145996d53c.tar.gz
askbot-9e6221283bde3f3d4b4115cd725fb4145996d53c.tar.bz2
askbot-9e6221283bde3f3d4b4115cd725fb4145996d53c.zip
Further Users views migration; cleanup before major migration to Post
-rw-r--r--askbot/models/__init__.py14
-rw-r--r--askbot/models/base.py31
-rw-r--r--askbot/models/meta.py21
-rw-r--r--askbot/models/question.py2
-rw-r--r--askbot/models/tag.py7
-rw-r--r--askbot/skins/default/templates/user_profile/user_recent.html34
-rw-r--r--askbot/skins/default/templates/user_profile/user_stats.html2
-rw-r--r--askbot/tests/misc_tests.py47
-rw-r--r--askbot/views/commands.py116
-rw-r--r--askbot/views/users.py543
10 files changed, 265 insertions, 552 deletions
diff --git a/askbot/models/__init__.py b/askbot/models/__init__.py
index 7d251815..7fff58fd 100644
--- a/askbot/models/__init__.py
+++ b/askbot/models/__init__.py
@@ -312,7 +312,7 @@ def _assert_user_can(
raise django_exceptions.PermissionDenied(error_message)
def user_assert_can_unaccept_best_answer(self, answer = None):
- assert(isinstance(answer, Answer))
+ assert getattr(answer, 'post_type', '') == 'answer'
blocked_error_message = _(
'Sorry, you cannot accept or unaccept best answers '
'because your account is blocked'
@@ -368,7 +368,7 @@ def user_assert_can_unaccept_best_answer(self, answer = None):
raise django_exceptions.PermissionDenied(error_message)
def user_assert_can_accept_best_answer(self, answer = None):
- assert(isinstance(answer, Answer))
+ assert getattr(answer, 'post_type', '') == 'answer'
self.assert_can_unaccept_best_answer(answer)
def user_assert_can_vote_for_post(
@@ -601,12 +601,12 @@ def user_assert_can_edit_post(self, post = None):
def user_assert_can_edit_question(self, question = None):
- assert isinstance(question, Post) and question.post_type=='question'
+ assert getattr(question, 'post_type', '') == 'question'
self.assert_can_edit_post(question)
def user_assert_can_edit_answer(self, answer = None):
- assert isinstance(answer, Post) and answer.post_type=='answer'
+ assert getattr(answer, 'post_type', '') == 'answer'
self.assert_can_edit_post(answer)
@@ -953,10 +953,12 @@ def user_post_comment(
comment = body_text,
added_at = timestamp,
)
+ if hasattr(comment, 'self_comment'): # Handle Post-s
+ comment = comment.self_comment
award_badges_signal.send(None,
event = 'post_comment',
actor = self,
- context_object = comment.self_comment,
+ context_object = comment,
timestamp = timestamp
)
return comment
@@ -1407,7 +1409,7 @@ def user_post_answer(
self.assert_can_post_answer()
- if not isinstance(question, Post) or not question.post_type == 'question':
+ if getattr(question, 'post_type', '') != 'question':
raise TypeError('question argument must be provided')
if body_text is None:
raise ValueError('Body text is required to post answer')
diff --git a/askbot/models/base.py b/askbot/models/base.py
index 5ac2ac7a..121b0182 100644
--- a/askbot/models/base.py
+++ b/askbot/models/base.py
@@ -5,8 +5,6 @@ import logging
from django.db import models
from django.utils.html import strip_tags
from django.contrib.auth.models import User
-from django.contrib.contenttypes import generic
-from django.contrib.contenttypes.models import ContentType
from django.contrib.sitemaps import ping_google
#todo: maybe merge askbot.utils.markup and forum.utils.html
@@ -188,35 +186,6 @@ class BaseQuerySetManager(models.Manager):
except AttributeError:
return getattr(self.get_query_set(), attr, *args)
-class UserContent(models.Model):
- user = models.ForeignKey(User, related_name='%(class)ss')
-
- class Meta:
- abstract = True
- app_label = 'askbot'
-
-
-class MetaContent(models.Model):
- """
- Base class for Vote and Comment
- """
- content_type = models.ForeignKey(ContentType)
- object_id = models.PositiveIntegerField()
- content_object = generic.GenericForeignKey('content_type', 'object_id')
-
- class Meta:
- abstract = True
- app_label = 'askbot'
-
-class DeletableContent(models.Model):
- deleted = models.BooleanField(default=False)
- deleted_at = models.DateTimeField(null=True, blank=True)
- deleted_by = models.ForeignKey(User, null=True, blank=True, related_name='deleted_%(class)ss')
-
- class Meta:
- abstract = True
- app_label = 'askbot'
-
class AnonymousContent(models.Model):
"""
diff --git a/askbot/models/meta.py b/askbot/models/meta.py
index 0a4fb349..6fc1e70d 100644
--- a/askbot/models/meta.py
+++ b/askbot/models/meta.py
@@ -1,4 +1,5 @@
import datetime
+from django.contrib.contenttypes import generic
from django.contrib.contenttypes.models import ContentType
from django.db import models
from django.utils import html as html_utils
@@ -29,21 +30,26 @@ class VoteManager(models.Manager):
return 0
-class Vote(base.MetaContent, base.UserContent):
+class Vote(base.UserContent):
VOTE_UP = +1
VOTE_DOWN = -1
VOTE_CHOICES = (
(VOTE_UP, u'Up'),
(VOTE_DOWN, u'Down'),
)
+ user = models.ForeignKey('auth.User', related_name='votes')
+ content_type = models.ForeignKey(ContentType)
+ object_id = models.PositiveIntegerField()
+ content_object = generic.GenericForeignKey('content_type', 'object_id')
vote = models.SmallIntegerField(choices=VOTE_CHOICES)
voted_at = models.DateTimeField(default=datetime.datetime.now)
objects = VoteManager()
- class Meta(base.MetaContent.Meta):
+ class Meta:
unique_together = ('content_type', 'object_id', 'user')
+ app_label = 'askbot'
db_table = u'vote'
def __unicode__(self):
@@ -86,7 +92,7 @@ class Vote(base.MetaContent, base.UserContent):
#todo: move this class to content
-class Comment(base.MetaContent, base.UserContent):
+class Comment(base.UserContent):
post_type = 'comment'
comment = models.CharField(max_length = const.COMMENT_HARD_MAX_LENGTH)
added_at = models.DateTimeField(default = datetime.datetime.now)
@@ -94,13 +100,20 @@ class Comment(base.MetaContent, base.UserContent):
score = models.IntegerField(default = 0)
offensive_flag_count = models.IntegerField(default = 0)
+ user = models.ForeignKey('auth.User', related_name='comments')
+
+ content_type = models.ForeignKey(ContentType)
+ object_id = models.PositiveIntegerField()
+ content_object = generic.GenericForeignKey('content_type', 'object_id')
+
_urlize = True
_use_markdown = True
_escape_html = True
is_anonymous = False #comments are never anonymous - may change
- class Meta(base.MetaContent.Meta):
+ class Meta:
ordering = ('-added_at',)
+ app_label = 'askbot'
db_table = u'comment'
#these two are methods
diff --git a/askbot/models/question.py b/askbot/models/question.py
index d0a30fcc..e9b732f6 100644
--- a/askbot/models/question.py
+++ b/askbot/models/question.py
@@ -919,7 +919,7 @@ class QuestionView(models.Model):
class FavoriteQuestion(models.Model):
"""A favorite Question of a User."""
thread = models.ForeignKey(Thread)
- user = models.ForeignKey(User, related_name='unused_user_favorite_questions')
+ user = models.ForeignKey(User, related_name='user_favorite_questions')
added_at = models.DateTimeField(default=datetime.datetime.now)
class Meta:
diff --git a/askbot/models/tag.py b/askbot/models/tag.py
index 7bd49d12..349b409b 100644
--- a/askbot/models/tag.py
+++ b/askbot/models/tag.py
@@ -124,9 +124,14 @@ class Tag(DeletableContent):
# Denormalised data
used_count = models.PositiveIntegerField(default=0)
+ deleted = models.BooleanField(default=False)
+ deleted_at = models.DateTimeField(null=True, blank=True)
+ deleted_by = models.ForeignKey(User, null=True, blank=True, related_name='deleted_tags')
+
objects = TagManager()
- class Meta(DeletableContent.Meta):
+ class Meta:
+ app_label = 'askbot'
db_table = u'tag'
ordering = ('-used_count', 'name')
diff --git a/askbot/skins/default/templates/user_profile/user_recent.html b/askbot/skins/default/templates/user_profile/user_recent.html
index 84d10357..09689419 100644
--- a/askbot/skins/default/templates/user_profile/user_recent.html
+++ b/askbot/skins/default/templates/user_profile/user_recent.html
@@ -13,25 +13,23 @@
</div>
<div style="float:left;overflow:hidden;">
{% if act.is_badge %}
- <a href="{{act.badge.get_absolute_url()}}" title="{{ act.badge.get_type_display() }} : {% trans description=act.badge.description %}{{description}}{% endtrans %}" class="medal"><span class="{{ act.badge.css_class }}">&#9679;</span>&nbsp;{% trans name=act.badge.name %}{{name}}{% endtrans %}</a>
- {% if act.related_object_type == 'question' %}{# question #}
- {% for question in questions %}{# could also create a new dict #}
- {% if question.question_id == act.obj %}
- (<a title="{{question.summary|collapse}}"
- href="{% url question question.question_id %}{{question.thread.title|slugify}}">{% trans %}source{% endtrans %}</a>)
- {% endif %}
- {% endfor %}
- {% elif act.related_object_type == 'answer' %}{# answer #}
- {% for answer in answers %}{# could also create a new dict #}
- {% if answer.answer_id == act.obj %}
- (<a title="{{answer.text|collapse}}"
- href="{% url question answer.question_id %}{{answer.question_title|slugify}}#{{answer.answer_id}}">{% trans %}source{% endtrans %}</a>)
- {% endif %}
- {% endfor %}
- {% endif %}
+ <a href="{{act.badge.get_absolute_url()}}"
+ title="{{ act.badge.get_type_display() }} : {% trans description=act.badge.description %}{{description}}{% endtrans %}"
+ class="medal">
+ <span class="{{ act.badge.css_class }}">&#9679;</span>&nbsp;{% trans name=act.badge.name %}{{name}}{% endtrans %}
+ </a>
+ {% if act.content_object.post_type == 'question' %}
+ {% set question=act.content_object %}
+ (<a title="{{question.summary|collapse}}"
+ href="{% url question question.id %}{{question.thread.title|slugify}}">{% trans %}source{% endtrans %}</a>)
+ {% elif act.content_object.post_type == 'answer' %}
+ {% set answer=act.content_object %}
+ (<a title="{{answer.text|collapse}}"
+ href="{% url question answer.question_id %}{{answer.question.thread.title|slugify}}#{{answer.id}}">{% trans %}source{% endtrans %}</a>)
+ {% endif %}
{% else %}
- <span class="post-type-{{ act.type_id }}"><a href="{{ act.title_link }}">{{ act.title|escape }}</a></span>
- {% if act.summary %}<span class="revision-summary">{{ act.summary|escape }}</span>{% endif %}
+ <span class="post-type-{{ act.type_id }}"><a href="{{ act.title_link }}">{{ act.title|escape }}</a></span>
+ {% if act.summary %}<span class="revision-summary">{{ act.summary|escape }}</span>{% endif %}
{% endif %}
<div style="height:5px"></div>
</div>
diff --git a/askbot/skins/default/templates/user_profile/user_stats.html b/askbot/skins/default/templates/user_profile/user_stats.html
index 0691dbad..95619560 100644
--- a/askbot/skins/default/templates/user_profile/user_stats.html
+++ b/askbot/skins/default/templates/user_profile/user_stats.html
@@ -114,7 +114,7 @@
</span>
<ul id="badge-context-{{ badge.id }}" class="badge-context-list" style="display:none">
{% for award in badge_user_awards %}
- {% if award.content_object %}
+ {% if award.content_object_is_post %}
<li>
<a
title="{{ award.content_object.get_snippet()|collapse }}"
diff --git a/askbot/tests/misc_tests.py b/askbot/tests/misc_tests.py
index 306d62ce..3150c377 100644
--- a/askbot/tests/misc_tests.py
+++ b/askbot/tests/misc_tests.py
@@ -1,12 +1,4 @@
-import datetime
-from django.contrib.contenttypes.models import ContentType
-from django.test.client import Client
from askbot.tests.utils import AskbotTestCase
-from askbot.conf import settings
-from askbot import models
-from askbot.models.badges import award_badges_signal
-
-from askbot.views.users import get_related_object_type_name
from askbot.models.post import PostRevision
class MiscTests(AskbotTestCase):
@@ -16,45 +8,6 @@ class MiscTests(AskbotTestCase):
self.u2 = self.create_user(username='user2')
self.u3 = self.create_user(username='user3')
- def test_get_related_object_type_name_for_question(self):
- question = self.post_question(user=self.u1)
- #import ipdb; ipdb.set_trace()
- ct = ContentType.objects.get_for_model(question)
- self.assertEqual('question', get_related_object_type_name(ct.id, question.id))
-
- def test_get_related_object_type_name_for_question_revision(self):
- question = self.post_question(user=self.u1)
- revision = question.revisions.all()[0]
- ct = ContentType.objects.get_for_model(revision)
- self.assertEqual('question', get_related_object_type_name(ct.id, revision.id))
-
- def test_get_related_object_type_name_for_answer(self):
- question = self.post_question(user=self.u1)
- answer = self.post_answer(user=self.u1, question=question)
- ct = ContentType.objects.get_for_model(answer)
- self.assertEqual('answer', get_related_object_type_name(ct.id, answer.id))
-
- def test_get_related_object_type_name_for_answer_revision(self):
- question = self.post_question(user=self.u1)
- answer = self.post_answer(user=self.u1, question=question)
- revision = answer.revisions.all()[0]
- ct = ContentType.objects.get_for_model(revision)
- self.assertEqual('answer', get_related_object_type_name(ct.id, revision.id))
-
- def test_get_related_object_type_name_for_anything_else_1(self):
- ct = ContentType.objects.get_for_model(self.u2)
- self.assertTrue(
- get_related_object_type_name(ct.id, self.u2.id) is None
- )
-
- def test_get_related_object_type_name_for_anything_else_2(self):
- question = self.post_question(user=self.u1)
- comment = self.post_comment(user=self.u1, parent_post=question)
- ct = ContentType.objects.get_for_model(comment)
- self.assertTrue(
- get_related_object_type_name(ct.id, comment.id) is None
- )
-
def test_proper_PostRevision_manager_is_used(self):
"Makes sure that both normal and related managers for PostRevision don't implement .create() method"
question = self.post_question(user=self.u1)
diff --git a/askbot/views/commands.py b/askbot/views/commands.py
index 2ef56731..e0e83209 100644
--- a/askbot/views/commands.py
+++ b/askbot/views/commands.py
@@ -25,6 +25,65 @@ from askbot.skins.loaders import render_into_skin
from askbot import const
import logging
+
+def manage_inbox(request):
+ """delete, mark as new or seen user's
+ response memo objects, excluding flags
+ request data is memo_list - list of integer id's of the ActivityAuditStatus items
+ and action_type - string - one of delete|mark_new|mark_seen
+ """
+
+ response_data = dict()
+ try:
+ if request.is_ajax():
+ if request.method == 'POST':
+ post_data = simplejson.loads(request.raw_post_data)
+ if request.user.is_authenticated():
+ activity_types = const.RESPONSE_ACTIVITY_TYPES_FOR_DISPLAY
+ activity_types += (const.TYPE_ACTIVITY_MENTION, )
+ user = request.user
+ memo_set = models.ActivityAuditStatus.objects.filter(
+ id__in = post_data['memo_list'],
+ activity__activity_type__in = activity_types,
+ user = user
+ )
+
+ action_type = post_data['action_type']
+ if action_type == 'delete':
+ memo_set.delete()
+ elif action_type == 'mark_new':
+ memo_set.update(status = models.ActivityAuditStatus.STATUS_NEW)
+ elif action_type == 'mark_seen':
+ memo_set.update(status = models.ActivityAuditStatus.STATUS_SEEN)
+ else:
+ raise exceptions.PermissionDenied(
+ _('Oops, apologies - there was some error')
+ )
+
+ user.update_response_counts()
+
+ response_data['success'] = True
+ data = simplejson.dumps(response_data)
+ return HttpResponse(data, mimetype="application/json")
+ else:
+ raise exceptions.PermissionDenied(
+ _('Sorry, but anonymous users cannot access the inbox')
+ )
+ else:
+ raise exceptions.PermissionDenied('must use POST request')
+ else:
+ #todo: show error page but no-one is likely to get here
+ return HttpResponseRedirect(reverse('index'))
+ except Exception, e:
+ message = unicode(e)
+ if message == '':
+ message = _('Oops, apologies - there was some error')
+ response_data['message'] = message
+ response_data['success'] = False
+ data = simplejson.dumps(response_data)
+ return HttpResponse(data, mimetype="application/json")
+
+
def process_vote(user = None, vote_direction = None, post = None):
"""function (non-view) that actually processes user votes
- i.e. up- or down- votes
@@ -78,63 +137,6 @@ def process_vote(user = None, vote_direction = None, post = None):
return response_data
-def manage_inbox(request):
- """delete, mark as new or seen user's
- response memo objects, excluding flags
- request data is memo_list - list of integer id's of the ActivityAuditStatus items
- and action_type - string - one of delete|mark_new|mark_seen
- """
-
- response_data = dict()
- try:
- if request.is_ajax():
- if request.method == 'POST':
- post_data = simplejson.loads(request.raw_post_data)
- if request.user.is_authenticated():
- activity_types = const.RESPONSE_ACTIVITY_TYPES_FOR_DISPLAY
- activity_types += (const.TYPE_ACTIVITY_MENTION, )
- user = request.user
- memo_set = models.ActivityAuditStatus.objects.filter(
- id__in = post_data['memo_list'],
- activity__activity_type__in = activity_types,
- user = user
- )
-
- action_type = post_data['action_type']
- if action_type == 'delete':
- memo_set.delete()
- elif action_type == 'mark_new':
- memo_set.update(status = models.ActivityAuditStatus.STATUS_NEW)
- elif action_type == 'mark_seen':
- memo_set.update(status = models.ActivityAuditStatus.STATUS_SEEN)
- else:
- raise exceptions.PermissionDenied(
- _('Oops, apologies - there was some error')
- )
-
- user.update_response_counts()
-
- response_data['success'] = True
- data = simplejson.dumps(response_data)
- return HttpResponse(data, mimetype="application/json")
- else:
- raise exceptions.PermissionDenied(
- _('Sorry, but anonymous users cannot access the inbox')
- )
- else:
- raise exceptions.PermissionDenied('must use POST request')
- else:
- #todo: show error page but no-one is likely to get here
- return HttpResponseRedirect(reverse('index'))
- except Exception, e:
- message = unicode(e)
- if message == '':
- message = _('Oops, apologies - there was some error')
- response_data['message'] = message
- response_data['success'] = False
- data = simplejson.dumps(response_data)
- return HttpResponse(data, mimetype="application/json")
-
def vote(request, id):
"""
diff --git a/askbot/views/users.py b/askbot/views/users.py
index a0a16028..64a0d829 100644
--- a/askbot/views/users.py
+++ b/askbot/views/users.py
@@ -7,9 +7,11 @@ and other views showing profile-related information.
Also this module includes the view listing all forum users.
"""
import calendar
+import collections
import functools
import datetime
import logging
+import operator
from django.db.models import Count, Q
from django.conf import settings as django_settings
@@ -37,18 +39,6 @@ from askbot.skins.loaders import render_into_skin
from askbot.templatetags import extra_tags
-#todo: queries in the user activity summary view must be redone
-def get_related_object_type_name(content_type_id, object_id):
- if content_type_id == ContentType.objects.get_for_model(models.Question).id:
- return 'question'
- elif content_type_id == ContentType.objects.get_for_model(models.Answer).id:
- return 'answer'
- elif content_type_id == ContentType.objects.get_for_model(models.PostRevision).id:
- post_revision = models.PostRevision.objects.get(id=object_id)
- return post_revision.revision_type_str()
-
- return None
-
def owner_or_moderator_required(f):
@functools.wraps(f)
def wrapped_func(request, profile_owner, context):
@@ -317,15 +307,14 @@ def user_stats(request, user, context):
#
# INFO: There's bug in Django that makes the following query kind of broken (GROUP BY clause is problematic):
# http://stackoverflow.com/questions/7973461/django-aggregation-does-excessive-group-by-clauses
- # Fortunately it looks to return correct results for the test data
+ # Fortunately it looks like it returns correct results for the test data
user_tags = models.Tag.objects.filter(threads__posts__author=user).\
annotate(user_tag_usage_count=Count('threads')).\
order_by('-user_tag_usage_count')[:const.USER_VIEW_DATA_SIZE]
user_tags = list(user_tags) # evaluate
-
#
- # Badges/Awards (TODO: refactor into Managers/QuerySets when a pattern emerges; Simplify when we get rid of Queastion&Answer models)
+ # Badges/Awards (TODO: refactor into Managers/QuerySets when a pattern emerges; Simplify when we get rid of Question&Answer models)
#
question_type = ContentType.objects.get_for_model(models.Question)
answer_type = ContentType.objects.get_for_model(models.Answer)
@@ -351,27 +340,24 @@ def user_stats(request, user, context):
elif post.self_answer_id:
awarded_answers_map[post.self_answer_id] = post
- badges_dict = {}
+ badges_dict = collections.defaultdict(list)
for award in user_awards:
# Fetch content object
if award.content_type_id == question_type.id:
award.content_object = awarded_questions_map[award.object_id]
+ award.content_object_is_post = True
elif award.content_type_id == answer_type.id:
award.content_object = awarded_answers_map[award.object_id]
+ award.content_object_is_post = True
else:
- award.content_object = None
+ award.content_object_is_post = False
# "Assign" to its Badge
- if award not in badges_dict:
- badges_dict[award.badge] = [award]
- else:
- badges_dict[award.badge].append(award)
-
- badges = list(badges_dict.items())
- badges.sort(key=lambda badge_tuple: len(badge_tuple[1]), reverse=True)
+ badges_dict[award.badge].append(award)
- total_badges = len(badges)
+ badges = badges_dict.items()
+ badges.sort(key=operator.itemgetter(1), reverse=True)
data = {
'active_tab':'users',
@@ -398,7 +384,7 @@ def user_stats(request, user, context):
'user_tags' : user_tags,
'badges': badges,
- 'total_badges' : total_badges,
+ 'total_badges' : len(badges),
}
context.update(data)
@@ -411,7 +397,7 @@ def user_recent(request, user, context):
if type_id in item:
return item[1]
- class Event:
+ class Event(object):
is_badge = False
def __init__(self, time, type, title, summary, answer_id, question_id):
self.time = time
@@ -427,271 +413,121 @@ def user_recent(request, user, context):
if int(answer_id) > 0:
self.title_link += '#%s' % answer_id
- class AwardEvent:
+ class AwardEvent(object):
is_badge = True
- def __init__(self, time, obj, cont, type, id, related_object_type = None):
+ def __init__(self, time, type, content_object, badge):
self.time = time
- self.obj = obj
- self.cont = cont
self.type = get_type_name(type)
- self.type_id = type
- self.badge = get_object_or_404(models.BadgeData, id=id)
- self.related_object_type = related_object_type
+ self.content_object = content_object
+ self.badge = badge
activities = []
- # ask questions
- questions = models.Activity.objects.extra(
- select={
- 'title' : 'askbot_thread.title',
- 'question_id' : 'question.id',
- 'summary' : 'question.summary',
- 'active_at' : 'activity.active_at',
- 'activity_type' : 'activity.activity_type'
- },
- tables=['activity', 'question', 'askbot_thread'],
- where=['activity.content_type_id = %s AND activity.object_id = question.id AND askbot_thread.id = question.thread_id AND ' +
- 'activity.user_id = %s AND activity.activity_type = %s AND NOT question.deleted'],
- params=[ContentType.objects.get_for_model(models.Question).id, user.id, const.TYPE_ACTIVITY_ASK_QUESTION],
- order_by=['-activity.active_at']
- ).values(
- 'title',
- 'question_id',
- 'summary',
- 'active_at',
- 'activity_type'
- )
-
- for q in questions:
- q_event = Event(
- q['active_at'],
- q['activity_type'],
- q['title'],
- '',
- '0',
- q['question_id']
- )
- activities.append(q_event)
-
- # answers
- answers = models.Activity.objects.extra(
- select={
- 'title' : 'askbot_thread.title',
- 'question_id' : 'question.id',
- 'summary' : 'question.summary',
- 'answer_id' : 'answer.id',
- 'active_at' : 'activity.active_at',
- 'activity_type' : 'activity.activity_type'
- },
- tables=['activity', 'answer', 'question', 'askbot_thread'],
- where=['activity.content_type_id = %s AND activity.object_id = answer.id AND ' +
- 'answer.question_id=question.id AND askbot_thread.id=question.thread_id AND NOT answer.deleted AND activity.user_id=%s AND '+
- 'activity.activity_type=%s AND NOT question.deleted'],
- params=[ContentType.objects.get_for_model(models.Answer).id, user.id, const.TYPE_ACTIVITY_ANSWER],
- order_by=['-activity.active_at']
- ).values(
- 'title',
- 'question_id',
- 'summary',
- 'answer_id',
- 'active_at',
- 'activity_type'
- )
- if len(answers) > 0:
- answer_activities = [(Event(q['active_at'], q['activity_type'], q['title'], '', q['answer_id'], \
- q['question_id'])) for q in answers]
- activities.extend(answer_activities)
-
- # question comments
- comments = models.Activity.objects.extra(
- select={
- 'title' : 'askbot_thread.title',
- 'question_id' : 'comment.object_id',
- 'added_at' : 'comment.added_at',
- 'activity_type' : 'activity.activity_type'
- },
- tables=['activity', 'question', 'comment', 'askbot_thread'],
-
- 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 askbot_thread.id=question.thread_id AND '+
- 'comment.content_type_id=%s AND activity.user_id = %s AND activity.activity_type=%s AND ' +
- 'NOT question.deleted'],
- params=[ContentType.objects.get_for_model(models.Comment).id, ContentType.objects.get_for_model(models.Question).id, user.id, const.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', \
- q['question_id'])) for q in comments]
- activities.extend(comments)
-
- # answer comments
- comments = models.Activity.objects.extra(
- select={
- 'title' : 'askbot_thread.title',
- 'question_id' : 'question.id',
- 'answer_id' : 'answer.id',
- 'added_at' : 'comment.added_at',
- 'activity_type' : 'activity.activity_type'
- },
- tables=['activity', 'question', 'answer', 'comment', 'askbot_thread'],
-
- 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 askbot_thread.id=question.thread_id AND '+
- 'activity.user_id = %s AND activity.activity_type=%s AND '+
- 'NOT answer.deleted AND NOT question.deleted'],
- params=[ContentType.objects.get_for_model(models.Comment).id, ContentType.objects.get_for_model(models.Answer).id, user.id, const.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'], \
- q['question_id'])) for q in comments]
- activities.extend(comments)
-
- # question revisions
- revisions = models.Activity.objects.extra(
- select={
- 'title' : 'askbot_postrevision.title',
- 'question_id' : 'askbot_postrevision.question_id',
- 'added_at' : 'activity.active_at',
- 'activity_type' : 'activity.activity_type',
- 'summary' : 'askbot_postrevision.summary'
- },
- tables=['activity', 'askbot_postrevision', 'question'],
- where=['''
- activity.content_type_id=%s AND activity.object_id=askbot_postrevision.id AND
- askbot_postrevision.question_id=question.id AND askbot_postrevision.revision_type=%s AND NOT question.deleted AND
- activity.user_id=askbot_postrevision.author_id AND activity.user_id=%s AND
- activity.activity_type=%s
- '''],
- params=[ContentType.objects.get_for_model(models.PostRevision).id, models.PostRevision.QUESTION_REVISION, user.id, const.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', \
- q['question_id'])) for q in revisions]
- activities.extend(revisions)
-
- # answer revisions
- revisions = models.Activity.objects.extra(
- select={
- 'title' : 'askbot_thread.title',
- 'question_id' : 'question.id',
- 'answer_id' : 'answer.id',
- 'added_at' : 'activity.active_at',
- 'activity_type' : 'activity.activity_type',
- 'summary' : 'askbot_postrevision.summary'
- },
- tables=['activity', 'askbot_postrevision', 'question', 'answer', 'askbot_thread'],
- where=['''
- activity.content_type_id=%s AND activity.object_id=askbot_postrevision.id AND
- askbot_postrevision.answer_id=answer.id AND askbot_postrevision.revision_type=%s AND
- answer.question_id=question.id AND askbot_thread.id=question.thread_id AND NOT question.deleted AND NOT answer.deleted AND
- activity.user_id=askbot_postrevision.author_id AND activity.user_id=%s AND
- activity.activity_type=%s
- '''],
- params=[ContentType.objects.get_for_model(models.PostRevision).id, models.PostRevision.ANSWER_REVISION, user.id, const.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'], \
- q['answer_id'], q['question_id'])) for q in revisions]
- activities.extend(revisions)
-
- # accepted answers
- accept_answers = models.Activity.objects.extra(
- select={
- 'title' : 'askbot_thread.title',
- 'question_id' : 'question.id',
- 'added_at' : 'activity.active_at',
- 'activity_type' : 'activity.activity_type',
- },
- tables=['activity', 'answer', 'question', 'askbot_thread'],
- 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 '+
- 'NOT answer.deleted AND NOT question.deleted AND '+
- 'answer.question_id=question.id AND askbot_thread.id=question.thread_id AND activity.activity_type=%s'],
- params=[ContentType.objects.get_for_model(models.Answer).id, user.id, const.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]
- activities.extend(accept_answers)
- #award history
- awards = models.Activity.objects.extra(
- select={
- 'badge_id' : 'askbot_badgedata.id',
- 'awarded_at': 'award.awarded_at',
- 'object_id': 'award.object_id',
- 'content_type_id': 'award.content_type_id',
- 'activity_type' : 'activity.activity_type'
- },
- tables=['activity', 'award', 'askbot_badgedata'],
- where=['activity.user_id = award.user_id AND activity.user_id = %s AND '+
- 'award.badge_id=askbot_badgedata.id AND activity.object_id=award.id AND activity.activity_type=%s'],
- params=[user.id, const.TYPE_ACTIVITY_PRIZE],
- order_by=['-activity.active_at']
- ).values(
- 'badge_id',
- 'awarded_at',
- 'object_id',
- 'content_type_id',
- 'activity_type'
- )
- for award in awards:
- related_object_type = get_related_object_type_name(
- content_type_id=award['content_type_id'],
- object_id=award['object_id']
- )
- activities.append(
- AwardEvent(
- award['awarded_at'],
- award['object_id'],
- award['content_type_id'],
- award['activity_type'],
- award['badge_id'],
- related_object_type = related_object_type
- )
- )
-
- activities.sort(lambda x,y: cmp(y.time, x.time))
+
+ # TODO: Convert to Post
+
+ for activity in models.Activity.objects.filter(user=user):
+
+ # TODO: multi-if means that we have here a construct for which a design pattern should be used
+
+ # ask questions
+ if activity.activity_type == const.TYPE_ACTIVITY_ASK_QUESTION:
+ q = activity.content_object
+ if q.deleted:
+ activities.append(Event(
+ time=activity.active_at,
+ type=activity.activity_type,
+ title=q.thread.title,
+ summary=q.summary, # TODO: was set to '' before, but that was probably wrong
+ answer_id=0,
+ question_id=q.id
+ ))
+
+ elif activity.activity_type == const.TYPE_ACTIVITY_ANSWER:
+ ans = activity.content_object
+ if not ans.deleted and not ans.question.deleted:
+ activities.append(Event(
+ time=activity.active_at,
+ type=activity.activity_type,
+ title=ans.question.thread.title,
+ summary=ans.question.summary,
+ answer_id=ans.id,
+ question_id=ans.question.id
+ ))
+
+ elif activity.activity_type == const.TYPE_ACTIVITY_COMMENT_QUESTION:
+ cm = activity.content_object
+ q = cm.content_object
+ if not q.deleted:
+ activities.append(Event(
+ time=cm.added_at,
+ type=activity.activity_type,
+ title=q.thread.title,
+ summary='',
+ answer_id=0,
+ question_id=q.id
+ ))
+
+ elif activity.activity_type == const.TYPE_ACTIVITY_COMMENT_ANSWER:
+ cm = activity.content_object
+ ans = cm.content_object
+ if not ans.deleted and not ans.question.deleted:
+ activities.append(Event(
+ time=cm.added_at,
+ type=activity.activity_type,
+ title=ans.question.thread.title,
+ summary='',
+ answer_id=ans.id,
+ question_id=ans.question.id
+ ))
+
+ elif activity.activity_type == const.TYPE_ACTIVITY_UPDATE_QUESTION:
+ q = activity.content_object
+ if not q.deleted:
+ activities.append(Event(
+ time=activity.active_at,
+ type=activity.activity_type,
+ title=q.thread.title,
+ summary=q.summary,
+ answer_id=0,
+ question_id=q.id
+ ))
+
+ elif activity.activity_type == const.TYPE_ACTIVITY_UPDATE_ANSWER:
+ ans = activity.content_object
+ if not ans.deleted and not ans.question.deleted:
+ activities.append(Event(
+ time=activity.active_at,
+ type=activity.activity_type,
+ title=ans.question.thread.title,
+ summary=ans.summary,
+ answer_id=ans.id,
+ question_id=ans.question.id
+ ))
+
+ elif activity.activity_type == const.TYPE_ACTIVITY_MARK_ANSWER:
+ ans = activity.content_object
+ if not ans.deleted and not ans.question.deleted:
+ activities.append(Event(
+ time=activity.active_at,
+ type=activity.activity_type,
+ title=ans.question.thread.title,
+ summary='',
+ answer_id=0,
+ question_id=ans.question.id
+ ))
+
+ elif activity.activity_type == const.TYPE_ACTIVITY_PRIZE:
+ award = activity.content_object
+ activities.append(AwardEvent(
+ time=award.awarded_at,
+ type=activity.activity_type,
+ content_object=award.content_object,
+ badge=award.badge,
+ ))
+
+ activities.sort(key=operator.attrgetter('time'), reverse=True)
data = {
- 'answers': answers,
- 'questions': questions,
'active_tab': 'users',
'page_class': 'user-profile-page',
'tab_name' : 'recent',
@@ -728,12 +564,10 @@ def user_responses(request, user, context):
user = request.user,
activity__activity_type__in = activity_types
).select_related(
- 'activity__active_at',
- 'activity__object_id',
+ 'activity',
'activity__content_type',
- 'activity__question__thread__title',
- 'activity__user__username',
- 'activity__user__id',
+ 'activity__question__thread',
+ 'activity__user',
'activity__user__gravatar',
).order_by(
'-activity__active_at'
@@ -801,57 +635,23 @@ def user_network(request, user, context):
return render_into_skin('user_profile/user_network.html', context, request)
@owner_or_moderator_required
-def user_votes(request, user, context):
-
+def user_votes(request, user, context): # TODO: Convert to Post, but first migrate Vote to using Post
+ all_votes = list(models.Vote.objects.filter(user=user))
votes = []
- question_votes = models.Vote.objects.extra(
- select={
- 'title' : 'askbot_thread.title',
- 'question_id' : 'question.id',
- 'answer_id' : 0,
- 'voted_at' : 'vote.voted_at',
- 'vote' : 'vote',
- },
- select_params=[user.id],
- tables=['vote', 'question', 'auth_user', 'askbot_thread'],
- where=['vote.content_type_id = %s AND vote.user_id = %s AND vote.object_id = question.id AND askbot_thread.id=question.thread_id '+
- 'AND vote.user_id=auth_user.id'],
- params=[ContentType.objects.get_for_model(models.Question).id, user.id],
- order_by=['-vote.id']
- ).values(
- 'title',
- 'question_id',
- 'answer_id',
- 'voted_at',
- 'vote',
- )
- if(len(question_votes) > 0):
- votes.extend(question_votes)
-
- answer_votes = models.Vote.objects.extra(
- select={
- 'title' : 'askbot_thread.title',
- 'question_id' : 'question.id',
- 'answer_id' : 'answer.id',
- 'voted_at' : 'vote.voted_at',
- 'vote' : 'vote',
- },
- select_params=[user.id],
- tables=['vote', 'answer', 'question', 'auth_user', 'askbot_thread'],
- where=['vote.content_type_id = %s AND vote.user_id = %s AND vote.object_id = answer.id '+
- 'AND answer.question_id = question.id AND askbot_thread.id=question.thread_id AND vote.user_id=auth_user.id'],
- params=[ContentType.objects.get_for_model(models.Answer).id, user.id],
- order_by=['-vote.id']
- ).values(
- 'title',
- 'question_id',
- 'answer_id',
- 'voted_at',
- 'vote',
- )
- if(len(answer_votes) > 0):
- votes.extend(answer_votes)
- votes.sort(lambda x,y: cmp(y['voted_at'], x['voted_at']))
+ for vote in all_votes:
+ obj = vote.content_object
+ if isinstance(obj, models.Question):
+ vote.title = obj.thread.title
+ vote.question_id = obj.id
+ vote.answer_id = 0
+ votes.append(vote)
+ elif isinstance(obj, models.Answer):
+ vote.title = obj.question.thread.title
+ vote.question_id = obj.question.id
+ vote.answer_id = obj.id
+ votes.append(vote)
+
+ votes.sort(key=operator.attrgetter('id'), reverse=True)
data = {
'active_tab':'users',
@@ -864,28 +664,14 @@ def user_votes(request, user, context):
context.update(data)
return render_into_skin('user_profile/user_votes.html', context, request)
+
def user_reputation(request, user, context):
- reputes = models.Repute.objects.filter(user=user).order_by('-reputed_at')
- #select_related() adds stuff needed for the query
- reputes = reputes.select_related(
- 'question__thread__title',
- 'question__id',
- 'user__username'
- )
- #prepare data for the graph
- rep_list = []
- #last values go in first
- rep_list.append('[%s,%s]' % (
- calendar.timegm(
- datetime.datetime.now().timetuple()
- ) * 1000,
- user.reputation
- )
- )
- #ret remaining values in
+ reputes = models.Repute.objects.filter(user=user).select_related('question', 'question__thread', 'user').order_by('-reputed_at')
+
+ # prepare data for the graph - last values go in first
+ rep_list = ['[%s,%s]' % (calendar.timegm(datetime.datetime.now().timetuple()) * 1000, user.reputation)]
for rep in reputes:
- dic = '[%s,%s]' % (calendar.timegm(rep.reputed_at.timetuple()) * 1000, rep.reputation)
- rep_list.append(dic)
+ rep_list.append('[%s,%s]' % (calendar.timegm(rep.reputed_at.timetuple()) * 1000, rep.reputation))
reps = ','.join(rep_list)
reps = '[%s]' % reps
@@ -901,22 +687,13 @@ def user_reputation(request, user, context):
context.update(data)
return render_into_skin('user_profile/user_reputation.html', context, request)
+
def user_favorites(request, user, context):
- favorited_thread_id_list= models.FavoriteQuestion.objects.filter(
- user = user
- ).values_list('thread__id', flat=True)
- questions = models.Question.objects.filter(
- thread__id__in=favorited_thread_id_list
- ).order_by(
- '-score', '-thread__last_activity_at'
- ).select_related(
- 'thread__last_activity_by__id',
- 'thread__last_activity_by__username',
- 'thread__last_activity_by__reputation',
- 'thread__last_activity_by__gold',
- 'thread__last_activity_by__silver',
- 'thread__last_activity_by__bronze'
- )[:const.USER_VIEW_DATA_SIZE]
+ favorite_threads = user.user_favorite_questions.values_list('thread', flat=True)
+ questions = models.Post.objects.filter(post_type='question', thread__in=favorite_threads)\
+ .select_related('thread', 'thread__last_activity_by')\
+ .order_by('-score', '-thread__last_activity_at')[:const.USER_VIEW_DATA_SIZE]
+
data = {
'active_tab':'users',
'page_class': 'user-profile-page',
@@ -924,12 +701,11 @@ def user_favorites(request, user, context):
'tab_description' : _('users favorite questions'),
'page_title' : _('profile - favorite questions'),
'questions' : questions,
-# Commented out, doesn't seem to be used
-# 'favorited_myself': favorited_q_id_list,
}
context.update(data)
return render_into_skin('user_profile/user_favorites.html', context, request)
+
@owner_or_moderator_required
@csrf.csrf_protect
def user_email_subscriptions(request, user, context):
@@ -984,7 +760,7 @@ def user_email_subscriptions(request, user, context):
request
)
-user_view_call_table = {
+USER_VIEW_CALL_TABLE = {
'stats': user_stats,
'recent': user_recent,
'inbox': user_responses,
@@ -1006,16 +782,10 @@ def user(request, id, slug=None, tab_name=None):
"""
profile_owner = get_object_or_404(models.User, id = id)
- if tab_name is None:
- #sort CGI parameter tells us which tab in the user
- #profile to show, the default one is 'stats'
+ if not tab_name:
tab_name = request.GET.get('sort', 'stats')
- if tab_name in user_view_call_table:
- #get the actual view function
- user_view_func = user_view_call_table[tab_name]
- else:
- user_view_func = user_stats
+ user_view_func = USER_VIEW_CALL_TABLE.get(tab_name, user_stats)
context = {
'view_user': profile_owner,
@@ -1023,6 +793,7 @@ def user(request, id, slug=None, tab_name=None):
}
return user_view_func(request, profile_owner, context)
+
def update_has_custom_avatar(request):
"""updates current avatar type data for the user
"""