summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-x.gitignore1
-rw-r--r--askbot/api.py34
-rw-r--r--askbot/context.py30
-rw-r--r--askbot/deps/django_authopenid/views.py2
-rw-r--r--askbot/locale/en/LC_MESSAGES/django.po45
-rw-r--r--askbot/migrations/0024_add_recipients_m2m_to_activity_and_denorm_question_on_activity.py34
-rw-r--r--askbot/migrations/0025_transfer_flagged_items_to_activity.py347
-rw-r--r--askbot/migrations/0026_add_seen_and_new_response_counts_to_user.py315
-rw-r--r--askbot/migrations/0027_populate_new_response_counts.py313
-rw-r--r--askbot/migrations/0028_delete_response_count_column_from_user_model.py311
-rw-r--r--askbot/migrations_api/__init__.py10
-rw-r--r--askbot/migrations_api/version1.py63
-rw-r--r--askbot/models/__init__.py65
-rw-r--r--askbot/models/user.py7
-rw-r--r--askbot/skins/default/media/images/dialog-warning-off.pngbin0 -> 419 bytes
-rw-r--r--askbot/skins/default/media/images/dialog-warning.pngbin0 -> 603 bytes
-rw-r--r--askbot/skins/default/media/js/com.cnprog.post.js10
-rw-r--r--askbot/skins/default/media/js/com.cnprog.utils.js16
-rw-r--r--askbot/skins/default/media/js/user.js99
-rwxr-xr-xaskbot/skins/default/media/style/style.css34
-rw-r--r--askbot/skins/default/templates/header.html43
-rw-r--r--askbot/skins/default/templates/macros.html6
-rw-r--r--askbot/skins/default/templates/questions.html2
-rw-r--r--askbot/skins/default/templates/user.html31
-rw-r--r--askbot/skins/default/templates/user_edit.html20
-rw-r--r--askbot/skins/default/templates/user_inbox.html85
-rw-r--r--askbot/skins/default/templates/user_reputation.html30
-rw-r--r--askbot/skins/default/templates/user_responses.html36
-rw-r--r--askbot/skins/default/templates/user_tabs.html18
-rw-r--r--askbot/tests/on_screen_notification_tests.py110
-rw-r--r--askbot/tests/page_load_tests.py2
-rw-r--r--askbot/urls.py5
-rw-r--r--askbot/views/commands.py102
-rw-r--r--askbot/views/users.py60
34 files changed, 1999 insertions, 287 deletions
diff --git a/.gitignore b/.gitignore
index 509dae34..a9ff6eaf 100755
--- a/.gitignore
+++ b/.gitignore
@@ -34,3 +34,4 @@ askbot/upfiles/*.gif
askbot/upfiles/*.png
askbot/skins/common/media/mathjax/
/jinja2
+*.tag.tz
diff --git a/askbot/api.py b/askbot/api.py
new file mode 100644
index 00000000..c79f29dd
--- /dev/null
+++ b/askbot/api.py
@@ -0,0 +1,34 @@
+"""place for the API calls into askbot
+at this point most of the useful functions are still
+in the askbot.models module, but
+api must become a place to manupulate the data in the askbot application
+so that other implementations of the data storage could be possible
+"""
+from askbot import models
+from askbot import const
+
+def get_info_on_moderation_items(user):
+ """returns a dictionary with
+ counts of new and seen moderation items for a given user
+ if user is not a moderator or admin, returns None
+ """
+ if user.is_anonymous():
+ return None
+ if not(user.is_moderator() or user.is_administrator()):
+ return None
+
+ messages = models.ActivityAuditStatus.objects.filter(
+ activity__activity_type = const.TYPE_ACTIVITY_MARK_OFFENSIVE,
+ user = user
+ )
+
+ seen_count = messages.filter(
+ status = models.ActivityAuditStatus.STATUS_SEEN
+ ).count()
+ new_count = messages.filter(
+ status = models.ActivityAuditStatus.STATUS_NEW
+ ).count()
+ return {
+ 'seen_count': seen_count,
+ 'new_count': new_count
+ }
diff --git a/askbot/context.py b/askbot/context.py
index 73f6018a..59056003 100644
--- a/askbot/context.py
+++ b/askbot/context.py
@@ -1,35 +1,13 @@
from django.conf import settings
from askbot.conf import settings as askbot_settings
+from askbot import api
import datetime
-def application_settings(context):
+def application_settings(request):
my_settings = askbot_settings.as_dict()
my_settings['LANGUAGE_CODE'] = settings.LANGUAGE_CODE
my_settings['ASKBOT_URL'] = settings.ASKBOT_URL
- return {'settings':my_settings}
-
-def auth_processor(request):
- """
- Returns context variables required by apps that use Django's authentication
- system.
-
- If there is no 'user' attribute in the request, uses AnonymousUser (from
- django.contrib.auth).
- """
- if hasattr(request, 'user'):
- user = request.user
- if user.is_authenticated():
- messages = user.message_set.all()
- else:
- messages = None
- else:
- from django.contrib.auth.models import AnonymousUser
- user = AnonymousUser()
- messages = None
-
- from django.core.context_processors import PermWrapper
return {
- 'user': user,
- 'messages': messages,
- 'perms': PermWrapper(user),
+ 'settings': my_settings,
+ 'moderation_items': api.get_info_on_moderation_items(request.user)
}
diff --git a/askbot/deps/django_authopenid/views.py b/askbot/deps/django_authopenid/views.py
index 115c8478..fb4aae82 100644
--- a/askbot/deps/django_authopenid/views.py
+++ b/askbot/deps/django_authopenid/views.py
@@ -581,7 +581,7 @@ def delete_login_method(request):
logging.critical(
'have multiple %(provider)s logins for user %(id)s'
) % {'provider':provider_name, 'id': request.user.id}
- message = _('Sorry, there was some error, we will look at it')
+ message = _('Oops, sorry - there was some error - please try again')
return HttpResponse(message, status=500, mimetype = 'application/json')
else:
raise Http404
diff --git a/askbot/locale/en/LC_MESSAGES/django.po b/askbot/locale/en/LC_MESSAGES/django.po
index 210fdcf0..4cf2df04 100644
--- a/askbot/locale/en/LC_MESSAGES/django.po
+++ b/askbot/locale/en/LC_MESSAGES/django.po
@@ -1245,11 +1245,8 @@ msgid "Please, enter your password"
msgstr "Send me a new password"
#: deps/django_authopenid/forms.py:274 deps/django_authopenid/forms.py:278
-#, fuzzy
msgid "Please, enter your new password"
msgstr ""
-"<span class='big strong'>Enter your Askbot login and password</span><br/"
-"><span class='grey'>(or select your OpenID provider above)</span>"
#: deps/django_authopenid/forms.py:289
msgid "Passwords did not match"
@@ -1428,9 +1425,8 @@ msgid ""
msgstr ""
#: deps/django_authopenid/views.py:349
-#, fuzzy
msgid "Your new password saved"
-msgstr "New password created"
+msgstr ""
#: deps/django_authopenid/views.py:511
msgid "Please click any of the icons below to sign in"
@@ -2409,26 +2405,18 @@ msgstr[0] ""
msgstr[1] ""
#: models/__init__.py:1207
-#, fuzzy, python-format
+#, python-format
msgid "one silver badge"
msgid_plural "%(count)d silver badges"
msgstr[0] ""
-"Obtaining silver badge requires significant patience. If you have received "
-"one, that means you have greatly contributed to this community."
msgstr[1] ""
-"Obtaining silver badge requires significant patience. If you have received "
-"one, that means you have greatly contributed to this community."
#: models/__init__.py:1214
-#, fuzzy, python-format
+#, python-format
msgid "one bronze badge"
msgid_plural "%(count)d bronze badges"
msgstr[0] ""
-"If you are an active participant in this community, you will be recognized "
-"with this badge."
msgstr[1] ""
-"If you are an active participant in this community, you will be recognized "
-"with this badge."
#: models/__init__.py:1225
#, python-format
@@ -2447,9 +2435,9 @@ msgid "Re: \"%(title)s\""
msgstr ""
#: models/__init__.py:1506 models/__init__.py:1511
-#, fuzzy, python-format
+#, python-format
msgid "Question: \"%(title)s\""
-msgstr "Tags"
+msgstr ""
#: models/__init__.py:1691
#, python-format
@@ -2607,9 +2595,8 @@ msgstr ""
#: skins/default/templates/404.jinja.html:41
#: skins/default/templates/questions.html:30
-#, fuzzy
msgid "see all questions"
-msgstr "Post Your Answer"
+msgstr ""
#: skins/default/templates/404.jinja.html:42
msgid "see all tags"
@@ -2629,14 +2616,12 @@ msgid "please report the error to the site administrators if you wish"
msgstr ""
#: skins/default/templates/500.jinja.html:22
-#, fuzzy
msgid "see latest questions"
-msgstr "questions with most answers"
+msgstr ""
#: skins/default/templates/500.jinja.html:23
-#, fuzzy
msgid "see tags"
-msgstr "Tags"
+msgstr ""
#: skins/default/templates/about.html:3 skins/default/templates/about.html:8
msgid "About"
@@ -2644,9 +2629,8 @@ msgstr ""
#: skins/default/templates/answer_edit.html:4
#: skins/default/templates/answer_edit.html:23
-#, fuzzy
msgid "Edit answer"
-msgstr "oldest"
+msgstr ""
#: skins/default/templates/answer_edit.html:23
#: skins/default/templates/question_edit.html:22
@@ -2703,7 +2687,6 @@ msgid "answer tips"
msgstr "Tips"
#: skins/default/templates/answer_edit_tips.html:6
-#, fuzzy
msgid "please make your answer relevant to this community"
msgstr "ask a question interesting to this community"
@@ -2719,7 +2702,6 @@ msgstr ""
"best questions and answers!"
#: skins/default/templates/answer_edit_tips.html:12
-#, fuzzy
msgid "please try to provide details"
msgstr "provide enough details"
@@ -2760,9 +2742,8 @@ msgstr ""
#: skins/default/templates/answer_edit_tips.html:43
#: skins/default/templates/question_edit_tips.html:40
-#, fuzzy
msgid "link"
-msgstr "Hi, there! Please sign in"
+msgstr ""
#: skins/default/templates/answer_edit_tips.html:43
#: skins/default/templates/answer_edit_tips.html:47
@@ -2792,9 +2773,8 @@ msgid "learn more about Markdown"
msgstr ""
#: skins/default/templates/ask.html:3
-#, fuzzy
msgid "Ask a question"
-msgstr "Ask Your Question"
+msgstr ""
#: skins/default/templates/ask_form.html:7
msgid "login to post question info"
@@ -3067,9 +3047,8 @@ msgid "upvote"
msgstr ""
#: skins/default/templates/faq.html:51
-#, fuzzy
msgid "use tags"
-msgstr "people"
+msgstr ""
#: skins/default/templates/faq.html:56
#, fuzzy
diff --git a/askbot/migrations/0024_add_recipients_m2m_to_activity_and_denorm_question_on_activity.py b/askbot/migrations/0024_add_recipients_m2m_to_activity_and_denorm_question_on_activity.py
index 91b6b808..c5213526 100644
--- a/askbot/migrations/0024_add_recipients_m2m_to_activity_and_denorm_question_on_activity.py
+++ b/askbot/migrations/0024_add_recipients_m2m_to_activity_and_denorm_question_on_activity.py
@@ -4,6 +4,7 @@ from south.db import db
from south.v2 import DataMigration
from django.db import models
from askbot import const
+from askbot.migrations_api.version1 import API
#some of activities are not related to question, so they are not processed here
APPROPRIATE_ACTIVITIES = (
@@ -25,7 +26,7 @@ APPROPRIATE_ACTIVITIES = (
class Migration(DataMigration):
def forwards(self, orm):
- self._orm_for_askbot = orm
+ api = API(orm)
#1) fill in audit status values
activities = orm.Activity.objects.exclude(receiving_users=None)
@@ -41,7 +42,7 @@ class Migration(DataMigration):
for act in orm.Activity.objects.all():
if act.activity_type in APPROPRIATE_ACTIVITIES:
try:
- act.question = self.get_question_from_generic_relation(act)
+ act.question = api.get_origin_post_from_content_object(act)
act.save()
except Exception, e:
have_problems = True
@@ -55,35 +56,6 @@ class Migration(DataMigration):
print 'This is most likely not a big issue, but if you save this error message'
print 'and email to admin@askbot.org, that would help. Thanks.'
- def get_orm(self):
- return self._orm_for_askbot
-
- def get_question_from_generic_relation(self, parent):
- orm = self.get_orm()
- model = parent.content_type.model
- id = parent.object_id
- #print 'model is ' + model
- if model == 'question':
- return orm.Question.objects.get(id=id)
- elif model == 'answer':
- return orm.Answer.objects.get(id=id).question
- elif model == 'favoritequestion':
- try:
- return orm.FavoriteQuestion.objects.get(id=id).question
- except orm.FavoriteQuestion.DoesNotExist:
- #ignore this issue for now
- return None
- elif model == 'answerrevision':
- return orm.AnswerRevision.objects.get(id=id).answer.question
- elif model == 'questionrevision':
- return orm.QuestionRevision.objects.get(id=id).question
- elif model == 'comment':
- comment = orm.Comment.objects.get(id=id)
- return self.get_question_from_generic_relation(comment)
- else:
- #print 'dropped migration of activity in %s' % model
- return None
-
def backwards(self, orm):
orm.ActivityAuditStatus.objects.all().delete()
diff --git a/askbot/migrations/0025_transfer_flagged_items_to_activity.py b/askbot/migrations/0025_transfer_flagged_items_to_activity.py
new file mode 100644
index 00000000..6c40bbbe
--- /dev/null
+++ b/askbot/migrations/0025_transfer_flagged_items_to_activity.py
@@ -0,0 +1,347 @@
+# encoding: utf-8
+import datetime
+from south.db import db
+from south.v2 import DataMigration
+from django.db import models
+from askbot.migrations_api.version1 import API
+from askbot import const
+
+OFFENSIVE = const.TYPE_ACTIVITY_MARK_OFFENSIVE
+
+class Migration(DataMigration):
+
+ def forwards(self, orm):
+ """find all FlaggedItems and the corresponding Activity
+ transfer content object to Activity
+ add moderators and admins to the activity recipients
+ and set the denormalized value of question to the origin post
+ of the flagged item
+ """
+ api = API(orm)
+ moderators = api.get_moderators_and_admins()
+ for flag in orm.FlaggedItem.objects.all():
+ activity_items = api.get_activity_items_for_object(flag)
+ if len(activity_items) == 0:#fix a glitch
+ activity = orm.Activity(
+ user = flag.user,
+ active_at = flag.flagged_at,
+ activity_type = OFFENSIVE
+ )
+ elif len(activity_items) == 1:
+ activity = activity_items[0]
+ else:
+ raise ValueError('cannot have >1 flagged items per activity')
+ assert(activity.user==flag.user)
+ assert(activity.content_type==flag.content_type)
+ assert(activity.object_id==flag.object_id)
+ activity.question = api.get_origin_post_from_content_object(flag)
+ activity.save()
+ api.add_recipients_to_activity(moderators, activity)
+ flag.delete()
+
+ def backwards(self, orm):
+ """there is a side-effect that activity recipients are not removed
+ question reference is not deleted either
+ """
+ activity_items = orm.Activity.objects.filter(activity_type=OFFENSIVE)
+ api = API(orm)
+ for activity in activity_items:
+ flag = orm.FlaggedItem(
+ user = activity.user,
+ flagged_at = activity.active_at,
+ object_id = activity.object_id,
+ content_type = activity.content_type
+ )
+ flag.save()
+
+ models = {
+ 'askbot.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', [], {}),
+ 'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['askbot.Question']", 'null': 'True'}),
+ 'receiving_users': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'received_activity'", 'to': "orm['auth.User']"}),
+ 'recipients': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'incoming_activity'", 'through': "'ActivityAuditStatus'", 'to': "orm['auth.User']"}),
+ 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"})
+ },
+ 'askbot.activityauditstatus': {
+ 'Meta': {'unique_together': "(('user', 'activity'),)", 'object_name': 'ActivityAuditStatus'},
+ 'activity': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['askbot.Activity']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'status': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),
+ 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"})
+ },
+ 'askbot.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['askbot.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'})
+ },
+ 'askbot.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'})
+ },
+ 'askbot.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['askbot.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'})
+ },
+ 'askbot.answerrevision': {
+ 'Meta': {'object_name': 'AnswerRevision', 'db_table': "u'answer_revision'"},
+ 'answer': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'revisions'", 'to': "orm['askbot.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', [], {})
+ },
+ 'askbot.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['askbot.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']"})
+ },
+ 'askbot.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', [], {})
+ },
+ 'askbot.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', [], {}),
+ 'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'comments'", 'to': "orm['auth.User']"})
+ },
+ 'askbot.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']"})
+ },
+ 'askbot.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['askbot.Question']"}),
+ 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_favorite_questions'", 'to': "orm['auth.User']"})
+ },
+ 'askbot.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']"})
+ },
+ 'askbot.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['askbot.Tag']"}),
+ 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tag_selections'", 'to': "orm['auth.User']"})
+ },
+ 'askbot.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['askbot.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'})
+ },
+ 'askbot.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['askbot.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'})
+ },
+ 'askbot.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['askbot.Question']"}),
+ 'when': ('django.db.models.fields.DateTimeField', [], {}),
+ 'who': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'question_views'", 'to': "orm['auth.User']"})
+ },
+ 'askbot.repute': {
+ 'Meta': {'object_name': 'Repute', 'db_table': "u'repute'"},
+ 'comment': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}),
+ '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['askbot.Question']", 'null': 'True', 'blank': 'True'}),
+ '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']"})
+ },
+ 'askbot.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'})
+ },
+ 'askbot.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'})
+ },
+ '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_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'}),
+ 'response_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'silver': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),
+ 'status': ('django.db.models.fields.CharField', [], {'default': "'w'", 'max_length': '2'}),
+ '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'})
+ }
+ }
+
+ complete_apps = ['askbot']
diff --git a/askbot/migrations/0026_add_seen_and_new_response_counts_to_user.py b/askbot/migrations/0026_add_seen_and_new_response_counts_to_user.py
new file mode 100644
index 00000000..4cd05f83
--- /dev/null
+++ b/askbot/migrations/0026_add_seen_and_new_response_counts_to_user.py
@@ -0,0 +1,315 @@
+# 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 fields
+ try:
+ db.add_column('auth_user', 'new_response_count', self.gf('django.db.models.fields.IntegerField')(default=0), keep_default=False)
+ db.add_column('auth_user', 'seen_response_count', self.gf('django.db.models.fields.IntegerField')(default=0), keep_default=False)
+ except:
+ pass
+
+ def backwards(self, orm):
+ # Deleting fields
+ db.delete_column('auth_user', 'new_response_count')
+ db.delete_column('auth_user', 'seen_response_count')
+
+
+ models = {
+ 'askbot.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', [], {}),
+ 'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['askbot.Question']", 'null': 'True'}),
+ 'receiving_users': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'received_activity'", 'to': "orm['auth.User']"}),
+ 'recipients': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'incoming_activity'", 'through': "'ActivityAuditStatus'", 'to': "orm['auth.User']"}),
+ 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"})
+ },
+ 'askbot.activityauditstatus': {
+ 'Meta': {'unique_together': "(('user', 'activity'),)", 'object_name': 'ActivityAuditStatus'},
+ 'activity': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['askbot.Activity']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'status': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),
+ 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"})
+ },
+ 'askbot.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['askbot.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'})
+ },
+ 'askbot.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'})
+ },
+ 'askbot.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['askbot.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'})
+ },
+ 'askbot.answerrevision': {
+ 'Meta': {'object_name': 'AnswerRevision', 'db_table': "u'answer_revision'"},
+ 'answer': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'revisions'", 'to': "orm['askbot.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', [], {})
+ },
+ 'askbot.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['askbot.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']"})
+ },
+ 'askbot.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', [], {})
+ },
+ 'askbot.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', [], {}),
+ 'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'comments'", 'to': "orm['auth.User']"})
+ },
+ 'askbot.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']"})
+ },
+ 'askbot.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['askbot.Question']"}),
+ 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_favorite_questions'", 'to': "orm['auth.User']"})
+ },
+ 'askbot.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']"})
+ },
+ 'askbot.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['askbot.Tag']"}),
+ 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tag_selections'", 'to': "orm['auth.User']"})
+ },
+ 'askbot.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['askbot.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'})
+ },
+ 'askbot.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['askbot.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'})
+ },
+ 'askbot.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['askbot.Question']"}),
+ 'when': ('django.db.models.fields.DateTimeField', [], {}),
+ 'who': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'question_views'", 'to': "orm['auth.User']"})
+ },
+ 'askbot.repute': {
+ 'Meta': {'object_name': 'Repute', 'db_table': "u'repute'"},
+ 'comment': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}),
+ '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['askbot.Question']", 'null': 'True', 'blank': 'True'}),
+ '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']"})
+ },
+ 'askbot.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'})
+ },
+ 'askbot.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'})
+ },
+ '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_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'}),
+ 'response_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'new_response_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'seen_response_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'silver': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),
+ 'status': ('django.db.models.fields.CharField', [], {'default': "'w'", 'max_length': '2'}),
+ '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'})
+ }
+ }
+
+ complete_apps = ['askbot']
diff --git a/askbot/migrations/0027_populate_new_response_counts.py b/askbot/migrations/0027_populate_new_response_counts.py
new file mode 100644
index 00000000..2f0ec4e1
--- /dev/null
+++ b/askbot/migrations/0027_populate_new_response_counts.py
@@ -0,0 +1,313 @@
+# encoding: utf-8
+import datetime
+from south.db import db
+from south.v2 import DataMigration
+from django.db import models
+
+class Migration(DataMigration):
+
+ def forwards(self, orm):
+ """transfer value of response_count to new_response_count
+ """
+ for user in orm['auth.User'].objects.all():
+ user.new_response_count= user.response_count
+ user.save()
+
+
+ def backwards(self, orm):
+ """transfer a total of new and seen responses to response_count"""
+ for user in orm['auth.User'].objects.all():
+ user.response_count= user.new_response_count + user.seen_response_count
+ user.save()
+
+ models = {
+ 'askbot.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', [], {}),
+ 'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['askbot.Question']", 'null': 'True'}),
+ 'receiving_users': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'received_activity'", 'to': "orm['auth.User']"}),
+ 'recipients': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'incoming_activity'", 'through': "'ActivityAuditStatus'", 'to': "orm['auth.User']"}),
+ 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"})
+ },
+ 'askbot.activityauditstatus': {
+ 'Meta': {'unique_together': "(('user', 'activity'),)", 'object_name': 'ActivityAuditStatus'},
+ 'activity': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['askbot.Activity']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'status': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),
+ 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"})
+ },
+ 'askbot.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['askbot.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'})
+ },
+ 'askbot.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'})
+ },
+ 'askbot.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['askbot.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'})
+ },
+ 'askbot.answerrevision': {
+ 'Meta': {'object_name': 'AnswerRevision', 'db_table': "u'answer_revision'"},
+ 'answer': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'revisions'", 'to': "orm['askbot.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', [], {})
+ },
+ 'askbot.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['askbot.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']"})
+ },
+ 'askbot.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', [], {})
+ },
+ 'askbot.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', [], {}),
+ 'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'comments'", 'to': "orm['auth.User']"})
+ },
+ 'askbot.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']"})
+ },
+ 'askbot.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['askbot.Question']"}),
+ 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_favorite_questions'", 'to': "orm['auth.User']"})
+ },
+ 'askbot.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']"})
+ },
+ 'askbot.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['askbot.Tag']"}),
+ 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tag_selections'", 'to': "orm['auth.User']"})
+ },
+ 'askbot.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['askbot.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'})
+ },
+ 'askbot.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['askbot.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'})
+ },
+ 'askbot.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['askbot.Question']"}),
+ 'when': ('django.db.models.fields.DateTimeField', [], {}),
+ 'who': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'question_views'", 'to': "orm['auth.User']"})
+ },
+ 'askbot.repute': {
+ 'Meta': {'object_name': 'Repute', 'db_table': "u'repute'"},
+ 'comment': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}),
+ '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['askbot.Question']", 'null': 'True', 'blank': 'True'}),
+ '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']"})
+ },
+ 'askbot.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'})
+ },
+ 'askbot.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'})
+ },
+ '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_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'}),
+ 'response_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'silver': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),
+ 'status': ('django.db.models.fields.CharField', [], {'default': "'w'", 'max_length': '2'}),
+ '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'})
+ }
+ }
+
+ complete_apps = ['askbot']
diff --git a/askbot/migrations/0028_delete_response_count_column_from_user_model.py b/askbot/migrations/0028_delete_response_count_column_from_user_model.py
new file mode 100644
index 00000000..cd04bda9
--- /dev/null
+++ b/askbot/migrations/0028_delete_response_count_column_from_user_model.py
@@ -0,0 +1,311 @@
+# 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 fields
+ db.delete_column('auth_user', 'response_count')
+
+
+ def backwards(self, orm):
+ # Deleting fields
+ db.add_column('auth_user', 'response_count', self.gf('django.db.models.fields.IntegerField')(default=0), keep_default=False)
+
+
+ models = {
+ 'askbot.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', [], {}),
+ 'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['askbot.Question']", 'null': 'True'}),
+ 'receiving_users': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'received_activity'", 'to': "orm['auth.User']"}),
+ 'recipients': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'incoming_activity'", 'through': "'ActivityAuditStatus'", 'to': "orm['auth.User']"}),
+ 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"})
+ },
+ 'askbot.activityauditstatus': {
+ 'Meta': {'unique_together': "(('user', 'activity'),)", 'object_name': 'ActivityAuditStatus'},
+ 'activity': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['askbot.Activity']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'status': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),
+ 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"})
+ },
+ 'askbot.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['askbot.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'})
+ },
+ 'askbot.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'})
+ },
+ 'askbot.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['askbot.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'})
+ },
+ 'askbot.answerrevision': {
+ 'Meta': {'object_name': 'AnswerRevision', 'db_table': "u'answer_revision'"},
+ 'answer': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'revisions'", 'to': "orm['askbot.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', [], {})
+ },
+ 'askbot.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['askbot.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']"})
+ },
+ 'askbot.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', [], {})
+ },
+ 'askbot.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', [], {}),
+ 'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'comments'", 'to': "orm['auth.User']"})
+ },
+ 'askbot.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']"})
+ },
+ 'askbot.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['askbot.Question']"}),
+ 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_favorite_questions'", 'to': "orm['auth.User']"})
+ },
+ 'askbot.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']"})
+ },
+ 'askbot.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['askbot.Tag']"}),
+ 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tag_selections'", 'to': "orm['auth.User']"})
+ },
+ 'askbot.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['askbot.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'})
+ },
+ 'askbot.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['askbot.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'})
+ },
+ 'askbot.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['askbot.Question']"}),
+ 'when': ('django.db.models.fields.DateTimeField', [], {}),
+ 'who': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'question_views'", 'to': "orm['auth.User']"})
+ },
+ 'askbot.repute': {
+ 'Meta': {'object_name': 'Repute', 'db_table': "u'repute'"},
+ 'comment': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}),
+ '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['askbot.Question']", 'null': 'True', 'blank': 'True'}),
+ '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']"})
+ },
+ 'askbot.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'})
+ },
+ 'askbot.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'})
+ },
+ '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_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'}),
+ #'response_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'new_response_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'seen_response_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'silver': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),
+ 'status': ('django.db.models.fields.CharField', [], {'default': "'w'", 'max_length': '2'}),
+ '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'})
+ }
+ }
+
+ complete_apps = ['askbot']
diff --git a/askbot/migrations_api/__init__.py b/askbot/migrations_api/__init__.py
new file mode 100644
index 00000000..1e213613
--- /dev/null
+++ b/askbot/migrations_api/__init__.py
@@ -0,0 +1,10 @@
+"""this module serves as a helper for the South orm
+by mitigating absence of access to the django model api
+
+since models change with time, this api is implemented in different
+versions. Different versions do not need to have all the same functions.
+"""
+
+class BaseAPI(object):
+ def __init__(self, orm):
+ self.orm = orm
diff --git a/askbot/migrations_api/version1.py b/askbot/migrations_api/version1.py
new file mode 100644
index 00000000..cc63c09d
--- /dev/null
+++ b/askbot/migrations_api/version1.py
@@ -0,0 +1,63 @@
+"""Version 1 of API helper for the south orm
+usage of this api implementation starts with migration 24
+"""
+from askbot.migrations_api import BaseAPI
+from django.db import models
+#from django.contrib.contenttypes.models import ContentType
+
+class API(BaseAPI):
+ def get_origin_post_from_content_object(self, parent):
+ """follows relations from the parent object
+ until origin post (question) is found
+ starting point is always ``parent.content_object``
+ """
+ model = parent.content_type.model
+ id = parent.object_id
+ #print 'model is ' + model
+ if model == 'question':
+ return self.orm.Question.objects.get(id=id)
+ elif model == 'answer':
+ return self.orm.Answer.objects.get(id=id).question
+ elif model == 'favoritequestion':
+ try:
+ return self.orm.FavoriteQuestion.objects.get(id=id).question
+ except self.orm.FavoriteQuestion.DoesNotExist:
+ #ignore this issue for now
+ return None
+ elif model == 'answerrevision':
+ return self.orm.AnswerRevision.objects.get(id=id).answer.question
+ elif model == 'questionrevision':
+ return self.orm.QuestionRevision.objects.get(id=id).question
+ elif model == 'comment':
+ comment = self.orm.Comment.objects.get(id=id)
+ return self.get_question_from_generic_relation(comment)
+ else:
+ #print 'dropped migration of activity in %s' % model
+ return None
+
+ def get_moderators_and_admins(self):
+ """return list of forum moderators and django site admins
+ """
+ filter_expression = models.Q(status='m') | models.Q(is_superuser=True)
+ return self.orm['auth.User'].objects.filter(filter_expression)
+
+ def get_activity_items_for_object(self, instance):
+ """get all activity items that have content_object set
+ where ``<Activity instance>.content_object == instance``
+ """
+ return self.orm.Activity.objects.filter(
+ object_id = instance.id,
+ content_type = self.get_content_type_for_model(instance)
+ )
+
+ def get_content_type_for_model(self, instance):
+ ct = self.orm['contenttypes.ContentType'].objects
+ return ct.get(app_label='askbot', model=instance._meta.object_name.lower())
+
+ def add_recipients_to_activity(self, recipients, activity):
+ for recipient in recipients:
+ memo = self.orm.ActivityAuditStatus(
+ user = recipient,
+ activity = activity,
+ )
+ memo.save()
diff --git a/askbot/models/__init__.py b/askbot/models/__init__.py
index 4bb1293b..c0229ccf 100644
--- a/askbot/models/__init__.py
+++ b/askbot/models/__init__.py
@@ -76,7 +76,9 @@ User.add_to_class('tag_filter_setting',
default='ignored'
)
)
-User.add_to_class('response_count', models.IntegerField(default=0))
+User.add_to_class('new_response_count', models.IntegerField(default=0))
+User.add_to_class('seen_response_count', models.IntegerField(default=0))
+
def user_get_old_vote_for_post(self, post):
"""returns previous vote for this post
@@ -977,13 +979,6 @@ def user_visit_question(self, question = None, timestamp = None):
if timestamp is None:
timestamp = datetime.datetime.now()
- ACTIVITY_TYPES = const.RESPONSE_ACTIVITY_TYPES_FOR_DISPLAY
- ACTIVITY_TYPES += (const.TYPE_ACTIVITY_MENTION,)
- response_activities = Activity.objects.filter(
- recipients = self,
- activity_type__in = ACTIVITY_TYPES,
- question = question
- )
try:
question_view = QuestionView.objects.get(
who = self,
@@ -997,21 +992,36 @@ def user_visit_question(self, question = None, timestamp = None):
question_view.when = timestamp
question_view.save()
- #filter response activities (already directed to the qurrent user
- #as per the query in the beginning of this if branch)
+ #filter memo objects on response activities directed to the qurrent user
#that refer to the children of the currently
#viewed question and clear them for the current user
- need_to_save_user = False
+ ACTIVITY_TYPES = const.RESPONSE_ACTIVITY_TYPES_FOR_DISPLAY
+ ACTIVITY_TYPES += (const.TYPE_ACTIVITY_MENTION,)
audit_records = ActivityAuditStatus.objects.filter(
- activity__in = response_activities,
- user = self
- )
- if len(audit_records) > 0:
- self.decrement_response_count(len(audit_records))
+ user = self,
+ status = ActivityAuditStatus.STATUS_NEW,
+ activity__question = question
+ )
+
+ cleared_record_count = audit_records.filter(
+ activity__activity_type__in = ACTIVITY_TYPES
+ ).update(
+ status=ActivityAuditStatus.STATUS_SEEN
+ )
+ if cleared_record_count > 0:
+ self.decrement_response_count(cleared_record_count)
self.save()
- #todo: set status to seen and call update
- audit_records.delete()
+
+ #finally, mark admin memo objects if applicable
+ #the admin response counts are not denormalized b/c they are easy to obtain
+ if self.is_moderator() or self.is_administrator():
+ audit_records.filter(
+ activity__activity_type = const.TYPE_ACTIVITY_MARK_OFFENSIVE
+ ).update(
+ status=ActivityAuditStatus.STATUS_SEEN
+ )
+
def user_is_username_taken(cls,username):
try:
@@ -1362,7 +1372,7 @@ def user_increment_response_count(user):
"""increment response counter for user
by one
"""
- user.response_count += 1
+ user.new_response_count += 1
def user_decrement_response_count(user, amount=1):
"""decrement response count for the user
@@ -1370,10 +1380,11 @@ def user_decrement_response_count(user, amount=1):
but limit decrementation at zero exactly
"""
assert(amount > 0)
- if user.response_count >= amount:
- user.response_count -= amount
+ user.seen_response_count += amount
+ if user.new_response_count >= amount:
+ user.new_response_count -= amount
else:
- user.response_count = 0
+ user.new_response_count = 0
logging.critical(
'response count wanted to go below zero'
)
@@ -1796,9 +1807,13 @@ def record_flag_offensive(instance, mark_by, **kwargs):
question=instance.get_origin_post()
)
activity.save()
- recipients = instance.get_author_list(
- exclude_list = [mark_by]
- )
+# todo: report authors that their post is flagged offensive
+# recipients = instance.get_author_list(
+# exclude_list = [mark_by]
+# )
+ recipients = User.objects.filter(
+ models.Q(is_superuser=True) | models.Q(status='m')
+ )
activity.add_recipients(recipients)
def record_update_tags(question, **kwargs):
diff --git a/askbot/models/user.py b/askbot/models/user.py
index ad302705..fcf60639 100644
--- a/askbot/models/user.py
+++ b/askbot/models/user.py
@@ -9,6 +9,7 @@ from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes import generic
from django.contrib.auth.models import User
from django.utils.translation import ugettext as _
+from django.utils.html import strip_tags
from askbot import const
from askbot.utils import functions
@@ -148,6 +149,9 @@ class ActivityAuditStatus(models.Model):
app_label = 'askbot'
db_table = 'askbot_activityauditstatus'
+ def is_new(self):
+ return (self.status == self.STATUS_NEW)
+
class Activity(models.Model):
"""
@@ -193,6 +197,9 @@ class Activity(models.Model):
assert(user_count == 1)
return user_qs[0]
+ def get_preview(self):
+ return strip_tags(self.content_object.html)[:300]
+
def get_absolute_url(self):
return self.content_object.get_absolute_url()
diff --git a/askbot/skins/default/media/images/dialog-warning-off.png b/askbot/skins/default/media/images/dialog-warning-off.png
new file mode 100644
index 00000000..258e4d86
--- /dev/null
+++ b/askbot/skins/default/media/images/dialog-warning-off.png
Binary files differ
diff --git a/askbot/skins/default/media/images/dialog-warning.png b/askbot/skins/default/media/images/dialog-warning.png
new file mode 100644
index 00000000..a9e4ff39
--- /dev/null
+++ b/askbot/skins/default/media/images/dialog-warning.png
Binary files differ
diff --git a/askbot/skins/default/media/js/com.cnprog.post.js b/askbot/skins/default/media/js/com.cnprog.post.js
index 58c326e7..87b12a61 100644
--- a/askbot/skins/default/media/js/com.cnprog.post.js
+++ b/askbot/skins/default/media/js/com.cnprog.post.js
@@ -699,16 +699,6 @@ var questionRetagger = function(){
input.click(function(){return false});
};
- var setupButtonEventHandlers = function(button){
- button.keydown(function(e){
- if ((e.which && e.which == 13) || (e.keyCode && e.keyCode == 13)){
- doRetag();
- return false;
- }
- });
- button.click(doRetag);
- };
-
var createRetagForm = function(old_tags_string){
var div = $('<form method="post"></form>');
tagInput = $('<input id="retag_tags" type="text" autocomplete="off" name="tags" size="30"/>');
diff --git a/askbot/skins/default/media/js/com.cnprog.utils.js b/askbot/skins/default/media/js/com.cnprog.utils.js
index e0ce87c7..d9a4a0ee 100644
--- a/askbot/skins/default/media/js/com.cnprog.utils.js
+++ b/askbot/skins/default/media/js/com.cnprog.utils.js
@@ -15,6 +15,20 @@ var showMessage = function(object, msg) {
div.fadeIn("fast");
};
+var setupButtonEventHandlers = function(button, callback){
+ button.keydown(function(e){
+ if ((e.which && e.which == 13) || (e.keyCode && e.keyCode == 13)){
+ callback();
+ return false;
+ }
+ });
+ button.click(callback);
+};
+
+var setCheckBoxesIn = function(selector, value){
+ return $(selector + '> input[type=checkbox]').attr('checked', value);
+};
+
var notify = function() {
var visible = false;
return {
@@ -42,3 +56,5 @@ var notify = function() {
//Search Engine Keyword Highlight with Javascript
//http://scott.yang.id.au/code/se-hilite/
Hilite={elementid:"content",exact:true,max_nodes:1000,onload:true,style_name:"hilite",style_name_suffix:true,debug_referrer:""};Hilite.search_engines=[["local","q"],["cnprog\\.","q"],["google\\.","q"],["search\\.yahoo\\.","p"],["search\\.msn\\.","q"],["search\\.live\\.","query"],["search\\.aol\\.","userQuery"],["ask\\.com","q"],["altavista\\.","q"],["feedster\\.","q"],["search\\.lycos\\.","q"],["alltheweb\\.","q"],["technorati\\.com/search/([^\\?/]+)",1],["dogpile\\.com/info\\.dogpl/search/web/([^\\?/]+)",1,true]];Hilite.decodeReferrer=function(d){var g=null;var e=new RegExp("");for(var c=0;c<Hilite.search_engines.length;c++){var f=Hilite.search_engines[c];e.compile("^http://(www\\.)?"+f[0],"i");var b=d.match(e);if(b){var a;if(isNaN(f[1])){a=Hilite.decodeReferrerQS(d,f[1])}else{a=b[f[1]+1]}if(a){a=decodeURIComponent(a);if(f.length>2&&f[2]){a=decodeURIComponent(a)}a=a.replace(/\'|"/g,"");a=a.split(/[\s,\+\.]+/);return a}break}}return null};Hilite.decodeReferrerQS=function(f,d){var b=f.indexOf("?");var c;if(b>=0){var a=new String(f.substring(b+1));b=0;c=0;while((b>=0)&&((c=a.indexOf("=",b))>=0)){var e,g;e=a.substring(b,c);b=a.indexOf("&",c)+1;if(e==d){if(b<=0){return a.substring(c+1)}else{return a.substring(c+1,b-1)}}else{if(b<=0){return null}}}}return null};Hilite.hiliteElement=function(f,e){if(!e||f.childNodes.length==0){return}var c=new Array();for(var b=0;b<e.length;b++){e[b]=e[b].toLowerCase();if(Hilite.exact){c.push("\\b"+e[b]+"\\b")}else{c.push(e[b])}}c=new RegExp(c.join("|"),"i");var a={};for(var b=0;b<e.length;b++){if(Hilite.style_name_suffix){a[e[b]]=Hilite.style_name+(b+1)}else{a[e[b]]=Hilite.style_name}}var d=function(m){var j=c.exec(m.data);if(j){var n=j[0];var i="";var h=m.splitText(j.index);var g=h.splitText(n.length);var l=m.ownerDocument.createElement("SPAN");m.parentNode.replaceChild(l,h);l.className=a[n.toLowerCase()];l.appendChild(h);return l}else{return m}};Hilite.walkElements(f.childNodes[0],1,d)};Hilite.hilite=function(){var a=Hilite.debug_referrer?Hilite.debug_referrer:document.referrer;var b=null;a=Hilite.decodeReferrer(a);if(a&&((Hilite.elementid&&(b=document.getElementById(Hilite.elementid)))||(b=document.body))){Hilite.hiliteElement(b,a)}};Hilite.walkElements=function(d,f,e){var a=/^(script|style|textarea)/i;var c=0;while(d&&f>0){c++;if(c>=Hilite.max_nodes){var b=function(){Hilite.walkElements(d,f,e)};setTimeout(b,50);return}if(d.nodeType==1){if(!a.test(d.tagName)&&d.childNodes.length>0){d=d.childNodes[0];f++;continue}}else{if(d.nodeType==3){d=e(d)}}if(d.nextSibling){d=d.nextSibling}else{while(f>0){d=d.parentNode;f--;if(d.nextSibling){d=d.nextSibling;break}}}}};if(Hilite.onload){if(window.attachEvent){window.attachEvent("onload",Hilite.hilite)}else{if(window.addEventListener){window.addEventListener("load",Hilite.hilite,false)}else{var __onload=window.onload;window.onload=function(){Hilite.hilite();__onload()}}}};
+/* json2.js by D. Crockford */
+if(!this.JSON){this.JSON={}}(function(){function f(n){return n<10?"0"+n:n}if(typeof Date.prototype.toJSON!=="function"){Date.prototype.toJSON=function(key){return isFinite(this.valueOf())?this.getUTCFullYear()+"-"+f(this.getUTCMonth()+1)+"-"+f(this.getUTCDate())+"T"+f(this.getUTCHours())+":"+f(this.getUTCMinutes())+":"+f(this.getUTCSeconds())+"Z":null};String.prototype.toJSON=Number.prototype.toJSON=Boolean.prototype.toJSON=function(key){return this.valueOf()}}var cx=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,escapable=/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,gap,indent,meta={"\b":"\\b","\t":"\\t","\n":"\\n","\f":"\\f","\r":"\\r",'"':'\\"',"\\":"\\\\"},rep;function quote(string){escapable.lastIndex=0;return escapable.test(string)?'"'+string.replace(escapable,function(a){var c=meta[a];return typeof c==="string"?c:"\\u"+("0000"+a.charCodeAt(0).toString(16)).slice(-4)})+'"':'"'+string+'"'}function str(key,holder){var i,k,v,length,mind=gap,partial,value=holder[key];if(value&&typeof value==="object"&&typeof value.toJSON==="function"){value=value.toJSON(key)}if(typeof rep==="function"){value=rep.call(holder,key,value)}switch(typeof value){case"string":return quote(value);case"number":return isFinite(value)?String(value):"null";case"boolean":case"null":return String(value);case"object":if(!value){return"null"}gap+=indent;partial=[];if(Object.prototype.toString.apply(value)==="[object Array]"){length=value.length;for(i=0;i<length;i+=1){partial[i]=str(i,value)||"null"}v=partial.length===0?"[]":gap?"[\n"+gap+partial.join(",\n"+gap)+"\n"+mind+"]":"["+partial.join(",")+"]";gap=mind;return v}if(rep&&typeof rep==="object"){length=rep.length;for(i=0;i<length;i+=1){k=rep[i];if(typeof k==="string"){v=str(k,value);if(v){partial.push(quote(k)+(gap?": ":":")+v)}}}}else{for(k in value){if(Object.hasOwnProperty.call(value,k)){v=str(k,value);if(v){partial.push(quote(k)+(gap?": ":":")+v)}}}}v=partial.length===0?"{}":gap?"{\n"+gap+partial.join(",\n"+gap)+"\n"+mind+"}":"{"+partial.join(",")+"}";gap=mind;return v}}if(typeof JSON.stringify!=="function"){JSON.stringify=function(value,replacer,space){var i;gap="";indent="";if(typeof space==="number"){for(i=0;i<space;i+=1){indent+=" "}}else{if(typeof space==="string"){indent=space}}rep=replacer;if(replacer&&typeof replacer!=="function"&&(typeof replacer!=="object"||typeof replacer.length!=="number")){throw new Error("JSON.stringify")}return str("",{"":value})}}if(typeof JSON.parse!=="function"){JSON.parse=function(text,reviver){var j;function walk(holder,key){var k,v,value=holder[key];if(value&&typeof value==="object"){for(k in value){if(Object.hasOwnProperty.call(value,k)){v=walk(value,k);if(v!==undefined){value[k]=v}else{delete value[k]}}}}return reviver.call(holder,key,value)}text=String(text);cx.lastIndex=0;if(cx.test(text)){text=text.replace(cx,function(a){return"\\u"+("0000"+a.charCodeAt(0).toString(16)).slice(-4)})}if(/^[\],:{}\s]*$/.test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,"@").replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,"]").replace(/(?:^|:|,)(?:\s*\[)+/g,""))){j=eval("("+text+")");return typeof reviver==="function"?walk({"":j},""):j}throw new SyntaxError("JSON.parse")}}}());
diff --git a/askbot/skins/default/media/js/user.js b/askbot/skins/default/media/js/user.js
new file mode 100644
index 00000000..7877a828
--- /dev/null
+++ b/askbot/skins/default/media/js/user.js
@@ -0,0 +1,99 @@
+$(document).ready(function(){
+
+ var getSelected = function(){
+
+ var id_list = new Array();
+ var elements = $('#responses input:checked').parent();
+
+ elements.each(function(index, element){
+ var id = $(element).attr('id').replace(/^re_/,'');
+ id_list.push(id);
+ });
+
+ if (id_list.length === 0){
+ alert($.i18n._('Please select at least one item'));
+ }
+
+ return {id_list: id_list, elements: elements};
+ };
+
+ var submit = function(id_list, elements, action_type){
+ if (action_type == 'delete' || action_type == 'mark_new' || action_type == 'mark_seen'){
+ $.ajax({
+ type: 'POST',
+ cache: false,
+ dataType: 'json',
+ data: JSON.stringify({memo_list: id_list, action_type: action_type}),
+ url: askbot['urls']['manageInbox'],
+ success: function(response_data){
+ if (response_data['success'] === true){
+ if (action_type == 'delete'){
+ elements.remove();
+ }
+ else if (action_type == 'mark_new'){
+ elements.addClass('highlight');
+ elements.addClass('new');
+ elements.removeClass('seen');
+ }
+ else if (action_type == 'mark_seen'){
+ elements.removeClass('highlight');
+ elements.addClass('seen');
+ elements.removeClass('new');
+ }
+ }
+ else {
+ showMessage($('#responses'), response_data['message']);
+ }
+ }
+ });
+ }
+ };
+
+ var startAction = function(action_type){
+ var data = getSelected();
+ if (data['id_list'].length === 0){
+ return;
+ }
+ if (action_type == 'delete'){
+ if (data['id_list'].length === 1){
+ var msg = $.i18n._('Delete this notification?')
+ }
+ else {
+ var msg = $.i18n._('Delete these notifications?')
+ }
+ if (confirm(msg) === false){
+ return;
+ }
+ }
+ submit(data['id_list'], data['elements'], action_type);
+ };
+ setupButtonEventHandlers($('#re_mark_seen'), function(){startAction('mark_seen')});
+ setupButtonEventHandlers($('#re_mark_new'), function(){startAction('mark_new')});
+ setupButtonEventHandlers($('#re_dismiss'), function(){startAction('delete')});
+ setupButtonEventHandlers(
+ $('#sel_all'),
+ function(){
+ setCheckBoxesIn('#responses .new', true);
+ setCheckBoxesIn('#responses .seen', true);
+ }
+ );
+ setupButtonEventHandlers(
+ $('#sel_seen'),
+ function(){
+ setCheckBoxesIn('#responses .seen', true);
+ }
+ );
+ setupButtonEventHandlers(
+ $('#sel_new'),
+ function(){
+ setCheckBoxesIn('#responses .new', true);
+ }
+ );
+ setupButtonEventHandlers(
+ $('#sel_none'),
+ function(){
+ setCheckBoxesIn('#responses .new', false);
+ setCheckBoxesIn('#responses .seen', false);
+ }
+ );
+});
diff --git a/askbot/skins/default/media/style/style.css b/askbot/skins/default/media/style/style.css
index b01cbbab..ff5ceacc 100755
--- a/askbot/skins/default/media/style/style.css
+++ b/askbot/skins/default/media/style/style.css
@@ -949,7 +949,7 @@ a:hover.medal {
border-right: 1px solid #D1CA3D;
}
-/*Tab栏*/
+/*Tabs*/
.tabBar {
background-color: #FFF;
border-bottom: 1px solid white;
@@ -2732,6 +2732,38 @@ img.gravatar {
text-decoration: underline;
}
+#responses {
+ clear:both;
+ line-height:18px;
+ margin-bottom:15px;
+}
+
+#responses div.face {
+ float:left;
+ text-align: center;
+ width: 54px;
+ padding: 3px;
+ overflow:hidden;
+}
+
+.re {
+ min-height: 57px;
+ clear: both;
+}
+
+#responses input {
+ float:left;
+}
+#re_tools {
+ margin-bottom:10px;
+}
+#re_sections {
+ margin-bottom:6px;
+}
+#re_sections .on {
+ font-weight:bold;
+}
+
/* Pretty printing styles. Used with prettify.js. */
.str { color: #080; }
diff --git a/askbot/skins/default/templates/header.html b/askbot/skins/default/templates/header.html
index e549fa69..03e641e0 100644
--- a/askbot/skins/default/templates/header.html
+++ b/askbot/skins/default/templates/header.html
@@ -6,18 +6,47 @@
{% if request.user.is_authenticated() %}
<a href="{{ request.user.get_absolute_url() }}">{{ request.user.username }}</a>
{% spaceless %}
- <a class='ab-responses-envelope' href="{{request.user.get_absolute_url()}}?sort=responses">
+ {% if request.user.new_response_count > 0 or request.user.seen_response_count > 0 %}
+ <a class='ab-responses-envelope' href="{{request.user.get_absolute_url()}}?sort=inbox&section=forum">
<img
alt="{% trans username=request.user.username %}responses for {{username}}{% endtrans %}"
- {% if request.user.response_count > 0 %}
- src="{{ "/images/mail-envelope-full.png"|media }}"
- title="{% trans response_count=request.user.response_count %}you have a new response{% pluralize %}you nave {{response_count}} new responses{% endtrans %}"
- {% else %}
- src="{{ "/images/mail-envelope-empty.png"|media }}"
- title="{% trans %}no new responses yet{% endtrans %}"
+ {% if request.user.new_response_count > 0 %}
+ src="{{ "/images/mail-envelope-full.png"|media }}"
+ title="{% trans response_count=request.user.new_response_count %}you have a new response{% pluralize %}you nave {{response_count}} new responses{% endtrans %}"
+ {% elif request.user.seen_response_count > 0 %}
+ src="{{ "/images/mail-envelope-empty.png"|media }}"
+ title="{% trans %}no new responses yet{% endtrans %}"
{% endif %}
/>
</a>
+ {% endif %}
+ {% if moderation_items %}
+ <a class="ab-responses-envelope"
+ href="{{request.user.get_absolute_url()}}?sort=inbox&section=flags"
+ >
+ {% if moderation_items['new_count'] > 0 %}
+ <img src="{{'/images/dialog-warning.png'|media}}"
+ {% if moderation_items['seen_count'] > 0 %}
+ alt="{% trans new=moderation_items['new_count'], seen=moderation_items['seen_count']%}{{new}} new flagged posts and {{seen}} previous{% endtrans %}"
+ title="{% trans new=moderation_items['new_count'], seen=moderation_items['seen_count']%}{{new}} new flagged posts and {{seen}} previous{% endtrans %}"
+ {% else %}
+ alt="{% trans new=moderation_items['new_count'] %}{{new}} new flagged posts{% endtrans %}"
+ title="{% trans new=moderation_items['new_count'] %}{{new}} new flagged posts{% endtrans %}"
+ {% endif %}
+ />
+ {% elif moderation_items['seen_count'] > 0 %}
+ <img src={{'/images/dialog-warning-off.png'|media}}
+ alt="{% trans seen=moderation_items['seen_count'] %}{{seen}} flagged posts{% endtrans %}"
+ title="{% trans seen=moderation_items['seen_count'] %}{{seen}} flagged posts{% endtrans %}"
+ />
+ {% endif %}
+ </a>
+ {% endif %}
+ {#
+ {% endif %}
+ {% else if moderation_items['seen_count'] > 0 %}
+ {% endif %}
+ {% endif %#}
{% endspaceless %}
({{ macros.user_long_score_and_badge_summary(user) }})
<a href="{% url logout %}">{% trans %}logout{% endtrans %}</a>
diff --git a/askbot/skins/default/templates/macros.html b/askbot/skins/default/templates/macros.html
index 0df4a503..c9ccb562 100644
--- a/askbot/skins/default/templates/macros.html
+++ b/askbot/skins/default/templates/macros.html
@@ -24,7 +24,7 @@
<a class="user-micro-info"
href="{{user.get_absolute_url()}}?sort=reputation"
>{% trans %}karma:{% endtrans %} {{user.reputation}}</a>
- {% if user.gold or user.silver or user.bronze %}
+ {%- if user.gold or user.silver or user.bronze %}
<a class="user-micro-info"
href="{{user.get_absolute_url()}}#badges"
><span title="{{user.get_badge_summary}}">{% trans %}badges:{% endtrans %}
@@ -39,9 +39,9 @@
{% if user.bronze %}
<span class='badge3'>&#9679;</span>
<span class="badgecount">{{user.bronze}}</span>
- {% endif %}
+ {%- endif -%}
</span></a>
- {% endif %}
+ {%- endif -%}
{%- endmacro -%}
{%- macro paginator(p) -%}{# p is paginator context dictionary #}
diff --git a/askbot/skins/default/templates/questions.html b/askbot/skins/default/templates/questions.html
index ed9d36fb..aa68d86f 100644
--- a/askbot/skins/default/templates/questions.html
+++ b/askbot/skins/default/templates/questions.html
@@ -250,7 +250,9 @@
});
</script>
<script type='text/javascript' src='{{"/js/com.cnprog.editor.js"|media}}'></script>
+ {% if request.user.is_authenticated() %}
<script type='text/javascript' src='{{"/js/com.cnprog.tag_selector.js"|media}}'></script>
+ {% endif %}
<script type="text/javascript" src="{{"/js/live_search.js"|media}}"></script>
{% endblock %}
<!-- end questions.html -->
diff --git a/askbot/skins/default/templates/user.html b/askbot/skins/default/templates/user.html
index 2193fa61..ec84dadc 100644
--- a/askbot/skins/default/templates/user.html
+++ b/askbot/skins/default/templates/user.html
@@ -7,21 +7,6 @@
.user-stats-table { margin-left:50px; }
</style>
{% endblock %}
-{% block forejs %}
- {% if request.user|can_moderate_user(view_user) %}
- <!-- todo: add condition that scripts are loaded for admins only -->
- <script type='text/javascript' src='{{"/js/com.cnprog.admin.js"|media}}'></script>
- <script type='text/javascript' src='{{"/js/jquery.form.js"|media}}'></script>
- {% endif %}
- <script type="text/javascript">
- var viewUserID = {{view_user.id}};
- $().ready(function(){
- $("#nav_users").attr('className',"on");
- });
- </script>
- {% block userjs %}
- {% endblock %}
-{% endblock %}
{% block content %}
<div id="mainbar-full">
<div id="subheader" class="headUser">
@@ -36,3 +21,19 @@
{% endblock %}
</div>
{% endblock %}<!-- end user.html -->
+{% block endjs %}
+ {% if request.user|can_moderate_user(view_user) %}
+ <!-- todo: add condition that scripts are loaded for admins only -->
+ <script type='text/javascript' src='{{"/js/com.cnprog.admin.js"|media}}'></script>
+ <script type='text/javascript' src='{{"/js/jquery.form.js"|media}}'></script>
+ {% endif %}
+ <script type="text/javascript">
+ var viewUserID = {{view_user.id}};
+ $().ready(function(){
+ $("#nav_users").attr('className',"on");
+ });
+ </script>
+ {% block userjs %}
+ {% endblock %}
+{% endblock %}
+<!-- end of user.html -->
diff --git a/askbot/skins/default/templates/user_edit.html b/askbot/skins/default/templates/user_edit.html
index 3c6a0b1b..3fe78375 100644
--- a/askbot/skins/default/templates/user_edit.html
+++ b/askbot/skins/default/templates/user_edit.html
@@ -2,16 +2,6 @@
{% import "macros.html" as macros %}
<!-- user_edit.html -->
{% block title %}{% spaceless %}{% trans %}Edit user profile{% endtrans %}{% endspaceless %}{% endblock %}
-{% block forejs %}
- <script type="text/javascript">
- $().ready(function(){
- $("#nav_profile").attr('className',"on");
- $("#cancel").bind('click', function(){history.go(-1);})
- });
- </script>
- {% block userjs %}
- {% endblock %}
-{% endblock %}
{% block content %}
<div id="main-bar" class="headNormal">
{{ request.user.username }} - {% trans %}edit profile{% endtrans %}
@@ -88,4 +78,14 @@
</form>
</div>
{% endblock %}
+{% block endjs %}
+ <script type="text/javascript">
+ $().ready(function(){
+ $("#nav_profile").attr('className',"on");
+ $("#cancel").bind('click', function(){history.go(-1);})
+ });
+ </script>
+ {% block userjs %}
+ {% endblock %}
+{% endblock %}
<!-- end user_edit.html -->
diff --git a/askbot/skins/default/templates/user_inbox.html b/askbot/skins/default/templates/user_inbox.html
new file mode 100644
index 00000000..0904a302
--- /dev/null
+++ b/askbot/skins/default/templates/user_inbox.html
@@ -0,0 +1,85 @@
+{% extends "user.html" %}
+{% import "macros.html" as macros %}
+<!-- user_responses.html -->
+{#
+This template accepts a list of response list
+they are a generalized form of any response and
+
+The following properties of response object are used:
+timestamp - when it happened
+user - user who gave response (database object)
+response_type - type of response
+response_url - link to the question
+response_title - title of the question
+response_snippet - abbreviated content of the response
+inbox_section - forum|flags
+#}
+{% block usercontent %}
+ <div style="padding-top:5px;font-size:13px;">
+ {% set re_count = request.user.new_response_count +
+ request.user.seen_response_count
+ %}
+ {% if moderation_items %}
+ {% set flag_count = moderation_items['new_count'] +
+ moderation_items['seen_count']
+ %}
+ {% else %}
+ {% set flag_count = 0 %}
+ {% endif %}
+ {% if re_count > 0 and flag_count > 0 %}
+ <div id="re_sections">
+ {% trans %}Sections:{% endtrans %}
+ <a href="{{request.user.get_absolute_url()}}?sort=inbox&section=forum"
+ {% if inbox_section == 'forum' %}class="on"{% endif %}
+ >
+ {% trans %}forum responses ({{re_count}}){% endtrans -%}
+ </a> |
+ <a href="{{request.user.get_absolute_url()}}?sort=inbox&section=flags"
+ {% if inbox_section == 'flags' %}class="on"{% endif %}
+ >
+ {% trans %}flagged items ({{flag_count}}){% endtrans %}
+ </a>
+ </div>
+ {% endif %}
+ {% if inbox_section == 'forum' %}
+ <div id="re_tools">
+ <strong>{% trans %}select:{% endtrans %}</strong>
+ <a id="sel_all">{% trans %}all{% endtrans %}</a> |
+ <a id="sel_seen">{% trans %}seen{% endtrans %}</a> |
+ <a id="sel_new">{% trans %}new{% endtrans %}</a> |
+ <a id="sel_none">{% trans %}none{% endtrans %}</a><br />
+ <button id="re_mark_seen">{% trans %}mark as seen{% endtrans %}</button>
+ <button id="re_mark_new">{% trans %}mark as new{% endtrans %}</button>
+ <button id="re_dismiss">{% trans %}dismiss{% endtrans %}</button>
+ </div>
+ {% endif %}
+ <div id="responses">
+ {% for response in responses %}
+ <div id="re_{{response.id}}"
+ class="re{% if response.is_new %} new highlight{% else %} seen{% endif %}"
+ >
+ {% if inbox_section == 'forum' %}<input type="checkbox" />{% endif %}
+ <div class="face">
+ {{ macros.gravatar(response.user, 48) }}
+ </div>
+ <a style="font-size:12px" href="{{ response.user.get_absolute_url() }}">{{ response.user.username }}</a>
+ <a style="text-decoration:none;" href="{{ response.response_url }}">
+ {{ response.response_type }}
+ ({{ response.timestamp|diff_date(3, True) }}):<br/>
+ <strong>"{{ response.response_title|escape}}"</strong>&nbsp;
+ {{ response.response_snippet }}
+ </a>
+ </div>
+ {% endfor %}
+ </div>
+ </div>
+{% endblock %}
+{% block userjs %}
+ <script type="text/javascript" src="{{'/js/user.js'|media}}"></script>
+ <script type="text/javascript">
+ var askbot = askbot || {};
+ askbot['urls'] = askbot['urls'] || {};
+ askbot['urls']['manageInbox'] = '{% url manage_inbox %}';
+ </script>
+<!-- end user_responses.html -->
+{% endblock %}
diff --git a/askbot/skins/default/templates/user_reputation.html b/askbot/skins/default/templates/user_reputation.html
index 120e5259..dd9d341d 100644
--- a/askbot/skins/default/templates/user_reputation.html
+++ b/askbot/skins/default/templates/user_reputation.html
@@ -1,20 +1,5 @@
{% extends "user.html" %}
<!-- user_reputation.html -->
-{% block userjs %}
- <script type='text/javascript' src='{{"/js/excanvas.min.js"|media}}'></script>
- <script type='text/javascript' src='{{"/js/jquery.flot.min.js"|media}}'></script>
- <script type="text/javascript">
- $().ready(function(){
- var d = {{ reps }};
- var placeholder = $("#diagram");
- var plot = $.plot(placeholder, [d], {
- xaxis: { mode: "time" },
- points: { show: true },
- lines: { show: true }
- });
- });
- </script>
-{% endblock %}
{% block usercontent %}
<div class="karma-summary">
<div id="diagram" class="karma-diagram"></div>
@@ -34,4 +19,19 @@
{% endfor %}
</div>
</div>
+{% endblock %}
+{% block userjs %}
+ <script type='text/javascript' src='{{"/js/excanvas.min.js"|media}}'></script>
+ <script type='text/javascript' src='{{"/js/jquery.flot.min.js"|media}}'></script>
+ <script type="text/javascript">
+ $().ready(function(){
+ var d = {{ reps }};
+ var placeholder = $("#diagram");
+ var plot = $.plot(placeholder, [d], {
+ xaxis: { mode: "time" },
+ points: { show: true },
+ lines: { show: true }
+ });
+ });
+ </script>
{% endblock %}<!-- end user_reputation.html -->
diff --git a/askbot/skins/default/templates/user_responses.html b/askbot/skins/default/templates/user_responses.html
deleted file mode 100644
index 6cf65b1f..00000000
--- a/askbot/skins/default/templates/user_responses.html
+++ /dev/null
@@ -1,36 +0,0 @@
-{% extends "user.html" %}
-{% import "macros.html" as macros %}
-<!-- user_responses.html -->
-{#
-This template accepts a list of response list
-they are a generalized form of any response and
-
-The following properties of response object are used:
-timestamp - when it happened
-user - user who gave response (database object)
-response_type - type of response
-response_url - link to the question
-response_title - title of the question
-response_snippet - abbreviated content of the response
-#}
-{% block usercontent %}
- <div style="padding-top:5px;font-size:13px;">
- {% for response in responses %}
- <div style="clear:both;line-height:18px;margin-bottom:15px;">
- <div>
- <div style="float:left; display:inline-block; text-align: center; width: 54px; padding: 3px;overflow:hidden;">
- {{ macros.gravatar(response.user, 48) }}
- </div>
- <a style="font-size:12px" href="{{ response.user.get_absolute_url() }}">{{ response.user.username }}</a>
- <a style="text-decoration:none;" href="{{ response.response_url }}">
- {{ response.response_type }}
- ({{ response.timestamp|diff_date(3, True) }}):<br/>
- <strong>"{{ response.response_title|escape}}"</strong>&nbsp;
- {{ response.response_snippet }}
- </a>
- </div>
- </div>
- {% endfor %}
- </div>
-{% endblock %}
-<!-- end user_responses.html -->
diff --git a/askbot/skins/default/templates/user_tabs.html b/askbot/skins/default/templates/user_tabs.html
index 9ea39682..bf63ae77 100644
--- a/askbot/skins/default/templates/user_tabs.html
+++ b/askbot/skins/default/templates/user_tabs.html
@@ -1,28 +1,28 @@
<!-- user_tabs.html -->
<div class="tabBar">
- <div class="tabsA">
+ <div class="tabsC">
<a id="stats" {% if tab_name=="stats" %}class="on"{% endif %}
title="{% trans %}User profile{% endtrans %}"
href="{% url user_profile view_user.id, view_user.username|slugify %}?sort=stats">{% trans %}overview{% endtrans %}</a>
- <a id="recent" {% if tab_name=="recent" %}class="on"{% endif %}
- title="{% trans %}recent activity{% endtrans %}"
- href="{% url user_profile view_user.id, view_user.username|slugify %}?sort=recent">{% trans %}activity{% endtrans %}</a>
{% if request.user == view_user or request.user|can_moderate_user(view_user) %}
- <a id="responses" {% if tab_name=="responses" %}class="on"{% endif %}
+ <a id="inbox" {% if tab_name=="inbox" %}class="on"{% endif %}
title="{% trans %}comments and answers to others questions{% endtrans %}"
- href="{% url user_profile view_user.id, view_user.username|slugify %}?sort=responses">{% trans %}responses{% endtrans %}</a>
+ href="{% url user_profile view_user.id, view_user.username|slugify %}?sort=inbox">{% trans %}inbox{% endtrans %}</a>
{% endif %}
<a id="reputation" {% if tab_name=="reputation" %}class="on"{% endif %}
title="{% trans %}graph of user reputation{% endtrans %}"
href="{% url user_profile view_user.id, view_user.username|slugify %}?sort=reputation">{% trans %}reputation history{% endtrans %}</a>
+ <a id="favorites" {% if tab_name=="favorites" %}class="on"{% endif %}
+ title="{% trans %}questions that user selected as his/her favorite{% endtrans %}"
+ href="{% url user_profile view_user.id, view_user.username|slugify %}?sort=favorites">{% trans %}favorites{% endtrans %}</a>
+ <a id="recent" {% if tab_name=="recent" %}class="on"{% endif %}
+ title="{% trans %}recent activity{% endtrans %}"
+ href="{% url user_profile view_user.id, view_user.username|slugify %}?sort=recent">{% trans %}activity{% endtrans %}</a>
{% if request.user == view_user or request.user|can_moderate_user(view_user) %}
<a id="votes" {% if tab_name=="votes" %}class="on"{% endif %}
title="{% trans %}user vote record{% endtrans %}"
href="{% url user_profile view_user.id, view_user.username|slugify %}?sort=votes">{% trans %}casted votes{% endtrans %}</a>
{% endif %}
- <a id="favorites" {% if tab_name=="favorites" %}class="on"{% endif %}
- title="{% trans %}questions that user selected as his/her favorite{% endtrans %}"
- href="{% url user_profile view_user.id, view_user.username|slugify %}?sort=favorites">{% trans %}favorites{% endtrans %}</a>
{% if request.user == view_user or request.user|can_moderate_user(view_user) %}
<a id="email_subscriptions" {% if tab_name=="email_subscriptions" %}class="on"{% endif %}
title="{% trans %}email subscription settings{% endtrans %}"
diff --git a/askbot/tests/on_screen_notification_tests.py b/askbot/tests/on_screen_notification_tests.py
index 68e51d33..f8da736e 100644
--- a/askbot/tests/on_screen_notification_tests.py
+++ b/askbot/tests/on_screen_notification_tests.py
@@ -34,8 +34,10 @@ class OnScreenUpdateNotificationTests(TestCase):
def reset_response_counts(self):
self.reload_users()
+ models.ActivityAuditStatus.objects.all().delete()
for user in self.users:
- user.response_count = 0
+ user.new_response_count = 0
+ user.seen_response_count = 0
user.save()
def reload_users(self):
@@ -141,22 +143,42 @@ class OnScreenUpdateNotificationTests(TestCase):
comment = 'comment33'
)
- def assertResponseCountsEqual(self, counts_vector):
+ def assertNewResponseCountsEqual(self, counts_vector):
self.reload_users()
self.assertEquals(
[
- self.u11.response_count,
- self.u12.response_count,
- self.u13.response_count,
- self.u14.response_count,
- self.u21.response_count,
- self.u22.response_count,
- self.u23.response_count,
- self.u24.response_count,
- self.u31.response_count,
- self.u32.response_count,
- self.u33.response_count,
- self.u34.response_count,
+ self.u11.new_response_count,
+ self.u12.new_response_count,
+ self.u13.new_response_count,
+ self.u14.new_response_count,
+ self.u21.new_response_count,
+ self.u22.new_response_count,
+ self.u23.new_response_count,
+ self.u24.new_response_count,
+ self.u31.new_response_count,
+ self.u32.new_response_count,
+ self.u33.new_response_count,
+ self.u34.new_response_count,
+ ],
+ counts_vector
+ )
+
+ def assertSeenResponseCountsEqual(self, counts_vector):
+ self.reload_users()
+ self.assertEquals(
+ [
+ self.u11.seen_response_count,
+ self.u12.seen_response_count,
+ self.u13.seen_response_count,
+ self.u14.seen_response_count,
+ self.u21.seen_response_count,
+ self.u22.seen_response_count,
+ self.u23.seen_response_count,
+ self.u24.seen_response_count,
+ self.u31.seen_response_count,
+ self.u32.seen_response_count,
+ self.u33.seen_response_count,
+ self.u34.seen_response_count,
],
counts_vector
)
@@ -195,7 +217,7 @@ class OnScreenUpdateNotificationTests(TestCase):
comment.delete()
notifications = get_re_notif_after(timestamp)
self.assertEqual(len(notifications), 0)
- self.assertResponseCountsEqual(
+ self.assertNewResponseCountsEqual(
[
0, 0, 0, 0,
0, 0, 0, 0,
@@ -213,7 +235,7 @@ class OnScreenUpdateNotificationTests(TestCase):
comment.delete()
notifications = get_re_notif_after(timestamp)
self.assertEqual(len(notifications), 0)
- self.assertResponseCountsEqual(
+ self.assertNewResponseCountsEqual(
[
0, 0, 0, 0,
0, 0, 0, 0,
@@ -236,7 +258,7 @@ class OnScreenUpdateNotificationTests(TestCase):
set(notifications[0].recipients.all()),
set([self.u12, self.u13]),
)
- self.assertResponseCountsEqual(
+ self.assertNewResponseCountsEqual(
[
0, 1, 1, 0,
0, 0, 0, 0,
@@ -257,7 +279,7 @@ class OnScreenUpdateNotificationTests(TestCase):
set(notifications[0].recipients.all()),
set([self.u22, self.u23]),
)
- self.assertResponseCountsEqual(
+ self.assertNewResponseCountsEqual(
[
0, 0, 0, 0,
0, 1, 1, 0,
@@ -280,7 +302,7 @@ class OnScreenUpdateNotificationTests(TestCase):
set(notifications[0].recipients.all()),
set([self.u12, self.u13]),
)
- self.assertResponseCountsEqual(
+ self.assertNewResponseCountsEqual(
[
0, 1, 1, 0,
0, 0, 0, 0,
@@ -303,7 +325,7 @@ class OnScreenUpdateNotificationTests(TestCase):
set(notifications[0].recipients.all()),
set([self.u12, self.u13]),
)
- self.assertResponseCountsEqual(
+ self.assertNewResponseCountsEqual(
[
0, 1, 1, 0,
0, 0, 0, 0,
@@ -326,7 +348,7 @@ class OnScreenUpdateNotificationTests(TestCase):
set(notifications[0].recipients.all()),
set([self.u22, self.u23]),
)
- self.assertResponseCountsEqual(
+ self.assertNewResponseCountsEqual(
[
0, 0, 0, 0,
0, 1, 1, 0,
@@ -356,28 +378,54 @@ class OnScreenUpdateNotificationTests(TestCase):
set(notifications[0].recipients.all()),
set([self.u11, self.u12, self.u13])#all users are notified
)
- self.assertResponseCountsEqual(
+ self.assertNewResponseCountsEqual(
[
1, 1, 1, 0,
0, 0, 0, 0,
0, 0, 0, 0,
]
)
+ self.assertSeenResponseCountsEqual(
+ [
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ ]
+ )
self.u11.visit_question(self.question)
self.u12.visit_question(self.question)
notifications = get_re_notif_after(timestamp)
self.assertEqual(len(notifications), 1)
self.assertEqual(#visitors are not notified
set(notifications[0].recipients.all()),
- set([self.u13])
+ set([self.u11, self.u12, self.u13])
+ )
+ self.assertEqual(
+ self.u11.activityauditstatus_set.all()[0].status,
+ models.ActivityAuditStatus.STATUS_SEEN
+ )
+ self.assertEqual(
+ self.u12.activityauditstatus_set.all()[0].status,
+ models.ActivityAuditStatus.STATUS_SEEN
+ )
+ self.assertEqual(
+ self.u13.activityauditstatus_set.all()[0].status,
+ models.ActivityAuditStatus.STATUS_NEW
)
- self.assertResponseCountsEqual(
+ self.assertNewResponseCountsEqual(
[
0, 0, 1, 0,
0, 0, 0, 0,
0, 0, 0, 0,
]
)
+ self.assertSeenResponseCountsEqual(
+ [
+ 1, 1, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ ]
+ )
def test_comments_to_post_authors(self):
@@ -400,7 +448,7 @@ class OnScreenUpdateNotificationTests(TestCase):
set(notifications[0].recipients.all()),
set([self.u11, self.u13, self.u14]),
)
- self.assertResponseCountsEqual(
+ self.assertNewResponseCountsEqual(
[
1, 0, 1, 1,
0, 0, 0, 0,
@@ -426,7 +474,7 @@ class OnScreenUpdateNotificationTests(TestCase):
set(notifications[0].recipients.all()),
set([self.u21, self.u23, self.u24]),
)
- self.assertResponseCountsEqual(
+ self.assertNewResponseCountsEqual(
[
0, 0, 0, 0,
1, 0, 1, 1,
@@ -453,7 +501,7 @@ class OnScreenUpdateNotificationTests(TestCase):
set(notifications[0].recipients.all()),
set([self.u11, self.u12, self.u13, self.u21, self.u31])
)
- self.assertResponseCountsEqual(
+ self.assertNewResponseCountsEqual(
[
1, 1, 1, 0,
1, 0, 0, 0,
@@ -474,7 +522,7 @@ class OnScreenUpdateNotificationTests(TestCase):
set(notifications[0].recipients.all()),
set([self.u11, self.u12, self.u13, self.u14, self.u21])
)
- self.assertResponseCountsEqual(
+ self.assertNewResponseCountsEqual(
[
1, 1, 1, 1,
1, 0, 0, 0,
@@ -505,7 +553,7 @@ class OnScreenUpdateNotificationTests(TestCase):
]
)
)
- self.assertResponseCountsEqual(
+ self.assertNewResponseCountsEqual(
[
1, 1, 1, 0,
1, 1, 1, 0,
@@ -535,7 +583,7 @@ class OnScreenUpdateNotificationTests(TestCase):
]
)
)
- self.assertResponseCountsEqual(
+ self.assertNewResponseCountsEqual(
[
0, 1, 1, 0,
1, 0, 0, 0,
@@ -562,7 +610,7 @@ class OnScreenUpdateNotificationTests(TestCase):
]
)
)
- self.assertResponseCountsEqual(
+ self.assertNewResponseCountsEqual(
[
1, 1, 1, 0,
1, 0, 0, 0,
diff --git a/askbot/tests/page_load_tests.py b/askbot/tests/page_load_tests.py
index fa4416b8..64f03207 100644
--- a/askbot/tests/page_load_tests.py
+++ b/askbot/tests/page_load_tests.py
@@ -264,7 +264,7 @@ class PageLoadTests(PageLoadTestCase):
self.try_url(
'user_profile',
kwargs={'id': 2, 'slug': name_slug},
- data={'sort':'responses'},
+ data={'sort':'inbox'},
status_code=404,
template='404.html'
)
diff --git a/askbot/urls.py b/askbot/urls.py
index c8c1185e..321010d1 100644
--- a/askbot/urls.py
+++ b/askbot/urls.py
@@ -191,6 +191,11 @@ urlpatterns = patterns('',
name='read_message'
),
url(
+ r'^manage_inbox/$',
+ app.commands.manage_inbox,
+ name='manage_inbox'
+ ),
+ url(
r'^feeds/(?P<url>.*)/$',
'django.contrib.syndication.views.feed',
{'feed_dict': feeds},
diff --git a/askbot/views/commands.py b/askbot/views/commands.py
index 6681f23c..01487768 100644
--- a/askbot/views/commands.py
+++ b/askbot/views/commands.py
@@ -16,7 +16,7 @@ from django.http import HttpResponseForbidden
from django.shortcuts import get_object_or_404, render_to_response
from django.utils.translation import ugettext as _
from django.template import RequestContext
-from askbot.models import * #todo: clean this up
+from askbot import models
from askbot.forms import CloseForm
from askbot import auth
from django.core.urlresolvers import reverse
@@ -24,6 +24,7 @@ from django.contrib.auth.decorators import login_required
from askbot.utils.decorators import ajax_method, ajax_login_required
from askbot.templatetags import extra_filters as template_filters
from askbot.skins.loaders import ENV
+from askbot import const
import logging
def process_vote(user = None, vote_direction = None, post = None):
@@ -80,6 +81,75 @@ 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']
+ seen_memos = memo_set.filter(
+ status=models.ActivityAuditStatus.STATUS_SEEN
+ )
+ new_memos = memo_set.filter(
+ status=models.ActivityAuditStatus.STATUS_NEW
+ )
+ if action_type == 'delete':
+ user.new_response_count -= new_memos.count()
+ user.seen_response_count -= seen_memos.count()
+ assert(user.new_response_count >= 0)
+ assert(user.seen_response_count >= 0)
+ user.save()
+ memo_set.delete()
+ elif action_type == 'mark_new':
+ user.new_response_count += seen_memos.count()
+ user.seen_response_count -= seen_memos.count()
+ assert(user.seen_response_count >= 0)
+ user.save()
+ memo_set.update(status = models.ActivityAuditStatus.STATUS_NEW)
+ elif action_type == 'mark_seen':
+ user.new_response_count -= new_memos.count()
+ user.seen_response_count += new_memos.count()
+ assert(user.new_response_count >= 0)
+ user.save()
+ memo_set.update(status = models.ActivityAuditStatus.STATUS_SEEN)
+ else:
+ raise exceptions.PermissionDenied(
+ _('Oops, sorry - there was some error - please try again')
+ )
+ 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:
+ response_data['message'] = unicode(e)
+ response_data['success'] = False
+ data = simplejson.dumps(response_data)
+ return HttpResponse(data, mimetype="application/json")
+
def vote(request, id):
"""
@@ -139,7 +209,7 @@ def vote(request, id):
if vote_type == '0':
if request.user.is_authenticated():
answer_id = request.POST.get('postId')
- answer = get_object_or_404(Answer, id = answer_id)
+ answer = get_object_or_404(models.Answer, id = answer_id)
question = answer.question
# make sure question author is current user
if answer.accepted:
@@ -165,9 +235,9 @@ def vote(request, id):
#todo: fix this weirdness - why postId here
#and not with question?
id = request.POST.get('postId')
- post = get_object_or_404(Answer, id=id)
+ post = get_object_or_404(models.Answer, id=id)
else:
- post = get_object_or_404(Question, id=id)
+ post = get_object_or_404(models.Question, id=id)
#
######################
@@ -180,10 +250,10 @@ def vote(request, id):
elif vote_type in ['7', '8']:
#flag question or answer
if vote_type == '7':
- post = get_object_or_404(Question, id=id)
+ post = get_object_or_404(models.Question, id=id)
if vote_type == '8':
id = request.POST.get('postId')
- post = get_object_or_404(Answer, id=id)
+ post = get_object_or_404(models.Answer, id=id)
request.user.flag_post(post)
@@ -192,10 +262,10 @@ def vote(request, id):
elif vote_type in ['9', '10']:
#delete question or answer
- post = get_object_or_404(Question, id = id)
+ post = get_object_or_404(models.Question, id = id)
if vote_type == '10':
id = request.POST.get('postId')
- post = get_object_or_404(Answer, id = id)
+ post = get_object_or_404(models.Answer, id = id)
if post.deleted == True:
request.user.restore_post(post = post)
@@ -208,14 +278,14 @@ def vote(request, id):
response_data['allowed'] = 0
response_data['success'] = 0
- question = get_object_or_404(Question, id=id)
+ question = get_object_or_404(models.Question, id=id)
vote_type = request.POST.get('type')
#accept answer
if vote_type == '4':
has_favorited = False
fave = request.user.toggle_favorite_question(question)
- response_data['count'] = FavoriteQuestion.objects.filter(
+ response_data['count'] = models.FavoriteQuestion.objects.filter(
question = question
).count()
if fave == False:
@@ -232,7 +302,7 @@ def vote(request, id):
response_data['message'] = \
_('subscription saved, %(email)s needs validation, see %(details_url)s') \
% {'email':user.email,'details_url':reverse('faq') + '#validate'}
- feed_setting = EmailFeedSetting.objects.get(subscriber=user,feed_type='q_sel')
+ feed_setting = models.EmailFeedSetting.objects.get(subscriber=user,feed_type='q_sel')
if feed_setting.frequency == 'n':
feed_setting.frequency = 'd'
feed_setting.save()
@@ -265,7 +335,7 @@ def vote(request, id):
@ajax_login_required
def mark_tag(request, tag=None, **kwargs):#tagging system
action = kwargs['action']
- ts = MarkedTag.objects.filter(user=request.user, tag__name=tag)
+ ts = models.MarkedTag.objects.filter(user=request.user, tag__name=tag)
if action == 'remove':
logging.debug('deleting tag %s' % tag)
ts.delete()
@@ -273,8 +343,8 @@ def mark_tag(request, tag=None, **kwargs):#tagging system
reason = kwargs['reason']
if len(ts) == 0:
try:
- t = Tag.objects.get(name=tag)
- mt = MarkedTag(user=request.user, reason=reason, tag=t)
+ t = models.Tag.objects.get(name=tag)
+ mt = models.MarkedTag(user=request.user, reason=reason, tag=t)
mt.save()
except:
pass
@@ -305,7 +375,7 @@ def close(request, id):#close question
"""view to initiate and process
question close
"""
- question = get_object_or_404(Question, id=id)
+ question = get_object_or_404(models.Question, id=id)
try:
if request.method == 'POST':
form = CloseForm(request.POST)
@@ -336,7 +406,7 @@ def reopen(request, id):#re-open question
this is not an ajax view
"""
- question = get_object_or_404(Question, id=id)
+ question = get_object_or_404(models.Question, id=id)
# open question
try:
if request.method == 'POST' :
diff --git a/askbot/views/users.py b/askbot/views/users.py
index 0db51705..c2109cf8 100644
--- a/askbot/views/users.py
+++ b/askbot/views/users.py
@@ -20,7 +20,6 @@ from django.template import RequestContext
from django.http import HttpResponse, HttpResponseForbidden
from django.http import HttpResponseRedirect, Http404
from django.utils.translation import ugettext as _
-from django.utils.html import strip_tags
from django.utils import simplejson
from django.conf import settings as django_settings
import askbot
@@ -701,20 +700,46 @@ def user_responses(request, user):
user - the profile owner
"""
- response_list = []
+ section = 'forum'
+ if request.user.is_moderator() or request.user.is_administrator():
+ if 'section' in request.GET and request.GET['section'] == 'flags':
+ section = 'flags'
- activities = list()
- activities = models.Activity.responses_and_mentions.filter(recipients=user)
-
- for act in activities:
- origin_post = act.content_object.get_origin_post()
+ if section == 'forum':
+ activity_types = const.RESPONSE_ACTIVITY_TYPES_FOR_DISPLAY
+ activity_types += (const.TYPE_ACTIVITY_MENTION,)
+ else:
+ assert(section == 'flags')
+ activity_types = (const.TYPE_ACTIVITY_MARK_OFFENSIVE,)
+
+ memo_set = models.ActivityAuditStatus.objects.filter(
+ user = request.user,
+ activity__activity_type__in = activity_types
+ ).select_related(
+ 'activity__active_at',
+ 'activity__object_id',
+ 'activity__content_type',
+ 'activity__question__title',
+ 'activity__user__username',
+ 'activity__user__id',
+ 'activity__user__gravatar',
+ ).order_by(
+ '-activity__active_at'
+ )[:const.USER_VIEW_DATA_SIZE]
+
+ #todo: insert pagination code here
+
+ response_list = list()
+ for memo in memo_set:
response = {
- 'timestamp': act.active_at,
- 'user': act.user,
- 'response_url': act.get_absolute_url(),
- 'response_snippet': strip_tags(act.content_object.html)[:300],
- 'response_title': origin_post.title,
- 'response_type': act.get_activity_type_display(),
+ 'id': memo.id,
+ 'timestamp': memo.activity.active_at,
+ 'user': memo.activity.user,
+ 'is_new': memo.is_new(),
+ 'response_url': memo.activity.get_absolute_url(),
+ 'response_snippet': memo.activity.get_preview(),
+ 'response_title': memo.activity.question.title,
+ 'response_type': memo.activity.get_activity_type_display(),
}
response_list.append(response)
@@ -722,14 +747,15 @@ def user_responses(request, user):
data = {
'active_tab':'users',
- 'tab_name' : 'responses',
+ 'tab_name' : 'inbox',
+ 'inbox_section':section,
'tab_description' : _('comments and answers to others questions'),
'page_title' : _('profile - responses'),
'view_user' : user,
- 'responses' : response_list[:const.USER_VIEW_DATA_SIZE],
+ 'responses' : response_list,
}
context = RequestContext(request, data)
- template = ENV.get_template('user_responses.html')
+ template = ENV.get_template('user_inbox.html')
return HttpResponse(template.render(context))
@owner_or_moderator_required
@@ -911,7 +937,7 @@ def user_email_subscriptions(request, user):
user_view_call_table = {
'stats': user_stats,
'recent': user_recent,
- 'responses': user_responses,
+ 'inbox': user_responses,
'reputation': user_reputation,
'favorites': user_favorites,
'votes': user_votes,