]> git.openstreetmap.org Git - osqa.git/commitdiff
convertd comments to nodes
authorhernani <hernani@0cfe37f9-358a-4d5e-be75-b63607b5c754>
Fri, 16 Apr 2010 17:31:04 +0000 (17:31 +0000)
committerhernani <hernani@0cfe37f9-358a-4d5e-be75-b63607b5c754>
Fri, 16 Apr 2010 17:31:04 +0000 (17:31 +0000)
git-svn-id: http://svn.osqa.net/svnroot/osqa/trunk@40 0cfe37f9-358a-4d5e-be75-b63607b5c754

17 files changed:
forum/activity.py
forum/migrations/0017_auto__add_field_repute_node__add_field_repute_canceled.py [new file with mode: 0644]
forum/migrations/0018_comments_to_node.py [new file with mode: 0644]
forum/models/__init__.py
forum/models/base.py
forum/models/comment.py [new file with mode: 0644]
forum/models/meta.py
forum/models/node.py
forum/models/question.py
forum/models/repute.py
forum/models/user.py
forum/reputation.py
forum/skins/default/templates/node/comments.html
forum/skins/default/templates/users/stats.html
forum/subscriptions.py
forum/templatetags/node_tags.py
forum/views/commands.py

index a58307ba0123faea2eeb119f8cef51321b42751f..16877987317bea44a077ae37b8fed03f519d27f1 100644 (file)
@@ -1,35 +1,32 @@
 import datetime\r
 from django.db.models.signals import post_save\r
 from forum.models import *\r
-from forum.models.base import marked_deleted\r
-from forum.models.meta import vote_canceled\r
+from forum.models.base import marked_deleted, mark_canceled\r
+from forum.models.node import node_create\r
 from forum.models.answer import answer_accepted\r
 from forum.authentication import user_updated\r
 from forum.const import *\r
 \r
-def record_ask_event(instance, created, **kwargs):\r
-    if created:\r
-        activity = Activity(user=instance.author, active_at=instance.added_at, content_object=instance, activity_type=TYPE_ACTIVITY_ASK_QUESTION)\r
-        activity.save()\r
+def record_ask_event(instance, **kwargs):\r
+    activity = Activity(user=instance.author, active_at=instance.added_at, content_object=instance, activity_type=TYPE_ACTIVITY_ASK_QUESTION)\r
+    activity.save()\r
 \r
-post_save.connect(record_ask_event, sender=Question)\r
+node_create.connect(record_ask_event, sender=Question)\r
 \r
 \r
-def record_answer_event(instance, created, **kwargs):\r
-    if created:\r
-        activity = Activity(user=instance.author, active_at=instance.added_at, content_object=instance, activity_type=TYPE_ACTIVITY_ANSWER)\r
-        activity.save()\r
+def record_answer_event(instance, **kwargs):\r
+    activity = Activity(user=instance.author, active_at=instance.added_at, content_object=instance, activity_type=TYPE_ACTIVITY_ANSWER)\r
+    activity.save()\r
 \r
-post_save.connect(record_answer_event, sender=Answer)\r
+node_create.connect(record_answer_event, sender=Answer)\r
 \r
 \r
-def record_comment_event(instance, created, **kwargs):\r
-    if created:\r
-        act_type = (instance.content_object.__class__ is Question) and TYPE_ACTIVITY_COMMENT_QUESTION or TYPE_ACTIVITY_COMMENT_ANSWER\r
-        activity = Activity(user=instance.user, active_at=instance.added_at, content_object=instance, activity_type=act_type)\r
-        activity.save()\r
+def record_comment_event(instance, **kwargs):\r
+    act_type = (instance.content_object.__class__ is Question) and TYPE_ACTIVITY_COMMENT_QUESTION or TYPE_ACTIVITY_COMMENT_ANSWER\r
+    activity = Activity(user=instance.user, active_at=instance.added_at, content_object=instance, activity_type=act_type)\r
+    activity.save()\r
 \r
-post_save.connect(record_comment_event, sender=Comment)\r
+node_create.connect(record_comment_event, sender=Comment)\r
 \r
 \r
 def record_revision_event(instance, created, **kwargs):\r
@@ -80,7 +77,7 @@ def record_cancel_vote(instance, **kwargs):
     activity = Activity(user=instance.user, active_at=datetime.datetime.now(), content_object=instance, activity_type=act_type)\r
     activity.save()\r
 \r
-vote_canceled.connect(record_cancel_vote)\r
+mark_canceled.connect(record_cancel_vote, sender=Vote)\r
 \r
 \r
 def record_delete_post(instance, **kwargs):\r
diff --git a/forum/migrations/0017_auto__add_field_repute_node__add_field_repute_canceled.py b/forum/migrations/0017_auto__add_field_repute_node__add_field_repute_canceled.py
new file mode 100644 (file)
index 0000000..cb14267
--- /dev/null
@@ -0,0 +1,312 @@
+# encoding: utf-8\r
+import datetime\r
+from south.db import db\r
+from south.v2 import SchemaMigration\r
+from django.db import models\r
+\r
+class Migration(SchemaMigration):\r
+    \r
+    def forwards(self, orm):\r
+        \r
+        # Adding field 'Repute.node'\r
+        db.add_column(u'repute', 'node', self.gf('django.db.models.fields.related.ForeignKey')(related_name='reputes', null=True, to=orm['forum.Node']), keep_default=False)\r
+\r
+        # Adding field 'Repute.canceled'\r
+        db.add_column(u'repute', 'canceled', self.gf('django.db.models.fields.BooleanField')(default=False, blank=True), keep_default=False)\r
+    \r
+    \r
+    def backwards(self, orm):\r
+        \r
+        # Deleting field 'Repute.node'\r
+        db.delete_column(u'repute', 'node_id')\r
+\r
+        # Deleting field 'Repute.canceled'\r
+        db.delete_column(u'repute', 'canceled')\r
+    \r
+    \r
+    models = {\r
+        'auth.group': {\r
+            'Meta': {'object_name': 'Group'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),\r
+            'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'})\r
+        },\r
+        'auth.permission': {\r
+            'Meta': {'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},\r
+            'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})\r
+        },\r
+        'auth.user': {\r
+            'Meta': {'object_name': 'User'},\r
+            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),\r
+            'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),\r
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),\r
+            'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),\r
+            'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'}),\r
+            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})\r
+        },\r
+        'contenttypes.contenttype': {\r
+            'Meta': {'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},\r
+            'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})\r
+        },\r
+        'forum.activity': {\r
+            'Meta': {'object_name': 'Activity', 'db_table': "u'activity'"},\r
+            'active_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'activity_type': ('django.db.models.fields.SmallIntegerField', [], {}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'is_auditted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.anonymousnode': {\r
+            'Meta': {'object_name': 'AnonymousNode', '_ormbases': ['forum.Node']},\r
+            'convertible_to': ('django.db.models.fields.CharField', [], {'default': "'node'", 'max_length': '16'}),\r
+            'node_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['forum.Node']", 'unique': 'True', 'primary_key': 'True'}),\r
+            'validation_hash': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'anonymous_content'", 'to': "orm['forum.Node']"})\r
+        },\r
+        'forum.answer': {\r
+            'Meta': {'object_name': 'Answer', 'db_table': "u'answer'"},\r
+            'accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'accepted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'accepted_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']", 'null': 'True'}),\r
+            'node_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['forum.Node']", 'unique': 'True', 'primary_key': 'True'}),\r
+            'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'wikified_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})\r
+        },\r
+        'forum.authkeyuserassociation': {\r
+            'Meta': {'object_name': 'AuthKeyUserAssociation'},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'provider': ('django.db.models.fields.CharField', [], {'max_length': '64'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'auth_keys'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.award': {\r
+            'Meta': {'unique_together': "(('content_type', 'object_id', 'user', 'badge'),)", 'object_name': 'Award', 'db_table': "u'award'"},\r
+            'awarded_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'badge': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'award_badge'", 'to': "orm['forum.Badge']"}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'notified': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'awards'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.badge': {\r
+            'Meta': {'unique_together': "(('name', 'type'),)", 'object_name': 'Badge', 'db_table': "u'badge'"},\r
+            'awarded_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'awarded_to': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'badges'", 'through': "'Award'", 'to': "orm['forum.User']"}),\r
+            'description': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'multiple': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}),\r
+            'slug': ('django.db.models.fields.SlugField', [], {'db_index': 'True', 'max_length': '50', 'blank': 'True'}),\r
+            'type': ('django.db.models.fields.SmallIntegerField', [], {})\r
+        },\r
+        'forum.comment': {\r
+            'Meta': {'object_name': 'Comment', 'db_table': "u'comment'"},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'comment': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_comments'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'liked_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'comments_liked'", 'through': "'LikedComment'", 'to': "orm['forum.User']"}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'comments'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'comments'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.favoritequestion': {\r
+            'Meta': {'unique_together': "(('question', 'user'),)", 'object_name': 'FavoriteQuestion', 'db_table': "u'favorite_question'"},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Question']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_favorite_questions'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.flaggeditem': {\r
+            'Meta': {'object_name': 'FlaggedItem', 'db_table': "u'flagged_item'"},\r
+            'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'flagged_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'flaggeditems'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'reason': ('django.db.models.fields.CharField', [], {'max_length': '300', 'null': 'True'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'flaggeditems'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.keyvalue': {\r
+            'Meta': {'object_name': 'KeyValue'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'value': ('forum.models.utils.PickledObjectField', [], {})\r
+        },\r
+        'forum.likedcomment': {\r
+            'Meta': {'object_name': 'LikedComment'},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'comment': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Comment']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.markedtag': {\r
+            'Meta': {'object_name': 'MarkedTag'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'reason': ('django.db.models.fields.CharField', [], {'max_length': '16'}),\r
+            'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_selections'", 'to': "orm['forum.Tag']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tag_selections'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.node': {\r
+            'Meta': {'object_name': 'Node'},\r
+            'active_revision': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'active'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.NodeRevision']"}),\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'nodes'", 'to': "orm['forum.User']"}),\r
+            'body': ('django.db.models.fields.TextField', [], {}),\r
+            'comment_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_nodes'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'last_edited_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'last_edited_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'last_edited_nodes'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'node_type': ('django.db.models.fields.CharField', [], {'default': "'node'", 'max_length': '16'}),\r
+            'offensive_flag_count': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'children'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),\r
+            'tags': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'nodes'", 'to': "orm['forum.Tag']"}),\r
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'vote_down_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'vote_up_count': ('django.db.models.fields.IntegerField', [], {'default': '0'})\r
+        },\r
+        'forum.noderevision': {\r
+            'Meta': {'unique_together': "(('node', 'revision'),)", 'object_name': 'NodeRevision'},\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'noderevisions'", 'to': "orm['forum.User']"}),\r
+            'body': ('django.db.models.fields.TextField', [], {}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'revisions'", 'to': "orm['forum.Node']"}),\r
+            'revised_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'revision': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'summary': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),\r
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'})\r
+        },\r
+        'forum.question': {\r
+            'Meta': {'object_name': 'Question', 'db_table': "u'question'"},\r
+            'accepted_answer': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'question_accepting'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.Answer']"}),\r
+            'answer_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'close_reason': ('django.db.models.fields.SmallIntegerField', [], {'null': 'True', 'blank': 'True'}),\r
+            'closed': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'closed_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'closed_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'closed_questions'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'favorited_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'favorite_questions'", 'through': "'FavoriteQuestion'", 'to': "orm['forum.User']"}),\r
+            'favourite_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'last_activity_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'last_activity_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'last_active_in_questions'", 'to': "orm['forum.User']"}),\r
+            'node_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['forum.Node']", 'unique': 'True'}),\r
+            'subscribers': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'subscriptions'", 'through': "'QuestionSubscription'", 'to': "orm['forum.User']"}),\r
+            'view_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'wikified_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})\r
+        },\r
+        'forum.questionsubscription': {\r
+            'Meta': {'object_name': 'QuestionSubscription'},\r
+            'auto_subscription': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'last_view': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 4, 16, 14, 18, 46, 625000)'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Question']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.repute': {\r
+            'Meta': {'object_name': 'Repute', 'db_table': "u'repute'"},\r
+            'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Question']"}),\r
+            'reputation_type': ('django.db.models.fields.SmallIntegerField', [], {}),\r
+            'reputed_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'to': "orm['forum.User']"}),\r
+            'user_previous_rep': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'value': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'})\r
+        },\r
+        'forum.subscriptionsettings': {\r
+            'Meta': {'object_name': 'SubscriptionSettings'},\r
+            'all_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'all_questions_watched_tags': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'enable_notifications': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'member_joins': ('django.db.models.fields.CharField', [], {'default': "'n'", 'max_length': '1'}),\r
+            'new_question': ('django.db.models.fields.CharField', [], {'default': "'d'", 'max_length': '1'}),\r
+            'new_question_watched_tags': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}),\r
+            'notify_accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'notify_answers': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'notify_comments': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'notify_comments_own_post': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'notify_reply_to_comments': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_answered': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_asked': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_commented': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'questions_viewed': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'subscribed_questions': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}),\r
+            'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'subscription_settings'", 'unique': 'True', 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.tag': {\r
+            'Meta': {'object_name': 'Tag', 'db_table': "u'tag'"},\r
+            'created_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'created_tags'", 'to': "orm['forum.User']"}),\r
+            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_tags'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'marked_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'marked_tags'", 'through': "'MarkedTag'", 'to': "orm['forum.User']"}),\r
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'used_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'})\r
+        },\r
+        'forum.user': {\r
+            'Meta': {'object_name': 'User', '_ormbases': ['auth.User']},\r
+            'about': ('django.db.models.fields.TextField', [], {'blank': 'True'}),\r
+            'bronze': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'date_of_birth': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),\r
+            'email_isvalid': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'email_key': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}),\r
+            'gold': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'hide_ignored_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'is_approved': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'last_seen': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'location': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),\r
+            'questions_per_page': ('django.db.models.fields.SmallIntegerField', [], {'default': '10'}),\r
+            'real_name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),\r
+            'reputation': ('django.db.models.fields.PositiveIntegerField', [], {'default': '1'}),\r
+            'silver': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'user_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True', 'primary_key': 'True'}),\r
+            'website': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'})\r
+        },\r
+        'forum.validationhash': {\r
+            'Meta': {'unique_together': "(('user', 'type'),)", 'object_name': 'ValidationHash'},\r
+            'expiration': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 4, 17, 14, 18, 46, 835000)'}),\r
+            'hash_code': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'seed': ('django.db.models.fields.CharField', [], {'max_length': '12'}),\r
+            'type': ('django.db.models.fields.CharField', [], {'max_length': '12'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.vote': {\r
+            'Meta': {'object_name': 'Vote', 'db_table': "u'vote'"},\r
+            'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'votes'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'votes'", 'to': "orm['forum.User']"}),\r
+            'vote': ('django.db.models.fields.SmallIntegerField', [], {}),\r
+            'voted_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'})\r
+        }\r
+    }\r
+    \r
+    complete_apps = ['forum']\r
diff --git a/forum/migrations/0018_comments_to_node.py b/forum/migrations/0018_comments_to_node.py
new file mode 100644 (file)
index 0000000..1b10aee
--- /dev/null
@@ -0,0 +1,352 @@
+# encoding: utf-8\r
+import datetime\r
+from south.db import db\r
+from south.v2 import DataMigration\r
+from django.db import models\r
+from forum.migrations import ProgressBar\r
+\r
+class Migration(DataMigration):\r
+    \r
+    def forwards(self, orm):\r
+        c_count = orm.Comment.objects.count()\r
+        print "\nConverting %d comments:" % c_count\r
+        progress = ProgressBar(c_count)\r
+\r
+        for c in orm.Comment.objects.all():\r
+            node = orm.Node(\r
+                node_type='comment',\r
+                author=c.user,\r
+                added_at=c.added_at,\r
+                score=c.score,\r
+                vote_up_count=c.score,\r
+                vote_down_count=0,\r
+                offensive_flag_count=0,\r
+                last_edited_at=c.added_at,\r
+                last_edited_by=c.user,\r
+                body=c.comment,\r
+                deleted=c.deleted,\r
+                deleted_by=c.deleted_by,\r
+                deleted_at=c.deleted_at,\r
+                parent=c.node,\r
+            )\r
+            node.save()\r
+\r
+            revision = orm.NodeRevision(\r
+                summary="Initial revsion",\r
+                revision=1,\r
+                revised_at=c.added_at,\r
+                body=c.comment,\r
+                author=c.user,\r
+                node=node,\r
+            )\r
+\r
+            revision.save()\r
+\r
+            node.active_revision = revision\r
+            node.save()\r
+\r
+            for v in orm.LikedComment.objects.filter(comment=c):\r
+                vote = orm.Vote(\r
+                    node=node,\r
+                    vote=1,\r
+                    voted_at=v.added_at,\r
+                    canceled=v.canceled,\r
+                    user=v.user,\r
+                )\r
+\r
+                vote.save()\r
+\r
+            progress.update()\r
+\r
+        print "\n...done\n"\r
+    \r
+    \r
+    def backwards(self, orm):\r
+        "Write your backwards methods here."\r
+    \r
+    models = {\r
+        'auth.group': {\r
+            'Meta': {'object_name': 'Group'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),\r
+            'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'})\r
+        },\r
+        'auth.permission': {\r
+            'Meta': {'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},\r
+            'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})\r
+        },\r
+        'auth.user': {\r
+            'Meta': {'object_name': 'User'},\r
+            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),\r
+            'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),\r
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),\r
+            'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),\r
+            'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'}),\r
+            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})\r
+        },\r
+        'contenttypes.contenttype': {\r
+            'Meta': {'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},\r
+            'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})\r
+        },\r
+        'forum.activity': {\r
+            'Meta': {'object_name': 'Activity', 'db_table': "u'activity'"},\r
+            'active_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'activity_type': ('django.db.models.fields.SmallIntegerField', [], {}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'is_auditted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.anonymousnode': {\r
+            'Meta': {'object_name': 'AnonymousNode', '_ormbases': ['forum.Node']},\r
+            'convertible_to': ('django.db.models.fields.CharField', [], {'default': "'node'", 'max_length': '16'}),\r
+            'node_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['forum.Node']", 'unique': 'True', 'primary_key': 'True'}),\r
+            'validation_hash': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'anonymous_content'", 'to': "orm['forum.Node']"})\r
+        },\r
+        'forum.answer': {\r
+            'Meta': {'object_name': 'Answer', 'db_table': "u'answer'"},\r
+            'accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'accepted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'accepted_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']", 'null': 'True'}),\r
+            'node_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['forum.Node']", 'unique': 'True', 'primary_key': 'True'}),\r
+            'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'wikified_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})\r
+        },\r
+        'forum.authkeyuserassociation': {\r
+            'Meta': {'object_name': 'AuthKeyUserAssociation'},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'provider': ('django.db.models.fields.CharField', [], {'max_length': '64'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'auth_keys'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.award': {\r
+            'Meta': {'unique_together': "(('content_type', 'object_id', 'user', 'badge'),)", 'object_name': 'Award', 'db_table': "u'award'"},\r
+            'awarded_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'badge': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'award_badge'", 'to': "orm['forum.Badge']"}),\r
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'notified': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'awards'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.badge': {\r
+            'Meta': {'unique_together': "(('name', 'type'),)", 'object_name': 'Badge', 'db_table': "u'badge'"},\r
+            'awarded_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'awarded_to': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'badges'", 'through': "'Award'", 'to': "orm['forum.User']"}),\r
+            'description': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'multiple': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}),\r
+            'slug': ('django.db.models.fields.SlugField', [], {'db_index': 'True', 'max_length': '50', 'blank': 'True'}),\r
+            'type': ('django.db.models.fields.SmallIntegerField', [], {})\r
+        },\r
+        'forum.comment': {\r
+            'Meta': {'object_name': 'Comment', 'db_table': "u'comment'"},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'comment': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_comments'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'liked_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'comments_liked'", 'through': "'LikedComment'", 'to': "orm['forum.User']"}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'comments'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'comments'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.favoritequestion': {\r
+            'Meta': {'unique_together': "(('question', 'user'),)", 'object_name': 'FavoriteQuestion', 'db_table': "u'favorite_question'"},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Question']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_favorite_questions'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.flaggeditem': {\r
+            'Meta': {'object_name': 'FlaggedItem', 'db_table': "u'flagged_item'"},\r
+            'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'flagged_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'flaggeditems'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'reason': ('django.db.models.fields.CharField', [], {'max_length': '300', 'null': 'True'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'flaggeditems'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.keyvalue': {\r
+            'Meta': {'object_name': 'KeyValue'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'value': ('forum.models.utils.PickledObjectField', [], {})\r
+        },\r
+        'forum.likedcomment': {\r
+            'Meta': {'object_name': 'LikedComment'},\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'comment': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Comment']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.markedtag': {\r
+            'Meta': {'object_name': 'MarkedTag'},\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'reason': ('django.db.models.fields.CharField', [], {'max_length': '16'}),\r
+            'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_selections'", 'to': "orm['forum.Tag']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tag_selections'", 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.node': {\r
+            'Meta': {'object_name': 'Node'},\r
+            'active_revision': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'active'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.NodeRevision']"}),\r
+            'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'nodes'", 'to': "orm['forum.User']"}),\r
+            'body': ('django.db.models.fields.TextField', [], {}),\r
+            'comment_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_nodes'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'last_edited_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'last_edited_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'last_edited_nodes'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'node_type': ('django.db.models.fields.CharField', [], {'default': "'node'", 'max_length': '16'}),\r
+            'offensive_flag_count': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'children'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),\r
+            'tags': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'nodes'", 'to': "orm['forum.Tag']"}),\r
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'vote_down_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'vote_up_count': ('django.db.models.fields.IntegerField', [], {'default': '0'})\r
+        },\r
+        'forum.noderevision': {\r
+            'Meta': {'unique_together': "(('node', 'revision'),)", 'object_name': 'NodeRevision'},\r
+            'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'noderevisions'", 'to': "orm['forum.User']"}),\r
+            'body': ('django.db.models.fields.TextField', [], {}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'revisions'", 'to': "orm['forum.Node']"}),\r
+            'revised_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'revision': ('django.db.models.fields.PositiveIntegerField', [], {}),\r
+            'summary': ('django.db.models.fields.CharField', [], {'max_length': '300'}),\r
+            'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}),\r
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '300'})\r
+        },\r
+        'forum.question': {\r
+            'Meta': {'object_name': 'Question', 'db_table': "u'question'"},\r
+            'accepted_answer': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'question_accepting'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.Answer']"}),\r
+            'answer_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),\r
+            'close_reason': ('django.db.models.fields.SmallIntegerField', [], {'null': 'True', 'blank': 'True'}),\r
+            'closed': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'closed_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'closed_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'closed_questions'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'favorited_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'favorite_questions'", 'through': "'FavoriteQuestion'", 'to': "orm['forum.User']"}),\r
+            'favourite_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'last_activity_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'last_activity_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'last_active_in_questions'", 'to': "orm['forum.User']"}),\r
+            'node_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['forum.Node']", 'unique': 'True'}),\r
+            'subscribers': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'subscriptions'", 'through': "'QuestionSubscription'", 'to': "orm['forum.User']"}),\r
+            'view_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'wikified_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})\r
+        },\r
+        'forum.questionsubscription': {\r
+            'Meta': {'object_name': 'QuestionSubscription'},\r
+            'auto_subscription': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'last_view': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 4, 16, 14, 19, 21, 765000)'}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Question']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.repute': {\r
+            'Meta': {'object_name': 'Repute', 'db_table': "u'repute'"},\r
+            'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Question']"}),\r
+            'reputation_type': ('django.db.models.fields.SmallIntegerField', [], {}),\r
+            'reputed_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'to': "orm['forum.User']"}),\r
+            'user_previous_rep': ('django.db.models.fields.IntegerField', [], {'default': '0'}),\r
+            'value': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'})\r
+        },\r
+        'forum.subscriptionsettings': {\r
+            'Meta': {'object_name': 'SubscriptionSettings'},\r
+            'all_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'all_questions_watched_tags': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'enable_notifications': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'member_joins': ('django.db.models.fields.CharField', [], {'default': "'n'", 'max_length': '1'}),\r
+            'new_question': ('django.db.models.fields.CharField', [], {'default': "'d'", 'max_length': '1'}),\r
+            'new_question_watched_tags': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}),\r
+            'notify_accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'notify_answers': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'notify_comments': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'notify_comments_own_post': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'notify_reply_to_comments': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_answered': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_asked': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),\r
+            'questions_commented': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'questions_viewed': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'subscribed_questions': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}),\r
+            'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'subscription_settings'", 'unique': 'True', 'to': "orm['forum.User']"})\r
+        },\r
+        'forum.tag': {\r
+            'Meta': {'object_name': 'Tag', 'db_table': "u'tag'"},\r
+            'created_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'created_tags'", 'to': "orm['forum.User']"}),\r
+            'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),\r
+            'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_tags'", 'null': 'True', 'to': "orm['forum.User']"}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'marked_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'marked_tags'", 'through': "'MarkedTag'", 'to': "orm['forum.User']"}),\r
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'used_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'})\r
+        },\r
+        'forum.user': {\r
+            'Meta': {'object_name': 'User', '_ormbases': ['auth.User']},\r
+            'about': ('django.db.models.fields.TextField', [], {'blank': 'True'}),\r
+            'bronze': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'date_of_birth': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),\r
+            'email_isvalid': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'email_key': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}),\r
+            'gold': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'hide_ignored_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'is_approved': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'last_seen': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),\r
+            'location': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),\r
+            'questions_per_page': ('django.db.models.fields.SmallIntegerField', [], {'default': '10'}),\r
+            'real_name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),\r
+            'reputation': ('django.db.models.fields.PositiveIntegerField', [], {'default': '1'}),\r
+            'silver': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),\r
+            'user_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True', 'primary_key': 'True'}),\r
+            'website': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'})\r
+        },\r
+        'forum.validationhash': {\r
+            'Meta': {'unique_together': "(('user', 'type'),)", 'object_name': 'ValidationHash'},\r
+            'expiration': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2010, 4, 17, 14, 19, 21, 837000)'}),\r
+            'hash_code': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'seed': ('django.db.models.fields.CharField', [], {'max_length': '12'}),\r
+            'type': ('django.db.models.fields.CharField', [], {'max_length': '12'}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"})\r
+        },\r
+        'forum.vote': {\r
+            'Meta': {'object_name': 'Vote', 'db_table': "u'vote'"},\r
+            'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),\r
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),\r
+            'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'votes'", 'null': 'True', 'to': "orm['forum.Node']"}),\r
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'votes'", 'to': "orm['forum.User']"}),\r
+            'vote': ('django.db.models.fields.SmallIntegerField', [], {}),\r
+            'voted_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'})\r
+        }\r
+    }\r
+    \r
+    complete_apps = ['forum']\r
index e8353077b8b6ed327a62bd9a94e1895f63e3920b..df42a5b802230d7dcf6868920509aa9f57db3d0e 100644 (file)
@@ -1,10 +1,11 @@
 from question import Question ,QuestionRevision, FavoriteQuestion, QuestionSubscription\r
 from answer import Answer, AnswerRevision\r
 from tag import Tag, MarkedTag\r
-from meta import Vote, Comment, FlaggedItem, LikedComment\r
+from meta import Vote, FlaggedItem\r
 from user import User, Activity, ValidationHash, AuthKeyUserAssociation, SubscriptionSettings\r
 from repute import Badge, Award, Repute\r
 from node import Node, NodeRevision, NodeMetaClass, AnonymousNode\r
+from comment import Comment\r
 from utils import KeyValue\r
 \r
 try:\r
@@ -27,7 +28,7 @@ __all__ = [
         'Node', 'NodeRevision', 'AnonymousNode', \r
         'Question', 'FavoriteQuestion', 'QuestionSubscription', 'QuestionRevision',\r
         'Answer', 'AnswerRevision',\r
-        'Tag', 'Comment', 'Vote', 'FlaggedItem', 'MarkedTag', 'LikedComment', 'Badge', 'Award', 'Repute',\r
+        'Tag', 'Comment', 'Vote', 'FlaggedItem', 'MarkedTag', 'Badge', 'Award', 'Repute',\r
         'Activity', 'ValidationHash', 'AuthKeyUserAssociation', 'SubscriptionSettings', 'KeyValue', 'User',\r
         ]\r
 \r
index 13eae2279e13bebe4774f01c8c88c4696fb7efa6..7974af6f8ef3527c4fa01b8523c5e013a3dc3baa 100644 (file)
@@ -79,6 +79,7 @@ class BaseModel(models.Model):
 
 
 class ActiveObjectManager(models.Manager):
+    use_for_related_fields = True
     def get_query_set(self):
         return super(ActiveObjectManager, self).get_query_set().filter(canceled=False)
 
@@ -158,8 +159,25 @@ class DeletableContent(models.Model):
         else:
             return False
 
+mark_canceled = django.dispatch.Signal(providing_args=['instance'])
+
+class CancelableContent(models.Model):
+    canceled = models.BooleanField(default=False)
+
+    def cancel(self):
+        if not self.canceled:
+            self.canceled = True
+            self.save()
+            mark_canceled.send(sender=self.__class__, instance=self)
+            return True
+            
+        return False
+
+    class Meta:
+        abstract = True
+        app_label = 'forum'
+
 
-from meta import Comment, Vote, FlaggedItem
 from node import Node, NodeRevision
 
 class QandA(Node):
diff --git a/forum/models/comment.py b/forum/models/comment.py
new file mode 100644 (file)
index 0000000..071126e
--- /dev/null
@@ -0,0 +1,50 @@
+from base import *\r
+import re\r
+\r
+class Comment(Node):\r
+    class Meta(Node.Meta):\r
+        ordering = ('-added_at',)\r
+        proxy = True\r
+\r
+    def _update_parent_comment_count(self, diff):\r
+        parent = self.parent\r
+        parent.comment_count = parent.comment_count + diff\r
+        parent.save()\r
+\r
+    @property\r
+    def comment(self):\r
+        return self.body\r
+\r
+    @property\r
+    def content_object(self):\r
+        return self.parent.leaf\r
+\r
+    def save(self, *args, **kwargs):\r
+        super(Comment,self).save(*args, **kwargs)\r
+\r
+        if self._is_new:\r
+            self._update_parent_comment_count(1)\r
+\r
+        try:\r
+            ping_google()\r
+        except Exception:\r
+            logging.debug('problem pinging google did you register you sitemap with google?')\r
+\r
+    def mark_deleted(self, user):\r
+        if super(Comment, self).mark_deleted(user):\r
+            self._update_parent_comment_count(-1)\r
+\r
+    def unmark_deleted(self):\r
+        if super(Comment, self).unmark_deleted():\r
+            self._update_parent_comment_count(1)\r
+\r
+    def is_reply_to(self, user):\r
+        inreply = re.search('@\w+', self.comment)\r
+        if inreply is not None:\r
+            return user.username.startswith(inreply.group(0))\r
+\r
+        return False\r
+\r
+    def __unicode__(self):\r
+        return self.body\r
+\r
index 7e8213786f211dacb25bdc6840d10be2d6693d6e..c01c018f77daa5c4cef9cdd6e7decab5cf39a36d 100644 (file)
@@ -1,7 +1,6 @@
 from base import *
-import re
 
-class Vote(MetaContent, UserContent):
+class Vote(MetaContent, CancelableContent, UserContent):
     VOTE_UP = +1
     VOTE_DOWN = -1
     VOTE_CHOICES = (
@@ -11,7 +10,6 @@ class Vote(MetaContent, UserContent):
 
     vote           = models.SmallIntegerField(choices=VOTE_CHOICES)
     voted_at       = models.DateTimeField(default=datetime.datetime.now)
-    canceled       = models.BooleanField(default=False)
 
     active = ActiveObjectManager()
 
@@ -27,28 +25,23 @@ class Vote(MetaContent, UserContent):
         post.__dict__[field] = post.__dict__[field] + diff
         post.save()
 
+    def cancel(self):
+        if super(Vote, self).cancel():
+            self._update_post_vote_count(-1)
+
     def save(self, *args, **kwargs):
         super(Vote, self).save(*args, **kwargs)
         if self._is_new:
             self._update_post_vote_count(1)
 
-    def cancel(self):
-        if not self.canceled:
-            self.canceled = True
-            self.save()
-            self._update_post_vote_count(-1)
-            vote_canceled.send(sender=Vote, instance=self)
-
     def is_upvote(self):
         return self.vote == self.VOTE_UP
 
     def is_downvote(self):
         return self.vote == self.VOTE_DOWN
 
-vote_canceled = django.dispatch.Signal(providing_args=['instance'])
 
 class FlaggedItem(MetaContent, UserContent):
-    """A flag on a Question or Answer indicating offensive content."""
     flagged_at     = models.DateTimeField(default=datetime.datetime.now)
     reason         = models.CharField(max_length=300, null=True)
     canceled       = models.BooleanField(default=False)
@@ -78,75 +71,5 @@ class FlaggedItem(MetaContent, UserContent):
             self._update_post_flag_count(-1)
             
 
-class Comment(MetaContent, UserContent, DeletableContent):
-    comment        = models.CharField(max_length=300)
-    added_at       = models.DateTimeField(default=datetime.datetime.now)
-    score          = models.IntegerField(default=0)
-    liked_by       = models.ManyToManyField(User, through='LikedComment', related_name='comments_liked')
-
-    class Meta(MetaContent.Meta):
-        ordering = ('-added_at',)
-        db_table = u'comment'
-
-    def _update_post_comment_count(self, diff):
-        post = self.node.leaf
-        post.comment_count = post.comment_count + diff
-        post.save()
-
-    def save(self, *args, **kwargs):
-        super(Comment,self).save(*args, **kwargs)
-
-        if self._is_new:
-            self._update_post_comment_count(1)
-
-        try:
-            ping_google()
-        except Exception:
-            logging.debug('problem pinging google did you register you sitemap with google?')
-
-    def mark_deleted(self, user):
-        if super(Comment, self).mark_deleted(user):
-            self._update_post_comment_count(-1)
-
-    def unmark_deleted(self):
-        if super(Comment, self).unmark_deleted():
-            self._update_post_comment_count(1)
-
-    def is_reply_to(self, user):
-        inreply = re.search('@\w+', self.comment)
-        if inreply is not None:
-            return user.username.startswith(inreply.group(0))
-
-        return False
-
-    def __unicode__(self):
-        return self.comment
-
-
-class LikedComment(models.Model):
-    comment       = models.ForeignKey(Comment)
-    user          = models.ForeignKey(User)
-    added_at      = models.DateTimeField(default=datetime.datetime.now)
-    canceled      = models.BooleanField(default=False)
-
-    active = ActiveObjectManager()
-
-    class Meta:
-        app_label = 'forum'
-
-    def _update_comment_score(self, diff):
-        self.comment.score = self.comment.score + diff
-        self.comment.save()
-
-    def save(self, *args, **kwargs):
-        super(LikedComment, self).save(*args, **kwargs)
-        if self._is_new:
-            self._update_comment_score(1)
-
-    def cancel(self):
-        if not self.canceled:
-            self.canceled = True
-            self.save()
-            self._update_comment_score(-1)
 
 
index 932452d9c064ceae0a7235434b24c193843edb53..530981beee4087d131de6d63255ae6724b1f1d34 100644 (file)
@@ -12,6 +12,10 @@ class NodeContent(models.Model):
     author     = models.ForeignKey(User, related_name='%(class)ss')\r
     body       = models.TextField()\r
 \r
+    @property\r
+    def user(self):\r
+        return self.author\r
+\r
     @property\r
     def html(self):\r
         return mark_safe(sanitize_html(markdown.markdown(self.body)))\r
@@ -20,10 +24,6 @@ class NodeContent(models.Model):
     def headline(self):\r
         return self.title\r
 \r
-    @property\r
-    def summary(self):\r
-        return strip_tags(self.html)[:300]\r
-\r
     def tagname_list(self):\r
         if self.tagnames:\r
             return [name for name in self.tagnames.split(u' ')]\r
@@ -58,17 +58,17 @@ class NodeMetaClass(models.Model.__metaclass__):
         name = node_cls.__name__.lower()\r
 \r
         def children(self):\r
-            return node_cls.objects.filter(parent=self)\r
+            if node_cls._meta.proxy:\r
+                return node_cls.objects.filter(node_type=name, parent=self)\r
+            else:\r
+                return node_cls.objects.filter(parent=self)\r
 \r
         def parent(self):\r
             p = self.__dict__.get('_%s_cache' % name, None)\r
 \r
-            if p is None:\r
-                try:\r
-                    p = self.parent.leaf\r
-                    self.__dict__['_%s_cache' % name] = p\r
-                except Exception, e:\r
-                    pass\r
+            if p is None and (self.parent is not None) and self.parent.node_type == name:\r
+                p = self.parent.leaf\r
+                self.__dict__['_%s_cache' % name] = p\r
 \r
             return p\r
 \r
@@ -76,6 +76,8 @@ class NodeMetaClass(models.Model.__metaclass__):
         Node.add_to_class(name, property(parent))\r
 \r
 \r
+node_create = django.dispatch.Signal(providing_args=['instance'])\r
+\r
 class Node(BaseModel, NodeContent, DeletableContent):\r
     __metaclass__ = NodeMetaClass\r
 \r
@@ -90,7 +92,7 @@ class Node(BaseModel, NodeContent, DeletableContent):
     vote_up_count         = models.IntegerField(default=0)\r
     vote_down_count       = models.IntegerField(default=0)\r
 \r
-    comment_count        = models.PositiveIntegerField(default=0)\r
+    comment_count         = models.PositiveIntegerField(default=0)\r
     offensive_flag_count  = models.SmallIntegerField(default=0)\r
 \r
     last_edited_at        = models.DateTimeField(null=True, blank=True)\r
@@ -102,6 +104,10 @@ class Node(BaseModel, NodeContent, DeletableContent):
     def leaf(self):\r
         return NodeMetaClass.types[self.node_type].objects.get(id=self.id)\r
 \r
+    @property\r
+    def summary(self):\r
+        return strip_tags(self.html)[:300]\r
+\r
     def create_revision(self, user, **kwargs):\r
         revision = NodeRevision(author=user, **kwargs)\r
         \r
@@ -120,13 +126,17 @@ class Node(BaseModel, NodeContent, DeletableContent):
         self.title = revision.title\r
         self.tagnames = revision.tagnames\r
         self.body = revision.body\r
-        \r
-        self.last_edited_at = datetime.datetime.now()\r
-        self.last_edited_by = user\r
+\r
+        old_revision = self.active_revision\r
 \r
         self.active_revision = revision\r
         self.save()\r
 \r
+        if not old_revision:\r
+            self.last_edited_at = datetime.datetime.now()\r
+            self.last_edited_by = user\r
+            node_create.send(sender=self.__class__, instance=self)\r
+\r
     def get_tag_list_if_changed(self):\r
         dirty = self.get_dirty_fields()\r
 \r
index 485576d5522af30a4d3935ba51f3016ff283802d..da8083f6d1407f41d46649fce8593ea59ee3d01d 100644 (file)
@@ -17,7 +17,7 @@ class Question(QandA):
     view_count           = models.IntegerField(default=0)
     favourite_count      = models.IntegerField(default=0)
     last_activity_at     = models.DateTimeField(default=datetime.datetime.now)
-    last_activity_by     = models.ForeignKey(User, related_name='last_active_in_questions')
+    last_activity_by     = models.ForeignKey(User, related_name='last_active_in_questions', null=True)
 
     favorited_by         = models.ManyToManyField(User, through='FavoriteQuestion', related_name='favorite_questions')
 
@@ -38,12 +38,10 @@ class Question(QandA):
     def answer_accepted(self):
         return self.accepted_answer is not None
 
-    def delete(self):
-        super(Question, self).delete()
-        try:
-            ping_google()
-        except Exception:
-            logging.debug('problem pinging google did you register you sitemap with google?')
+    def save(self, *args, **kwargs):
+        if not self.last_activity_by:
+            self.last_activity_by = self.author
+        super(Question, self).save(*args, **kwargs)
 
     def update_last_activity(self, user):
         self.last_activity_by = user
@@ -78,9 +76,6 @@ class Question(QandA):
     def get_revision_url(self):
         return reverse('question_revisions', args=[self.id])
 
-    def get_latest_revision(self):
-        return self.revisions.all()[0]
-
     def get_related_questions(self, count=10):
         cache_key = '%s.related_questions:%d:%d' % (settings.APP_URL, count, self.id)
         related_list = cache.get(cache_key)
index 40943514a40ba09800ced2c350c6ba18ff8fa4c7..6457de2b028115fd7a57d0f9d3194b0f4d73ee92 100644 (file)
@@ -87,8 +87,7 @@ class Award(GenericContent, UserContent):
         db_table = u'award'
 
 
-class Repute(UserContent):
-    """The reputation histories for user"""
+class Repute(MetaContent, CancelableContent, UserContent):
     value    = models.SmallIntegerField(default=0)
     question = models.ForeignKey('Question')
     reputed_at = models.DateTimeField(default=datetime.datetime.now)
@@ -112,6 +111,11 @@ class Repute(UserContent):
     def reputation(self):
         return self.user_previous_rep + self.value
 
+    def cancel(self):
+        if super(Repute, self).cancel():
+            self.user.reputation = self.user.reputation - self.value
+            self.user.save()
+
     def save(self, *args, **kwargs):
         self.user_previous_rep = self.user.reputation
         self.user.reputation = self.user.reputation + self.value
index 536663143a8851bd5f716c0d7701558a7f8d8cb1..ab5941435b12ed06580972b2864be96334f8f01a 100644 (file)
@@ -240,12 +240,14 @@ class Activity(GenericContent):
     @property\r
     def node(self):\r
         if self.activity_type in (const.TYPE_ACTIVITY_ANSWER, const.TYPE_ACTIVITY_ASK_QUESTION,\r
-                const.TYPE_ACTIVITY_MARK_ANSWER, const.TYPE_ACTIVITY_UPDATE_QUESTION):\r
+                const.TYPE_ACTIVITY_MARK_ANSWER):\r
             return self.content_object\r
 \r
-        if self.activity_type in (const.TYPE_ACTIVITY_COMMENT_QUESTION,\r
-                const.TYPE_ACTIVITY_COMMENT_ANSWER, const.TYPE_ACTIVITY_UPDATE_ANSWER):\r
-            return self.content_object.node.leaf\r
+        if self.activity_type in (const.TYPE_ACTIVITY_COMMENT_QUESTION, const.TYPE_ACTIVITY_COMMENT_ANSWER):\r
+            return self.content_object.parent.leaf\r
+\r
+        if self.activity_type in (const.TYPE_ACTIVITY_UPDATE_ANSWER, const.TYPE_ACTIVITY_UPDATE_QUESTION):\r
+            return self.content_object.node.leaf            \r
             \r
         raise NotImplementedError()\r
 \r
index 4a0fe7ea92754b37b4a473250328963ec48577fe..8ee3469ba27b62205c440a32064a8260f9c1e3ac 100644 (file)
@@ -1,5 +1,5 @@
 from django.db.models.signals import post_save\r
-from forum.models.meta import vote_canceled\r
+from forum.models.base import mark_canceled\r
 from forum.models.answer import answer_accepted, answer_accepted_canceled\r
 \r
 from forum.models import *\r
@@ -93,7 +93,7 @@ def on_vote_canceled(instance, **kwargs):
 \r
         post.author.reputes.create(value=repute_value, question=question, reputation_type=repute_type)\r
 \r
-vote_canceled.connect(on_vote_canceled)\r
+mark_canceled.connect(on_vote_canceled, sender=Vote)\r
 \r
 \r
     \r
index 022f19ca1e3a282298191a7bd73dd13cb3a941f0..e91db87709a08db23742ab22130f31e9552347ba 100644 (file)
@@ -9,7 +9,7 @@
                     {% if comment.score %}{{ comment.score }}{% endif %}\r
                 </td>\r
                 <td class="comment-text" id="comment-{{comment.id}}-text">\r
-                    {{ comment.comment }}\r
+                    {{ comment.body }}\r
                 </td>\r
             </tr>\r
             <tr>\r
index 96a1f36d17723a57b500ce098baf08becd422e53..6381b59691726beee42c5537628384dbd3297737 100644 (file)
                 </a>
                 <div class="answer-link">
                     {% spaceless %}
-                    <a href="{{ answer.get_absolute_url }}#{{answer.id}}">{{answer.question.title}}</a>
+                    <a href="{{ answer.get_absolute_url }}">{{answer.headline}}</a>
                     {% endspaceless %}
-                    {% if answer.comment_count %}
-                    <span>
-                                   {% blocktrans count answer.comment_count as comment_count %}
-                    (one comment)
-                    {% plural %}
-                    the answer has been commented {{comment_count}} times
-                    {% endblocktrans %}
-                    </span> 
-                    {% endif %}
                 </div>
             </div>
             {% endfor %}
index 4c5725650994f45c2dbc9d8579fc5db812c2884f..4966ec65772c1b44683d6a770b07fccdd855acbe 100644 (file)
@@ -3,6 +3,7 @@ import re
 import datetime\r
 from forum.models import User, Question, Comment, QuestionSubscription, SubscriptionSettings, Answer\r
 from forum.models.user import activity_record\r
+from forum.models.node import node_create\r
 from forum.utils.mail import send_email\r
 from forum.views.readers import question_view\r
 from django.utils.translation import ugettext as _\r
@@ -25,9 +26,7 @@ def apply_default_filters(queryset, excluded_id):
 def create_recipients_dict(usr_list):\r
     return [(s['username'], s['email'], {'username': s['username']}) for s in usr_list]\r
 \r
-def question_posted(instance, created, **kwargs):\r
-    if not created: return\r
-\r
+def question_posted(instance, **kwargs):\r
     question = instance\r
 \r
     subscribers = User.objects.values('email', 'username').filter(\r
@@ -57,12 +56,10 @@ def question_posted(instance, created, **kwargs):
     for user in new_subscribers:\r
         create_subscription_if_not_exists(question, user)\r
 \r
-#post_save.connect(question_posted, sender=Question)\r
-\r
+node_create.connect(question_posted, sender=Question)\r
 \r
-def answer_posted(instance, created, **kwargs):\r
-    if not created: return\r
 \r
+def answer_posted(instance, **kwargs):\r
     answer = instance\r
     question = answer.question\r
 \r
@@ -82,11 +79,11 @@ def answer_posted(instance, created, **kwargs):
     if answer.author.subscription_settings.questions_answered:\r
         create_subscription_if_not_exists(question, answer.author)\r
 \r
-post_save.connect(answer_posted, sender=Answer)\r
+node_create.connect(answer_posted, sender=Answer)\r
 \r
 \r
-def comment_posted(sender, instance, **kwargs):\r
-    comment = instance.content_object\r
+def comment_posted(instance, **kwargs):\r
+    comment = instance\r
     post = comment.content_object\r
 \r
     if post.__class__ == Question:\r
@@ -107,7 +104,7 @@ def comment_posted(sender, instance, **kwargs):
                                 )\r
 \r
     subscribers = subscribers.filter(\r
-            q_filter, subscription_settings__subscribed_questions='i', subscription_settings__enable_notifications=True \r
+            q_filter, subscription_settings__subscribed_questions='i', subscription_settings__enable_notifications=True\r
     ).exclude(id=comment.user.id).distinct()\r
 \r
     recipients = create_recipients_dict(subscribers)\r
@@ -122,8 +119,7 @@ def comment_posted(sender, instance, **kwargs):
     if comment.user.subscription_settings.questions_commented:\r
         create_subscription_if_not_exists(question, comment.user)\r
 \r
-activity_record.connect(comment_posted, sender=const.TYPE_ACTIVITY_COMMENT_QUESTION, weak=False)\r
-activity_record.connect(comment_posted, sender=const.TYPE_ACTIVITY_COMMENT_ANSWER, weak=False)\r
+node_create.connect(comment_posted, sender=Comment)\r
 \r
 \r
 def answer_accepted(instance, created, **kwargs):\r
index 4b48f2e7807ece0f38ff4b46f69ae64de7b5ecdf..8a6b069920c281275b13ab2ed886c0ba86ce808b 100644 (file)
@@ -1,6 +1,6 @@
 from datetime import datetime, timedelta\r
 \r
-from forum.models import Question, FavoriteQuestion, LikedComment\r
+from forum.models import Question, FavoriteQuestion\r
 from django.utils.translation import ugettext as _\r
 from django.core.urlresolvers import reverse\r
 from django import template\r
@@ -107,7 +107,7 @@ def comments(post, user):
         \r
         if context['can_like']:\r
             try:\r
-                LikedComment.active.get(comment=c, user=user)\r
+                c.votes.get(user=user)\r
                 context['likes'] = True\r
             except:\r
                 context['likes'] = False\r
index 89f3fb8aaaf78137897e2b4fe72b7895a039b0cf..e2942bde8d36e03e8dbe8d5fc1424866dea7c378 100644 (file)
@@ -232,17 +232,16 @@ def comment(request, id):
         if not user.can_comment(post):
             raise NotEnoughRepPointsException( _('comment'))
 
-        comment = Comment(user=user, node=post)
+        comment = Comment(parent=post)
 
     comment_text = request.POST.get('comment', '').strip()
 
     if not len(comment_text):
         raise Exception(_("Comment is empty"))
 
-    comment.comment=comment_text
-    comment.save()
+    comment.create_revision(user, body=comment_text)
 
-    if comment._is_new:
+    if comment.active_revision.revision == 1:
         return {
             'commands': {
                 'insert_comment': [