diff options
34 files changed, 1999 insertions, 287 deletions
@@ -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 Binary files differnew file mode 100644 index 00000000..258e4d86 --- /dev/null +++ b/askbot/skins/default/media/images/dialog-warning-off.png diff --git a/askbot/skins/default/media/images/dialog-warning.png b/askbot/skins/default/media/images/dialog-warning.png Binary files differnew file mode 100644 index 00000000..a9e4ff39 --- /dev/null +++ b/askbot/skins/default/media/images/dialog-warning.png 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§ion=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§ion=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'>●</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§ion=forum" + {% if inbox_section == 'forum' %}class="on"{% endif %} + > + {% trans %}forum responses ({{re_count}}){% endtrans -%} + </a> | + <a href="{{request.user.get_absolute_url()}}?sort=inbox§ion=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> + {{ 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> - {{ 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, |