summaryrefslogtreecommitdiffstats
path: root/forum
diff options
context:
space:
mode:
Diffstat (limited to 'forum')
-rw-r--r--forum/const/__init__.py21
-rw-r--r--forum/migrations/0010_add_receiving_user_to_activity_model.py366
-rw-r--r--forum/models/__init__.py167
-rw-r--r--forum/models/base.py13
-rw-r--r--forum/models/meta.py1
-rw-r--r--forum/models/question.py16
-rw-r--r--forum/models/user.py2
-rw-r--r--forum/utils/markup.py2
-rw-r--r--forum/views/users.py1
9 files changed, 551 insertions, 38 deletions
diff --git a/forum/const/__init__.py b/forum/const/__init__.py
index 7ba5be23..5419d70a 100644
--- a/forum/const/__init__.py
+++ b/forum/const/__init__.py
@@ -92,6 +92,7 @@ TYPE_ACTIVITY_UPDATE_TAGS=15
TYPE_ACTIVITY_FAVORITE=16
TYPE_ACTIVITY_USER_FULL_UPDATED = 17
TYPE_ACTIVITY_QUESTION_EMAIL_UPDATE_SENT = 18
+TYPE_ACTIVITY_MENTION = 19
#TYPE_ACTIVITY_EDIT_QUESTION=17
#TYPE_ACTIVITY_EDIT_ANSWER=18
@@ -114,6 +115,26 @@ TYPE_ACTIVITY = (
(TYPE_ACTIVITY_FAVORITE, _('selected favorite')),
(TYPE_ACTIVITY_USER_FULL_UPDATED, _('completed user profile')),
(TYPE_ACTIVITY_QUESTION_EMAIL_UPDATE_SENT, _('email update sent to user')),
+ (TYPE_ACTIVITY_MENTION, _('mentioned in the post')),
+)
+
+#response activity has receiving user not empty
+RESPONSE_ACTIVITY_TYPES = (
+ TYPE_ACTIVITY_ANSWER,
+ TYPE_ACTIVITY_COMMENT_QUESTION,
+ TYPE_ACTIVITY_COMMENT_ANSWER,
+ TYPE_ACTIVITY_UPDATE_ANSWER,
+ TYPE_ACTIVITY_UPDATE_QUESTION,
+ TYPE_ACTIVITY_UPDATE_ANSWER,
+ TYPE_ACTIVITY_PRIZE,
+ TYPE_ACTIVITY_MARK_ANSWER,
+ TYPE_ACTIVITY_VOTE_UP,
+ TYPE_ACTIVITY_VOTE_DOWN,
+ TYPE_ACTIVITY_CANCEL_VOTE,
+ TYPE_ACTIVITY_DELETE_QUESTION,
+ TYPE_ACTIVITY_DELETE_ANSWER,
+ TYPE_ACTIVITY_MARK_OFFENSIVE,
+ TYPE_ACTIVITY_FAVORITE,
)
TYPE_RESPONSE = {
diff --git a/forum/migrations/0010_add_receiving_user_to_activity_model.py b/forum/migrations/0010_add_receiving_user_to_activity_model.py
new file mode 100644
index 00000000..5fb6ebe0
--- /dev/null
+++ b/forum/migrations/0010_add_receiving_user_to_activity_model.py
@@ -0,0 +1,366 @@
+# encoding: utf-8
+import datetime
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+
+class Migration(SchemaMigration):
+
+ def forwards(self, orm):
+
+ # Adding M2M table for field receiving_user on 'Activity'
+ db.create_table(u'activity_receiving_users', (
+ ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
+ ('activity', models.ForeignKey(orm['forum.activity'], null=False)),
+ ('user', models.ForeignKey(orm['auth.user'], null=False))
+ ))
+ db.create_unique(u'activity_receiving_users', ['activity_id', 'user_id'])
+
+
+ def backwards(self, orm):
+
+ # Removing M2M table for field receiving_user on 'Activity'
+ db.delete_table('activity_receiving_users')
+
+
+ models = {
+ 'auth.group': {
+ 'Meta': {'object_name': 'Group'},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
+ 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'})
+ },
+ 'auth.permission': {
+ 'Meta': {'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
+ 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+ },
+ 'auth.user': {
+ 'Meta': {'object_name': 'User'},
+ 'about': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'bronze': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),
+ 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'date_of_birth': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
+ 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
+ 'email_isvalid': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+ 'email_key': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}),
+ 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+ 'gold': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),
+ 'gravatar': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
+ 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'blank': 'True'}),
+ 'hide_ignored_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
+ 'is_approved': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+ 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+ 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+ 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+ 'last_seen': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'location': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
+ 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
+ 'questions_per_page': ('django.db.models.fields.SmallIntegerField', [], {'default': '10'}),
+ 'real_name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
+ 'reputation': ('django.db.models.fields.PositiveIntegerField', [], {'default': '1'}),
+ 'silver': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),
+ 'tag_filter_setting': ('django.db.models.fields.CharField', [], {'default': "'ignored'", 'max_length': '16'}),
+ 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'}),
+ 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}),
+ 'website': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'})
+ },
+ 'contenttypes.contenttype': {
+ 'Meta': {'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
+ 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
+ },
+ 'forum.activity': {
+ 'Meta': {'object_name': 'Activity', 'db_table': "u'activity'"},
+ 'active_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'activity_type': ('django.db.models.fields.SmallIntegerField', [], {}),
+ 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'is_auditted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+ 'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}),
+ 'receiving_users': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'received_activity'", 'to': "orm['auth.User']"}),
+ 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"})
+ },
+ 'forum.anonymousanswer': {
+ 'Meta': {'object_name': 'AnonymousAnswer'},
+ 'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'author': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'ip_addr': ('django.db.models.fields.IPAddressField', [], {'max_length': '15'}),
+ 'question': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'anonymous_answers'", 'to': "orm['forum.Question']"}),
+ 'session_key': ('django.db.models.fields.CharField', [], {'max_length': '40'}),
+ 'summary': ('django.db.models.fields.CharField', [], {'max_length': '180'}),
+ 'text': ('django.db.models.fields.TextField', [], {}),
+ 'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'})
+ },
+ 'forum.anonymousquestion': {
+ 'Meta': {'object_name': 'AnonymousQuestion'},
+ 'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'author': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'ip_addr': ('django.db.models.fields.IPAddressField', [], {'max_length': '15'}),
+ 'session_key': ('django.db.models.fields.CharField', [], {'max_length': '40'}),
+ 'summary': ('django.db.models.fields.CharField', [], {'max_length': '180'}),
+ 'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),
+ 'text': ('django.db.models.fields.TextField', [], {}),
+ 'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}),
+ 'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'})
+ },
+ 'forum.answer': {
+ 'Meta': {'object_name': 'Answer', 'db_table': "u'answer'"},
+ 'accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+ 'accepted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
+ 'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'answers'", 'to': "orm['auth.User']"}),
+ 'comment_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
+ 'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+ 'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
+ 'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_answers'", 'null': 'True', 'to': "orm['auth.User']"}),
+ 'html': ('django.db.models.fields.TextField', [], {'null': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'last_edited_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
+ 'last_edited_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'last_edited_answers'", 'null': 'True', 'to': "orm['auth.User']"}),
+ 'locked': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+ 'locked_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
+ 'locked_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'locked_answers'", 'null': 'True', 'to': "orm['auth.User']"}),
+ 'offensive_flag_count': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),
+ 'question': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'answers'", 'to': "orm['forum.Question']"}),
+ 'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'text': ('django.db.models.fields.TextField', [], {'null': 'True'}),
+ 'vote_down_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'vote_up_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+ 'wikified_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})
+ },
+ 'forum.answerrevision': {
+ 'Meta': {'object_name': 'AnswerRevision', 'db_table': "u'answer_revision'"},
+ 'answer': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'revisions'", 'to': "orm['forum.Answer']"}),
+ 'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'answerrevisions'", 'to': "orm['auth.User']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'revised_at': ('django.db.models.fields.DateTimeField', [], {}),
+ 'revision': ('django.db.models.fields.PositiveIntegerField', [], {}),
+ 'summary': ('django.db.models.fields.CharField', [], {'max_length': '300', 'blank': 'True'}),
+ 'text': ('django.db.models.fields.TextField', [], {})
+ },
+ 'forum.authkeyuserassociation': {
+ 'Meta': {'object_name': 'AuthKeyUserAssociation'},
+ 'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),
+ 'provider': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
+ 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'auth_keys'", 'to': "orm['auth.User']"})
+ },
+ 'forum.award': {
+ 'Meta': {'object_name': 'Award', 'db_table': "u'award'"},
+ 'awarded_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'badge': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'award_badge'", 'to': "orm['forum.Badge']"}),
+ 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'notified': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+ 'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}),
+ 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'award_user'", 'to': "orm['auth.User']"})
+ },
+ 'forum.badge': {
+ 'Meta': {'unique_together': "(('name', 'type'),)", 'object_name': 'Badge', 'db_table': "u'badge'"},
+ 'awarded_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
+ 'awarded_to': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'badges'", 'through': "'Award'", 'to': "orm['auth.User']"}),
+ 'description': ('django.db.models.fields.CharField', [], {'max_length': '300'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'multiple': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
+ 'slug': ('django.db.models.fields.SlugField', [], {'db_index': 'True', 'max_length': '50', 'blank': 'True'}),
+ 'type': ('django.db.models.fields.SmallIntegerField', [], {})
+ },
+ 'forum.book': {
+ 'Meta': {'object_name': 'Book', 'db_table': "u'book'"},
+ 'added_at': ('django.db.models.fields.DateTimeField', [], {}),
+ 'author': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+ 'cover_img': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'last_edited_at': ('django.db.models.fields.DateTimeField', [], {}),
+ 'pages': ('django.db.models.fields.SmallIntegerField', [], {}),
+ 'price': ('django.db.models.fields.DecimalField', [], {'max_digits': '6', 'decimal_places': '2'}),
+ 'publication': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+ 'published_at': ('django.db.models.fields.DateTimeField', [], {}),
+ 'questions': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'book'", 'db_table': "'book_question'", 'to': "orm['forum.Question']"}),
+ 'short_name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+ 'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),
+ 'title': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+ 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"})
+ },
+ 'forum.bookauthorinfo': {
+ 'Meta': {'object_name': 'BookAuthorInfo', 'db_table': "u'book_author_info'"},
+ 'added_at': ('django.db.models.fields.DateTimeField', [], {}),
+ 'blog_url': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+ 'book': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Book']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'last_edited_at': ('django.db.models.fields.DateTimeField', [], {}),
+ 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"})
+ },
+ 'forum.bookauthorrss': {
+ 'Meta': {'object_name': 'BookAuthorRss', 'db_table': "u'book_author_rss'"},
+ 'added_at': ('django.db.models.fields.DateTimeField', [], {}),
+ 'book': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Book']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'rss_created_at': ('django.db.models.fields.DateTimeField', [], {}),
+ 'title': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+ 'url': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+ 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"})
+ },
+ 'forum.comment': {
+ 'Meta': {'object_name': 'Comment', 'db_table': "u'comment'"},
+ 'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'comment': ('django.db.models.fields.CharField', [], {'max_length': '2048'}),
+ 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+ 'html': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '2048'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}),
+ 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'comments'", 'to': "orm['auth.User']"})
+ },
+ 'forum.emailfeedsetting': {
+ 'Meta': {'object_name': 'EmailFeedSetting'},
+ 'added_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+ 'feed_type': ('django.db.models.fields.CharField', [], {'max_length': '16'}),
+ 'frequency': ('django.db.models.fields.CharField', [], {'default': "'n'", 'max_length': '8'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'reported_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}),
+ 'subscriber': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'notification_subscriptions'", 'to': "orm['auth.User']"})
+ },
+ 'forum.favoritequestion': {
+ 'Meta': {'object_name': 'FavoriteQuestion', 'db_table': "u'favorite_question'"},
+ 'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Question']"}),
+ 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_favorite_questions'", 'to': "orm['auth.User']"})
+ },
+ 'forum.flaggeditem': {
+ 'Meta': {'unique_together': "(('content_type', 'object_id', 'user'),)", 'object_name': 'FlaggedItem', 'db_table': "u'flagged_item'"},
+ 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+ 'flagged_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}),
+ 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'flaggeditems'", 'to': "orm['auth.User']"})
+ },
+ 'forum.markedtag': {
+ 'Meta': {'object_name': 'MarkedTag'},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'reason': ('django.db.models.fields.CharField', [], {'max_length': '16'}),
+ 'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_selections'", 'to': "orm['forum.Tag']"}),
+ 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tag_selections'", 'to': "orm['auth.User']"})
+ },
+ 'forum.mention': {
+ 'Meta': {'object_name': 'Mention', 'db_table': "u'mention'"},
+ 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'mentioned_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'mentioned_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'mentions_sent'", 'to': "orm['auth.User']"}),
+ 'mentioned_whom': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'mentions_received'", 'to': "orm['auth.User']"}),
+ 'object_id': ('django.db.models.fields.PositiveIntegerField', [], {})
+ },
+ 'forum.question': {
+ 'Meta': {'object_name': 'Question', 'db_table': "u'question'"},
+ 'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'answer_accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+ 'answer_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
+ 'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'questions'", 'to': "orm['auth.User']"}),
+ 'close_reason': ('django.db.models.fields.SmallIntegerField', [], {'null': 'True', 'blank': 'True'}),
+ 'closed': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+ 'closed_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
+ 'closed_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'closed_questions'", 'null': 'True', 'to': "orm['auth.User']"}),
+ 'comment_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
+ 'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+ 'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
+ 'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_questions'", 'null': 'True', 'to': "orm['auth.User']"}),
+ 'favorited_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'favorite_questions'", 'through': "'FavoriteQuestion'", 'to': "orm['auth.User']"}),
+ 'favourite_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
+ 'followed_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'followed_questions'", 'to': "orm['auth.User']"}),
+ 'html': ('django.db.models.fields.TextField', [], {'null': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'last_activity_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'last_activity_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'last_active_in_questions'", 'to': "orm['auth.User']"}),
+ 'last_edited_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
+ 'last_edited_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'last_edited_questions'", 'null': 'True', 'to': "orm['auth.User']"}),
+ 'locked': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+ 'locked_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
+ 'locked_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'locked_questions'", 'null': 'True', 'to': "orm['auth.User']"}),
+ 'offensive_flag_count': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),
+ 'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'summary': ('django.db.models.fields.CharField', [], {'max_length': '180'}),
+ 'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),
+ 'tags': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'questions'", 'to': "orm['forum.Tag']"}),
+ 'text': ('django.db.models.fields.TextField', [], {'null': 'True'}),
+ 'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}),
+ 'view_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
+ 'vote_down_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'vote_up_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+ 'wikified_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})
+ },
+ 'forum.questionrevision': {
+ 'Meta': {'object_name': 'QuestionRevision', 'db_table': "u'question_revision'"},
+ 'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'questionrevisions'", 'to': "orm['auth.User']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'question': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'revisions'", 'to': "orm['forum.Question']"}),
+ 'revised_at': ('django.db.models.fields.DateTimeField', [], {}),
+ 'revision': ('django.db.models.fields.PositiveIntegerField', [], {}),
+ 'summary': ('django.db.models.fields.CharField', [], {'max_length': '300', 'blank': 'True'}),
+ 'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),
+ 'text': ('django.db.models.fields.TextField', [], {}),
+ 'title': ('django.db.models.fields.CharField', [], {'max_length': '300'})
+ },
+ 'forum.questionview': {
+ 'Meta': {'object_name': 'QuestionView'},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'question': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'viewed'", 'to': "orm['forum.Question']"}),
+ 'when': ('django.db.models.fields.DateTimeField', [], {}),
+ 'who': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'question_views'", 'to': "orm['auth.User']"})
+ },
+ 'forum.repute': {
+ 'Meta': {'object_name': 'Repute', 'db_table': "u'repute'"},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'negative': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),
+ 'positive': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),
+ 'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Question']"}),
+ 'reputation': ('django.db.models.fields.IntegerField', [], {'default': '1'}),
+ 'reputation_type': ('django.db.models.fields.SmallIntegerField', [], {}),
+ 'reputed_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"})
+ },
+ 'forum.tag': {
+ 'Meta': {'object_name': 'Tag', 'db_table': "u'tag'"},
+ 'created_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'created_tags'", 'to': "orm['auth.User']"}),
+ 'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+ 'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
+ 'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_tags'", 'null': 'True', 'to': "orm['auth.User']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),
+ 'used_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'})
+ },
+ 'forum.validationhash': {
+ 'Meta': {'unique_together': "(('user', 'type'),)", 'object_name': 'ValidationHash'},
+ 'expiration': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 5, 18, 11, 49, 24, 344026)'}),
+ 'hash_code': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'seed': ('django.db.models.fields.CharField', [], {'max_length': '12'}),
+ 'type': ('django.db.models.fields.CharField', [], {'max_length': '12'}),
+ 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"})
+ },
+ 'forum.vote': {
+ 'Meta': {'unique_together': "(('content_type', 'object_id', 'user'),)", 'object_name': 'Vote', 'db_table': "u'vote'"},
+ 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}),
+ 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'votes'", 'to': "orm['auth.User']"}),
+ 'vote': ('django.db.models.fields.SmallIntegerField', [], {}),
+ 'voted_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'})
+ }
+ }
+
+ complete_apps = ['forum']
diff --git a/forum/models/__init__.py b/forum/models/__init__.py
index c3ba280c..d4b9dcb4 100644
--- a/forum/models/__init__.py
+++ b/forum/models/__init__.py
@@ -8,6 +8,7 @@ from repute import Badge, Award, Repute
from django.core.urlresolvers import reverse
from forum.search.indexer import create_fulltext_indexes
from django.db.models.signals import post_syncdb
+import logging
import re
from base import *
@@ -108,7 +109,6 @@ def get_profile_url(self):
def get_profile_link(self):
profile_link = u'<a href="%s">%s</a>' % (self.get_profile_url(),self.username)
- logging.debug('in get profile link %s' % profile_link)
return mark_safe(profile_link)
#series of methods for user vote-type commands
@@ -246,7 +246,12 @@ def calculate_gravatar_hash(instance, **kwargs):
def record_ask_event(instance, created, **kwargs):
if created:
- activity = Activity(user=instance.author, active_at=instance.added_at, content_object=instance, activity_type=TYPE_ACTIVITY_ASK_QUESTION)
+ activity = Activity(
+ user=instance.author,
+ active_at=instance.added_at,
+ content_object=instance,
+ activity_type=TYPE_ACTIVITY_ASK_QUESTION
+ )
activity.save()
#todo: translate this
@@ -272,33 +277,85 @@ def record_answer_event(instance, created, **kwargs):
% q_author.get_profile_url()
q_author.message_set.create(message=msg)
- activity = Activity(user=instance.author, \
- active_at=instance.added_at,\
- content_object=instance, \
- activity_type=TYPE_ACTIVITY_ANSWER)
+ activity = Activity(
+ user = instance.author,
+ active_at = instance.added_at,
+ content_object = instance,
+ activity_type = TYPE_ACTIVITY_ANSWER
+ )
activity.save()
+ receiving_users = instance.question.get_author_list(
+ include_comments = True,
+ exclude_list = [instance.author],
+ )
+
+ activity.receiving_users.add(*receiving_users)
+
def record_comment_event(instance, created, **kwargs):
if created:
- from django.contrib.contenttypes.models import ContentType
- question_type = ContentType.objects.get_for_model(Question)
- question_type_id = question_type.id
- if (instance.content_type_id == question_type_id):
+ if isinstance(instance.content_object, Question):
type = TYPE_ACTIVITY_COMMENT_QUESTION
- else:
+ elif isinstance(instance.content_object, Answer):
type = TYPE_ACTIVITY_COMMENT_ANSWER
- activity = Activity(user=instance.user, active_at=instance.added_at, content_object=instance, activity_type=type)
+ else:
+ logging.critical('recording comment for %s is not implemented' % type(instance.content_object))
+
+ activity = Activity(
+ user = instance.user,
+ active_at = instance.added_at,
+ content_object = instance,
+ activity_type = type
+ )
activity.save()
+ receiving_users = instance.content_object.get_author_list(
+ include_comments = True,
+ exclude_list = [instance.user],
+ )
+ activity.receiving_users.add(*receiving_users)
+
+
def record_revision_question_event(instance, created, **kwargs):
if created and instance.revision <> 1:
- activity = Activity(user=instance.author, active_at=instance.revised_at, content_object=instance, activity_type=TYPE_ACTIVITY_UPDATE_QUESTION)
+ activity = Activity(
+ user=instance.author,
+ active_at=instance.revised_at,
+ content_object=instance,
+ activity_type=TYPE_ACTIVITY_UPDATE_QUESTION
+ )
activity.save()
+ receiving_users = set()
+ receiving_users.update(
+ instance.question.get_author_list(include_comments = True)
+ )
+ for a in instance.question.answers:
+ receiving_users.update(a.get_author_list())
+ receiving_users -= set([instance.author])
+
+ receiving_users = list(receiving_users)
+ activity.receiving_users.add(*receiving_users)
def record_revision_answer_event(instance, created, **kwargs):
if created and instance.revision <> 1:
- activity = Activity(user=instance.author, active_at=instance.revised_at, content_object=instance, activity_type=TYPE_ACTIVITY_UPDATE_ANSWER)
+ activity = Activity(
+ user=instance.author,
+ active_at=instance.revised_at,
+ content_object=instance,
+ activity_type=TYPE_ACTIVITY_UPDATE_ANSWER
+ )
activity.save()
+ receiving_users = set()
+ receiving_users.update(
+ instance.answer.get_author_list(
+ including_comments = True
+ )
+ )
+ receiving_users.update(instance.answer.question.get_author_list())
+ receiving_users -= set([instance.author])
+ receiving_users = list(receiving_users)
+
+ activity.receiving_users.add(*receiving_users)
def record_award_event(instance, created, **kwargs):
"""
@@ -306,9 +363,14 @@ def record_award_event(instance, created, **kwargs):
We also recaculate awarded_count of this badge and user information.
"""
if created:
- activity = Activity(user=instance.user, active_at=instance.awarded_at, content_object=instance,
- activity_type=TYPE_ACTIVITY_PRIZE)
+ activity = Activity(
+ user=instance.user,#todo: change this to community user who gives the award
+ active_at=instance.awarded_at,
+ content_object=instance,
+ activity_type=TYPE_ACTIVITY_PRIZE
+ )
activity.save()
+ activity.receiving_users.add(instance.user)
instance.badge.awarded_count += 1
instance.badge.save()
@@ -339,14 +401,23 @@ def record_answer_accepted(instance, created, **kwargs):
when answer is accepted, we record this for question author - who accepted it.
"""
if not created and instance.accepted:
- activity = Activity(user=instance.question.author, active_at=datetime.datetime.now(), \
- content_object=instance, activity_type=TYPE_ACTIVITY_MARK_ANSWER)
+ activity = Activity(
+ user=instance.question.author,
+ active_at=datetime.datetime.now(),
+ content_object=instance,
+ activity_type=TYPE_ACTIVITY_MARK_ANSWER
+ )
+ receiving_users = instance.get_author_list(
+ exclude_list = [instance.question.author]
+ )
+ activity.receiving_users.add(*receiving_users)
activity.save()
def update_last_seen(instance, created, **kwargs):
"""
when user has activities, we update 'last_seen' time stamp for him
"""
+ #todo: improve this
user = instance.user
user.last_seen = datetime.datetime.now()
user.save()
@@ -361,14 +432,26 @@ def record_vote(instance, created, **kwargs):
else:
vote_type = TYPE_ACTIVITY_VOTE_DOWN
- activity = Activity(user=instance.user, active_at=instance.voted_at, content_object=instance, activity_type=vote_type)
+ activity = Activity(
+ user=instance.user,
+ active_at=instance.voted_at,
+ content_object=instance,
+ activity_type=vote_type
+ )
+ #todo: problem cannot access receiving user here
activity.save()
def record_cancel_vote(instance, **kwargs):
"""
when user canceled vote, the vote will be deleted.
"""
- activity = Activity(user=instance.user, active_at=datetime.datetime.now(), content_object=instance, activity_type=TYPE_ACTIVITY_CANCEL_VOTE)
+ activity = Activity(
+ user=instance.user,
+ active_at=datetime.datetime.now(),
+ content_object=instance,
+ activity_type=TYPE_ACTIVITY_CANCEL_VOTE
+ )
+ #todo: same problem - cannot access receiving user here
activity.save()
def record_delete_question(instance, delete_by, **kwargs):
@@ -380,18 +463,38 @@ def record_delete_question(instance, delete_by, **kwargs):
else:
activity_type = TYPE_ACTIVITY_DELETE_ANSWER
- activity = Activity(user=delete_by, active_at=datetime.datetime.now(), content_object=instance, activity_type=activity_type)
+ activity = Activity(
+ user=delete_by,
+ active_at=datetime.datetime.now(),
+ content_object=instance,
+ activity_type=activity_type
+ )
+ #no need to set receiving user here
activity.save()
def record_mark_offensive(instance, mark_by, **kwargs):
- activity = Activity(user=mark_by, active_at=datetime.datetime.now(), content_object=instance, activity_type=TYPE_ACTIVITY_MARK_OFFENSIVE)
+ activity = Activity(
+ user=mark_by,
+ active_at=datetime.datetime.now(),
+ content_object=instance,
+ activity_type=TYPE_ACTIVITY_MARK_OFFENSIVE
+ )
activity.save()
+ receiving_users = instance.get_author_list(
+ exclude_list = [mark_by]
+ )
+ activity.receiving_users.add(*receiving_users)
def record_update_tags(question, **kwargs):
"""
when user updated tags of the question
"""
- activity = Activity(user=question.author, active_at=datetime.datetime.now(), content_object=question, activity_type=TYPE_ACTIVITY_UPDATE_TAGS)
+ activity = Activity(
+ user=question.author,
+ active_at=datetime.datetime.now(),
+ content_object=question,
+ activity_type=TYPE_ACTIVITY_UPDATE_TAGS
+ )
activity.save()
def record_favorite_question(instance, created, **kwargs):
@@ -399,11 +502,25 @@ def record_favorite_question(instance, created, **kwargs):
when user add the question in him favorite questions list.
"""
if created:
- activity = Activity(user=instance.user, active_at=datetime.datetime.now(), content_object=instance, activity_type=TYPE_ACTIVITY_FAVORITE)
+ activity = Activity(
+ user=instance.user,
+ active_at=datetime.datetime.now(),
+ content_object=instance,
+ activity_type=TYPE_ACTIVITY_FAVORITE
+ )
activity.save()
+ receiving_users = instance.question.get_author_list(
+ exclude_list = [instance.user]
+ )
+ activity.receiving_users.add(*receiving_users)
def record_user_full_updated(instance, **kwargs):
- activity = Activity(user=instance, active_at=datetime.datetime.now(), content_object=instance, activity_type=TYPE_ACTIVITY_USER_FULL_UPDATED)
+ activity = Activity(
+ user=instance,
+ active_at=datetime.datetime.now(),
+ content_object=instance,
+ activity_type=TYPE_ACTIVITY_USER_FULL_UPDATED
+ )
activity.save()
def post_stored_anonymous_content(sender,user,session_key,signal,*args,**kwargs):
diff --git a/forum/models/base.py b/forum/models/base.py
index 81626405..076d1cfa 100644
--- a/forum/models/base.py
+++ b/forum/models/base.py
@@ -155,6 +155,19 @@ class Content(models.Model):
def get_last_author(self):
return self.last_edited_by
+ def get_author_list(self, include_comments = False, recursive = False, exclude_list = None):
+ authors = set()
+ authors.update([r.author for r in self.revisions.all()])
+ if include_comments:
+ authors.update([c.user for c in self.comments.all()])
+ if recursive:
+ if hasattr(self, 'answers'):
+ for a in self.answers.all():
+ authors.update(a.get_author_list( include_comments = include_comments ) )
+ if exclude_list:
+ authors -= set(exclude_list)
+ return list(authors)
+
def post_get_last_update_info(self):#todo: rename this subroutine
when = self.added_at
who = self.author
diff --git a/forum/models/meta.py b/forum/models/meta.py
index 0ba07f98..d792beca 100644
--- a/forum/models/meta.py
+++ b/forum/models/meta.py
@@ -19,7 +19,6 @@ class VoteManager(models.Manager):
if user is not None:
today = datetime.date.today()
return self.filter(user=user, voted_at__range=(today, today + datetime.timedelta(1))).count()
-
else:
return 0
diff --git a/forum/models/question.py b/forum/models/question.py
index 584d6bf6..58852495 100644
--- a/forum/models/question.py
+++ b/forum/models/question.py
@@ -301,15 +301,6 @@ class Question(Content, DeletableContent):
except Exception:
logging.debug('problem pinging google did you register you sitemap with google?')
- def get_all_authors(self):
- authors = set()
- authors.update([r.author for r in self.revisions.all()])
- authors.update([c.user for c in self.comments.all()])
- for a in self.answers.filter(deleted = False):
- authors.update([r.author for r in a.revisions.all()])
- authors.update([c.user for c in a.comments.all()])
- return authors
-
def retag(self, retagged_by=None, retagged_at=None, tagnames=None):
if None in (retagged_by, retagged_at, tagnames):
raise Exception('arguments retagged_at, retagged_by and tagnames are required')
@@ -321,8 +312,11 @@ class Question(Content, DeletableContent):
self.last_activity_by = retagged_by
# Update the Question's tag associations
- tags_updated = self.objects.update_tags(self,
- form.cleaned_data['tags'], request.user)
+ tags_updated = self.objects.update_tags(
+ self,
+ form.cleaned_data['tags'],
+ request.user
+ )
# Create a new revision
latest_revision = self.get_latest_revision()
diff --git a/forum/models/user.py b/forum/models/user.py
index 5636ff9b..4e2b7f1a 100644
--- a/forum/models/user.py
+++ b/forum/models/user.py
@@ -15,6 +15,7 @@ class Activity(models.Model):
We keep some history data for user activities
"""
user = models.ForeignKey(User)
+ receiving_users = models.ManyToManyField(User, related_name='received_activity')
activity_type = models.SmallIntegerField(choices=TYPE_ACTIVITY)
active_at = models.DateTimeField(default=datetime.datetime.now)
content_type = models.ForeignKey(ContentType)
@@ -49,6 +50,7 @@ class MentionManager(models.Manager):
class Mention(models.Model):
"""
Table holding @mention type entries in the posts
+ todo: maybe merge this with Activity table
"""
mentioned_by = models.ForeignKey(User, related_name = 'mentions_sent')
mentioned_whom = models.ForeignKey(User, related_name = 'mentions_received')
diff --git a/forum/utils/markup.py b/forum/utils/markup.py
index 0eef1110..b921077a 100644
--- a/forum/utils/markup.py
+++ b/forum/utils/markup.py
@@ -44,7 +44,7 @@ def mentionize(text, context_object = None):
return text
op = context_object.get_origin_post()
- authors = list(op.get_all_authors())
+ authors = op.get_author_list( include_comments = True, recursive = True )
extra_name_seed = ''
for c in text:
diff --git a/forum/views/users.py b/forum/views/users.py
index f20a332e..742f714c 100644
--- a/forum/views/users.py
+++ b/forum/views/users.py
@@ -564,6 +564,7 @@ def user_responses(request, user_id, user_view):
user = get_object_or_404(User, id=user_id)
responses = []
+
answers = Answer.objects.extra(
select={
'title' : 'question.title',