From: jordan Date: Mon, 7 Mar 2011 22:10:47 +0000 (+0000) Subject: Merging jambazov --> trunk. X-Git-Tag: live~443 X-Git-Url: https://git.openstreetmap.org/osqa.git/commitdiff_plain/c6c168511f18d8984901b2c828a47310a2d54d64 Merging jambazov --> trunk. git-svn-id: http://svn.osqa.net/svnroot/osqa/trunk@796 0cfe37f9-358a-4d5e-be75-b63607b5c754 --- diff --git a/forum/actions/node.py b/forum/actions/node.py index cd39924..530c649 100644 --- a/forum/actions/node.py +++ b/forum/actions/node.py @@ -2,6 +2,7 @@ from django.utils.html import strip_tags from django.utils.translation import ugettext as _ from forum.models.action import ActionProxy from forum.models import Comment, Question, Answer, NodeRevision +import logging class NodeEditAction(ActionProxy): def create_revision_data(self, initial=False, **data): @@ -201,6 +202,8 @@ class AnswerToQuestionAction(ActionProxy): def process_data(self, title): self.node.node_type = "question" self.node.title = title + self.node.active_revision.title = title + self.node.active_revision.save() self.node.last_edited = self self.node.update_last_activity(self.user, save=True) diff --git a/forum/actions/user.py b/forum/actions/user.py index 50d1a73..5b818c7 100644 --- a/forum/actions/user.py +++ b/forum/actions/user.py @@ -23,6 +23,23 @@ class UserJoinsAction(ActionProxy): 'app_name': APP_SHORT_NAME, } +class EmailValidationAction(ActionProxy): + verb = _("validated e-mail") + + def repute_users(self): + self.repute(self.user, int(settings.REP_GAIN_BY_EMAIL_VALIDATION)) + + def process_action(self): + self.user.email_isvalid = True + self.user.save() + + def describe(self, viewer=None): + return _("%(user)s %(have_has)s validated the e-mail %(email)s") % { + 'user': self.hyperlink(self.user.get_profile_url(), self.friendly_username(viewer, self.user)), + 'have_has': self.viewer_or_user_verb(viewer, self.user, _('have'), _('has')), + 'email' : self.user.email + } + class EditProfileAction(ActionProxy): verb = _("edited profile") diff --git a/forum/forms/qanda.py b/forum/forms/qanda.py index 9890640..e107ad2 100644 --- a/forum/forms/qanda.py +++ b/forum/forms/qanda.py @@ -17,8 +17,8 @@ class TitleField(forms.CharField): def __init__(self, *args, **kwargs): super(TitleField, self).__init__(*args, **kwargs) self.required = True - self.widget = forms.TextInput(attrs={'size' : 70, 'autocomplete' : 'off'}) self.max_length = 255 + self.widget = forms.TextInput(attrs={'size' : 70, 'autocomplete' : 'off', 'maxlength' : self.max_length}) self.label = _('title') self.help_text = _('please enter a descriptive title for your question') self.initial = '' diff --git a/forum/management/commands/maintaindb.py b/forum/management/commands/maintaindb.py new file mode 100644 index 0000000..a2fc8de --- /dev/null +++ b/forum/management/commands/maintaindb.py @@ -0,0 +1,66 @@ +from django.core.management.base import BaseCommand, CommandError +from forum.models import Node, NodeRevision + +import logging + +# Used to activate the latest revision connected to some node +def activate_latest_revision(node): + # We're adding a new try-except block just in case that function has been called incorrectly. + try: + # The latest revision is the one that was added the last. + rev = node.revisions.all().order_by('-pk')[0] + node.active_revision_id = rev.id + node.save() + + return rev + except: + logging.error("Incorrect attempt to activate the latest revision of a node \ + that has no revisions at all has been made.") + return None + +# Used to create a new NodeRevision object according to the node content +def create_revision(node): + rev = NodeRevision( + author_id = node.author_id, + body = node.body, + node_id = node.id, + revised_at = node.added_at, + revision = 1, + summary = 'Initial revision', + tagnames = node.tagnames, + title = node.title, + ) + + node.save() + + return node + +class Command(BaseCommand): + + def handle(self,*args, **options): + print 'Running MaintainDb' + + nodes = Node.objects.all() + + for node in nodes: + if node.active_revision is None: + print "Node #%(node_id)d: NodeRevision doesn't exist" % dict(node_id=node.id) + + # We currently don't have any active revision for this Node. Let's check if there are any revisions + # at all for it. If there are any we activate the last. + if node.revisions.all().count() > 0: + print " We have revisions for Node #%(node_id)d." % dict(node_id=node.id) + + # If there are already some revisions connected to the current node, we activate the latest + activate_latest_revision(node) + else: + print " We don't have revisions for Node #%(node_id)d. We're "\ + "going to create a new one from the current node content."% dict(node_id=node.id) + + # First of all we're going to create a new revision according to the current node data... + create_revision(node) + + # ...and after that we're going to activate it + activate_latest_revision(node) + + #print rev.node diff --git a/forum/middleware/admin_messages.py b/forum/middleware/admin_messages.py new file mode 100644 index 0000000..2d391de --- /dev/null +++ b/forum/middleware/admin_messages.py @@ -0,0 +1,60 @@ +from forum.user_messages import create_message +from django.utils.translation import ugettext as _ +from django.core.urlresolvers import reverse +from django.core.exceptions import ObjectDoesNotExist + +from forum.settings import EMAIL_HOST, EMAIL_HOST_USER, EMAIL_HOST_PASSWORD, \ + APP_URL + +class AdminMessagesMiddleware(object): + def process_request(self, request): + # Check if the email settings are configured + self.check_email_settings(request) + + # Check if the APP_URL setting is configured + self.check_app_url(request) + + def check_email_settings(self, request): + # We want to warn only the administrators that the email settings are not configured. + # So, first of all we check if we're dealing with the administrators and after that if + # the SMTP settings are configured at all. We suppose that the SMTP settings are not configured + # if the EMAIL_HOST, the EMAIL_HOST_USER and the EMAIL_HOST_PASSWORD are not set at all. + if request.user.is_authenticated and request.user.is_staff and request.user.is_superuser and \ + EMAIL_HOST == '' and EMAIL_HOST_USER == '' and EMAIL_HOST_PASSWORD == '': + + msg = _(""" + The e-mail settings of this community are not configured yet. We strongly recommend you to + do that from the e-mail settings page as soon as possible. + """ % dict(email_settings_url=reverse('admin_set', kwargs={'set_name':'email'}))) + + # We do not want to repeat ourselves. If the message already exists in the message list, we're not going to + # add it. That's why first of all we're going the check if it is there. + try: + # If the message doesn't exist in the RelatedManager ObjectsDoesNotExist is going to be raised. + request.user.message_set.all().get(message=msg) + except ObjectDoesNotExist: + # Let's create the message. + request.user.message_set.create(message=msg) + except: + pass + + def check_app_url(self, request): + # We consider the APP_URL setting not configured if it contains only the protocol + # name or if it's shorter than 7 characters. + if request.user.is_authenticated and request.user.is_staff and request.user.is_superuser and \ + APP_URL == 'http://' or APP_URL == 'https://' or len(APP_URL) < 7: + + msg = _(""" + Please, configure your APP_URL setting from the local settings file. + """) + + # We do not want to repeat ourselves. If the message already exists in the message list, we're not going to + # add it. That's why first of all we're going the check if it is there. + try: + # If the message doesn't exist in the RelatedManager ObjectsDoesNotExist is going to be raised. + request.user.message_set.all().get(message=msg) + except ObjectDoesNotExist: + # Let's create the message. + request.user.message_set.create(message=msg) + except: + pass diff --git a/forum/migrations/0045_auto__add_openidassociation__add_openidnonce__add_field_tag_created_at.py b/forum/migrations/0045_auto__add_openidassociation__add_openidnonce__add_field_tag_created_at.py new file mode 100644 index 0000000..898d5c0 --- /dev/null +++ b/forum/migrations/0045_auto__add_openidassociation__add_openidnonce__add_field_tag_created_at.py @@ -0,0 +1,270 @@ +# 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 field 'Tag.created_at' + db.add_column('forum_tag', 'created_at', self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime.now, null=True, blank=True), keep_default=False) + + + def backwards(self, orm): + # Deleting field 'Tag.created_at' + db.delete_column('forum_tag', 'created_at') + + + models = { + 'auth.group': { + 'Meta': {'object_name': 'Group'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'}) + }, + 'auth.permission': { + 'Meta': {'ordering': "('content_type__app_label', 'codename')", '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'}, + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + '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'}) + }, + 'contenttypes.contenttype': { + 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + 'forum.action': { + 'Meta': {'object_name': 'Action'}, + 'action_date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'action_type': ('django.db.models.fields.CharField', [], {'max_length': '16'}), + 'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'canceled_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}), + 'canceled_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'canceled_actions'", 'null': 'True', 'to': "orm['forum.User']"}), + 'canceled_ip': ('django.db.models.fields.CharField', [], {'max_length': '16'}), + 'extra': ('forum.models.utils.PickledObjectField', [], {'null': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'ip': ('django.db.models.fields.CharField', [], {'max_length': '16'}), + 'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'actions'", 'null': 'True', 'to': "orm['forum.Node']"}), + 'real_user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'proxied_actions'", 'null': 'True', 'to': "orm['forum.User']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'actions'", 'to': "orm['forum.User']"}) + }, + 'forum.actionrepute': { + 'Meta': {'object_name': 'ActionRepute'}, + 'action': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'to': "orm['forum.Action']"}), + 'by_canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'to': "orm['forum.User']"}), + 'value': ('django.db.models.fields.IntegerField', [], {'default': '0'}) + }, + 'forum.authkeyuserassociation': { + 'Meta': {'object_name': 'AuthKeyUserAssociation'}, + 'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), + 'provider': ('django.db.models.fields.CharField', [], {'max_length': '64'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'auth_keys'", 'to': "orm['forum.User']"}) + }, + 'forum.award': { + 'Meta': {'unique_together': "(('user', 'badge', 'node'),)", 'object_name': 'Award'}, + 'action': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'award'", 'unique': 'True', 'to': "orm['forum.Action']"}), + 'awarded_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'badge': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'awards'", 'to': "orm['forum.Badge']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'node': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']", 'null': 'True'}), + 'trigger': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'awards'", 'null': 'True', 'to': "orm['forum.Action']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"}) + }, + 'forum.badge': { + 'Meta': {'object_name': '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['forum.User']"}), + 'cls': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'type': ('django.db.models.fields.SmallIntegerField', [], {}) + }, + 'forum.flag': { + 'Meta': {'unique_together': "(('user', 'node'),)", 'object_name': 'Flag'}, + 'action': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'flag'", 'unique': 'True', 'to': "orm['forum.Action']"}), + 'flagged_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'flags'", 'to': "orm['forum.Node']"}), + 'reason': ('django.db.models.fields.CharField', [], {'max_length': '300'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'flags'", 'to': "orm['forum.User']"}) + }, + 'forum.keyvalue': { + 'Meta': {'object_name': 'KeyValue'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), + 'value': ('forum.models.utils.PickledObjectField', [], {'null': 'True'}) + }, + 'forum.markedtag': { + 'Meta': {'object_name': 'MarkedTag'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'reason': ('django.db.models.fields.CharField', [], {'max_length': '16'}), + 'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_selections'", 'to': "orm['forum.Tag']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tag_selections'", 'to': "orm['forum.User']"}) + }, + 'forum.node': { + 'Meta': {'object_name': 'Node'}, + 'abs_parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'all_children'", 'null': 'True', 'to': "orm['forum.Node']"}), + 'active_revision': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'active'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.NodeRevision']"}), + 'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'nodes'", 'to': "orm['forum.User']"}), + 'body': ('django.db.models.fields.TextField', [], {}), + 'extra': ('forum.models.utils.PickledObjectField', [], {'null': 'True'}), + 'extra_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'extra_ref': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']", 'null': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'last_activity_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'last_activity_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']", 'null': 'True'}), + 'last_edited': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'edited_node'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.Action']"}), + 'marked': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'node_type': ('django.db.models.fields.CharField', [], {'default': "'node'", 'max_length': '16'}), + 'parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'children'", 'null': 'True', 'to': "orm['forum.Node']"}), + 'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'state_string': ('django.db.models.fields.TextField', [], {'default': "''"}), + 'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}), + 'tags': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'nodes'", 'to': "orm['forum.Tag']"}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}) + }, + 'forum.noderevision': { + 'Meta': {'unique_together': "(('node', 'revision'),)", 'object_name': 'NodeRevision'}, + 'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'noderevisions'", 'to': "orm['forum.User']"}), + 'body': ('django.db.models.fields.TextField', [], {}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'revisions'", 'to': "orm['forum.Node']"}), + 'revised_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'revision': ('django.db.models.fields.PositiveIntegerField', [], {}), + 'summary': ('django.db.models.fields.CharField', [], {'max_length': '300'}), + 'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}) + }, + 'forum.nodestate': { + 'Meta': {'unique_together': "(('node', 'state_type'),)", 'object_name': 'NodeState'}, + 'action': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'node_state'", 'unique': 'True', 'to': "orm['forum.Action']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'states'", 'to': "orm['forum.Node']"}), + 'state_type': ('django.db.models.fields.CharField', [], {'max_length': '16'}) + }, + 'forum.openidassociation': { + 'Meta': {'object_name': 'OpenIdAssociation'}, + 'assoc_type': ('django.db.models.fields.TextField', [], {'max_length': '64'}), + 'handle': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'issued': ('django.db.models.fields.IntegerField', [], {}), + 'lifetime': ('django.db.models.fields.IntegerField', [], {}), + 'secret': ('django.db.models.fields.TextField', [], {'max_length': '255'}), + 'server_url': ('django.db.models.fields.TextField', [], {'max_length': '2047'}) + }, + 'forum.openidnonce': { + 'Meta': {'object_name': 'OpenIdNonce'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'salt': ('django.db.models.fields.CharField', [], {'max_length': '50'}), + 'server_url': ('django.db.models.fields.URLField', [], {'max_length': '200'}), + 'timestamp': ('django.db.models.fields.IntegerField', [], {}) + }, + 'forum.questionsubscription': { + 'Meta': {'object_name': 'QuestionSubscription'}, + 'auto_subscription': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'last_view': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2011, 3, 3, 18, 19, 21, 244056)'}), + 'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"}) + }, + 'forum.subscriptionsettings': { + 'Meta': {'object_name': 'SubscriptionSettings'}, + 'all_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'all_questions_watched_tags': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'enable_notifications': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'member_joins': ('django.db.models.fields.CharField', [], {'default': "'n'", 'max_length': '1'}), + 'new_question': ('django.db.models.fields.CharField', [], {'default': "'n'", 'max_length': '1'}), + 'new_question_watched_tags': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}), + 'notify_accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'notify_answers': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'notify_comments': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'notify_comments_own_post': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'notify_reply_to_comments': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'questions_answered': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'questions_asked': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'questions_commented': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'questions_viewed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'send_digest': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'subscribed_questions': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}), + 'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'subscription_settings'", 'unique': 'True', 'to': "orm['forum.User']"}) + }, + 'forum.tag': { + 'Meta': {'ordering': "('-used_count', 'name')", 'object_name': 'Tag'}, + 'created_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now', 'null': 'True', 'blank': 'True'}), + 'created_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'created_tags'", 'to': "orm['forum.User']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'marked_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'marked_tags'", 'through': "'MarkedTag'", 'to': "orm['forum.User']"}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), + 'used_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}) + }, + 'forum.user': { + 'Meta': {'object_name': 'User', '_ormbases': ['auth.User']}, + 'about': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'bronze': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'date_of_birth': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}), + 'email_isvalid': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'gold': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'is_approved': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'last_seen': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'location': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}), + 'real_name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}), + 'reputation': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'silver': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'subscriptions': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'subscribers'", 'through': "'QuestionSubscription'", 'to': "orm['forum.Node']"}), + 'user_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True', 'primary_key': 'True'}), + 'website': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}) + }, + 'forum.userproperty': { + 'Meta': {'unique_together': "(('user', 'key'),)", 'object_name': 'UserProperty'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'key': ('django.db.models.fields.CharField', [], {'max_length': '16'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'properties'", 'to': "orm['forum.User']"}), + 'value': ('forum.models.utils.PickledObjectField', [], {'null': 'True'}) + }, + 'forum.validationhash': { + 'Meta': {'unique_together': "(('user', 'type'),)", 'object_name': 'ValidationHash'}, + 'expiration': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2011, 3, 4, 18, 19, 21, 460663)'}), + 'hash_code': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'seed': ('django.db.models.fields.CharField', [], {'max_length': '12'}), + 'type': ('django.db.models.fields.CharField', [], {'max_length': '12'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"}) + }, + 'forum.vote': { + 'Meta': {'unique_together': "(('user', 'node'),)", 'object_name': 'Vote'}, + 'action': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'vote'", 'unique': 'True', 'to': "orm['forum.Action']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'votes'", 'to': "orm['forum.Node']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'votes'", 'to': "orm['forum.User']"}), + 'value': ('django.db.models.fields.SmallIntegerField', [], {}), + 'voted_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}) + } + } + + complete_apps = ['forum'] diff --git a/forum/migrations/0046_set_tag_dates.py b/forum/migrations/0046_set_tag_dates.py new file mode 100644 index 0000000..78081a7 --- /dev/null +++ b/forum/migrations/0046_set_tag_dates.py @@ -0,0 +1,279 @@ +# encoding: utf-8 +import datetime +from south.db import db +from south.v2 import DataMigration +from django.db import models +from forum.models import Tag, Question +from urllib import unquote + +class Migration(DataMigration): + + def forwards(self, orm): + for tag in Tag.objects.all(): + try: + question = Question.objects.filter(tags__name=unquote(tag.name)).order_by('pk')[0] + date = question.added_at + tag.created_at = date + tag.save() + print str(date) + except: + pass + + + def backwards(self, orm): + "Write your backwards methods here." + + + models = { + 'auth.group': { + 'Meta': {'object_name': 'Group'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'}) + }, + 'auth.permission': { + 'Meta': {'ordering': "('content_type__app_label', 'codename')", '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'}, + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + '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'}) + }, + 'contenttypes.contenttype': { + 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + 'forum.action': { + 'Meta': {'object_name': 'Action'}, + 'action_date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'action_type': ('django.db.models.fields.CharField', [], {'max_length': '16'}), + 'canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'canceled_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}), + 'canceled_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'canceled_actions'", 'null': 'True', 'to': "orm['forum.User']"}), + 'canceled_ip': ('django.db.models.fields.CharField', [], {'max_length': '16'}), + 'extra': ('forum.models.utils.PickledObjectField', [], {'null': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'ip': ('django.db.models.fields.CharField', [], {'max_length': '16'}), + 'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'actions'", 'null': 'True', 'to': "orm['forum.Node']"}), + 'real_user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'proxied_actions'", 'null': 'True', 'to': "orm['forum.User']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'actions'", 'to': "orm['forum.User']"}) + }, + 'forum.actionrepute': { + 'Meta': {'object_name': 'ActionRepute'}, + 'action': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'to': "orm['forum.Action']"}), + 'by_canceled': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reputes'", 'to': "orm['forum.User']"}), + 'value': ('django.db.models.fields.IntegerField', [], {'default': '0'}) + }, + 'forum.authkeyuserassociation': { + 'Meta': {'object_name': 'AuthKeyUserAssociation'}, + 'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), + 'provider': ('django.db.models.fields.CharField', [], {'max_length': '64'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'auth_keys'", 'to': "orm['forum.User']"}) + }, + 'forum.award': { + 'Meta': {'unique_together': "(('user', 'badge', 'node'),)", 'object_name': 'Award'}, + 'action': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'award'", 'unique': 'True', 'to': "orm['forum.Action']"}), + 'awarded_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'badge': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'awards'", 'to': "orm['forum.Badge']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'node': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']", 'null': 'True'}), + 'trigger': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'awards'", 'null': 'True', 'to': "orm['forum.Action']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"}) + }, + 'forum.badge': { + 'Meta': {'object_name': '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['forum.User']"}), + 'cls': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'type': ('django.db.models.fields.SmallIntegerField', [], {}) + }, + 'forum.flag': { + 'Meta': {'unique_together': "(('user', 'node'),)", 'object_name': 'Flag'}, + 'action': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'flag'", 'unique': 'True', 'to': "orm['forum.Action']"}), + 'flagged_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'flags'", 'to': "orm['forum.Node']"}), + 'reason': ('django.db.models.fields.CharField', [], {'max_length': '300'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'flags'", 'to': "orm['forum.User']"}) + }, + 'forum.keyvalue': { + 'Meta': {'object_name': 'KeyValue'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), + 'value': ('forum.models.utils.PickledObjectField', [], {'null': 'True'}) + }, + 'forum.markedtag': { + 'Meta': {'object_name': 'MarkedTag'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'reason': ('django.db.models.fields.CharField', [], {'max_length': '16'}), + 'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_selections'", 'to': "orm['forum.Tag']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tag_selections'", 'to': "orm['forum.User']"}) + }, + 'forum.node': { + 'Meta': {'object_name': 'Node'}, + 'abs_parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'all_children'", 'null': 'True', 'to': "orm['forum.Node']"}), + 'active_revision': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'active'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.NodeRevision']"}), + 'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'nodes'", 'to': "orm['forum.User']"}), + 'body': ('django.db.models.fields.TextField', [], {}), + 'extra': ('forum.models.utils.PickledObjectField', [], {'null': 'True'}), + 'extra_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'extra_ref': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']", 'null': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'last_activity_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'last_activity_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']", 'null': 'True'}), + 'last_edited': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'edited_node'", 'unique': 'True', 'null': 'True', 'to': "orm['forum.Action']"}), + 'marked': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'node_type': ('django.db.models.fields.CharField', [], {'default': "'node'", 'max_length': '16'}), + 'parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'children'", 'null': 'True', 'to': "orm['forum.Node']"}), + 'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'state_string': ('django.db.models.fields.TextField', [], {'default': "''"}), + 'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}), + 'tags': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'nodes'", 'to': "orm['forum.Tag']"}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}) + }, + 'forum.noderevision': { + 'Meta': {'unique_together': "(('node', 'revision'),)", 'object_name': 'NodeRevision'}, + 'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'noderevisions'", 'to': "orm['forum.User']"}), + 'body': ('django.db.models.fields.TextField', [], {}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'revisions'", 'to': "orm['forum.Node']"}), + 'revised_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'revision': ('django.db.models.fields.PositiveIntegerField', [], {}), + 'summary': ('django.db.models.fields.CharField', [], {'max_length': '300'}), + 'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}) + }, + 'forum.nodestate': { + 'Meta': {'unique_together': "(('node', 'state_type'),)", 'object_name': 'NodeState'}, + 'action': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'node_state'", 'unique': 'True', 'to': "orm['forum.Action']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'states'", 'to': "orm['forum.Node']"}), + 'state_type': ('django.db.models.fields.CharField', [], {'max_length': '16'}) + }, + 'forum.openidassociation': { + 'Meta': {'object_name': 'OpenIdAssociation'}, + 'assoc_type': ('django.db.models.fields.TextField', [], {'max_length': '64'}), + 'handle': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'issued': ('django.db.models.fields.IntegerField', [], {}), + 'lifetime': ('django.db.models.fields.IntegerField', [], {}), + 'secret': ('django.db.models.fields.TextField', [], {'max_length': '255'}), + 'server_url': ('django.db.models.fields.TextField', [], {'max_length': '2047'}) + }, + 'forum.openidnonce': { + 'Meta': {'object_name': 'OpenIdNonce'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'salt': ('django.db.models.fields.CharField', [], {'max_length': '50'}), + 'server_url': ('django.db.models.fields.URLField', [], {'max_length': '200'}), + 'timestamp': ('django.db.models.fields.IntegerField', [], {}) + }, + 'forum.questionsubscription': { + 'Meta': {'object_name': 'QuestionSubscription'}, + 'auto_subscription': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'last_view': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2011, 3, 3, 19, 8, 39, 301998)'}), + 'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.Node']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"}) + }, + 'forum.subscriptionsettings': { + 'Meta': {'object_name': 'SubscriptionSettings'}, + 'all_questions': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'all_questions_watched_tags': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'enable_notifications': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'member_joins': ('django.db.models.fields.CharField', [], {'default': "'n'", 'max_length': '1'}), + 'new_question': ('django.db.models.fields.CharField', [], {'default': "'n'", 'max_length': '1'}), + 'new_question_watched_tags': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}), + 'notify_accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'notify_answers': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'notify_comments': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'notify_comments_own_post': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'notify_reply_to_comments': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'questions_answered': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'questions_asked': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'questions_commented': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'questions_viewed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'send_digest': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'subscribed_questions': ('django.db.models.fields.CharField', [], {'default': "'i'", 'max_length': '1'}), + 'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'subscription_settings'", 'unique': 'True', 'to': "orm['forum.User']"}) + }, + 'forum.tag': { + 'Meta': {'ordering': "('-used_count', 'name')", 'object_name': 'Tag'}, + 'created_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now', 'null': 'True', 'blank': 'True'}), + 'created_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'created_tags'", 'to': "orm['forum.User']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'marked_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'marked_tags'", 'through': "'MarkedTag'", 'to': "orm['forum.User']"}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), + 'used_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}) + }, + 'forum.user': { + 'Meta': {'object_name': 'User', '_ormbases': ['auth.User']}, + 'about': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'bronze': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'date_of_birth': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}), + 'email_isvalid': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'gold': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'is_approved': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'last_seen': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'location': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}), + 'real_name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}), + 'reputation': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'silver': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'subscriptions': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'subscribers'", 'through': "'QuestionSubscription'", 'to': "orm['forum.Node']"}), + 'user_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True', 'primary_key': 'True'}), + 'website': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}) + }, + 'forum.userproperty': { + 'Meta': {'unique_together': "(('user', 'key'),)", 'object_name': 'UserProperty'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'key': ('django.db.models.fields.CharField', [], {'max_length': '16'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'properties'", 'to': "orm['forum.User']"}), + 'value': ('forum.models.utils.PickledObjectField', [], {'null': 'True'}) + }, + 'forum.validationhash': { + 'Meta': {'unique_together': "(('user', 'type'),)", 'object_name': 'ValidationHash'}, + 'expiration': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2011, 3, 4, 19, 8, 39, 353678)'}), + 'hash_code': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'seed': ('django.db.models.fields.CharField', [], {'max_length': '12'}), + 'type': ('django.db.models.fields.CharField', [], {'max_length': '12'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['forum.User']"}) + }, + 'forum.vote': { + 'Meta': {'unique_together': "(('user', 'node'),)", 'object_name': 'Vote'}, + 'action': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'vote'", 'unique': 'True', 'to': "orm['forum.Action']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'node': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'votes'", 'to': "orm['forum.Node']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'votes'", 'to': "orm['forum.User']"}), + 'value': ('django.db.models.fields.SmallIntegerField', [], {}), + 'voted_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}) + } + } + + complete_apps = ['forum'] + diff --git a/forum/models/node.py b/forum/models/node.py index ebe9139..abd1f5a 100644 --- a/forum/models/node.py +++ b/forum/models/node.py @@ -7,6 +7,7 @@ from django.utils.translation import ugettext as _ from django.utils.safestring import mark_safe from django.utils.html import strip_tags from forum.utils.html import sanitize_html +from forum.settings import SUMMARY_LENGTH from utils import PickledObjectField class NodeContent(models.Model): @@ -304,7 +305,7 @@ class Node(BaseModel, NodeContent): @property def summary(self): - return strip_tags(self.html)[:300] + return strip_tags(self.html)[:SUMMARY_LENGTH] @models.permalink def get_revisions_url(self): diff --git a/forum/models/tag.py b/forum/models/tag.py index 0bff004..44e0a74 100644 --- a/forum/models/tag.py +++ b/forum/models/tag.py @@ -1,3 +1,4 @@ +import datetime from base import * from django.utils.translation import ugettext as _ @@ -11,6 +12,7 @@ class ActiveTagManager(models.Manager): class Tag(BaseModel): name = models.CharField(max_length=255, unique=True) created_by = models.ForeignKey(User, related_name='created_tags') + created_at = models.DateTimeField(default=datetime.datetime.now, blank=True, null=True) marked_by = models.ManyToManyField(User, related_name="marked_tags", through="MarkedTag") # Denormalised data used_count = models.PositiveIntegerField(default=0) @@ -22,7 +24,7 @@ class Tag(BaseModel): app_label = 'forum' def __unicode__(self): - return self.name + return u'%s' % self.name def add_to_usage_count(self, value): if self.used_count + value < 0: diff --git a/forum/settings/email.py b/forum/settings/email.py index 5e8bddf..ec27101 100644 --- a/forum/settings/email.py +++ b/forum/settings/email.py @@ -2,6 +2,7 @@ from base import Setting, SettingSet from django.utils.translation import ugettext_lazy as _ from django.forms.widgets import PasswordInput from django.forms.widgets import RadioSelect +from forms import TestEmailSettingsWidget EMAIL_SET = SettingSet('email', _('Email settings'), _("Email server and other email related settings."), 50) @@ -17,6 +18,12 @@ choices=EMAIL_SUBSCRIBE_CHOICES, help_text = _("Choose what should be the default email subscription status while registering."), required=False)) +TEST_EMAIL_SETTINGS = Setting('TEST_EMAIL_SETTINGS', '', EMAIL_SET, dict( +label = _("E-Mail settings test"), +help_text = _("Test the current E-Mail configuration."), +required=False, +widget=TestEmailSettingsWidget)) + EMAIL_HOST = Setting('EMAIL_HOST', '', EMAIL_SET, dict( label = _("Email Server"), help_text = _("The SMTP server through which your application will be sending emails."), diff --git a/forum/settings/forms.py b/forum/settings/forms.py index 0c12301..3e3cc5a 100644 --- a/forum/settings/forms.py +++ b/forum/settings/forms.py @@ -4,6 +4,7 @@ from django import forms from forum.settings.base import Setting from django.utils.translation import ugettext as _ from django.core.files.storage import FileSystemStorage +from django.core.urlresolvers import reverse class DummySetting: pass @@ -120,7 +121,20 @@ class CommaStringListWidget(forms.Textarea): else: return ', '.join(data[name]) +class TestEmailSettingsWidget(forms.TextInput): + def render(self, name, value, attrs=None): + if not value: + value = '' - - - + return """ +
+ Test + +
+ +
+
+
+ """ % reverse("test_email_settings") \ No newline at end of file diff --git a/forum/settings/repgain.py b/forum/settings/repgain.py index cfb566b..6b283ec 100644 --- a/forum/settings/repgain.py +++ b/forum/settings/repgain.py @@ -11,6 +11,10 @@ MAX_REP_BY_UPVOTE_DAY = Setting('MAX_REP_BY_UPVOTE_DAY', 200, REP_GAIN_SET, dict label = "Max rep by up votes / day", help_text = _("Maximum reputation a user can gain in one day for being upvoted."))) +REP_GAIN_BY_EMAIL_VALIDATION = Setting('REP_GAIN_BY_EMAIL_VALIDATION', 10, REP_GAIN_SET, dict( +label = _("Rep gain by e-mail validation"), +help_text = _("Reputation a user gains for validating his e-mail."))) + REP_GAIN_BY_UPVOTED = Setting('REP_GAIN_BY_UPVOTED', 10, REP_GAIN_SET, dict( label = _("Rep gain by upvoted"), help_text = _("Reputation a user gains for having one of his posts up voted."))) diff --git a/forum/settings/view.py b/forum/settings/view.py index 1eb44b0..fa6edf3 100644 --- a/forum/settings/view.py +++ b/forum/settings/view.py @@ -4,6 +4,10 @@ from django.utils.translation import ugettext_lazy as _ """ view settings """ VIEW_SET = SettingSet('view', _('View settings'), _("Set up how certain parts of the site are displayed."), 20) +SUMMARY_LENGTH = Setting('SUMMARY_LENGTH', 300, VIEW_SET, dict( +label = _("Summary Length"), +help_text = _("The number of characters that are going to be displayed in order to get the content summary."))) + RECENT_TAGS_SIZE = Setting('RECENT_TAGS_SIZE', 25, VIEW_SET, dict( label = _("Recent tags block size"), help_text = _("The number of tags to display in the recent tags block in the front page."))) diff --git a/forum/skins/default/media/js/osqa.admin.js b/forum/skins/default/media/js/osqa.admin.js index ee4feed..ccd7103 100644 --- a/forum/skins/default/media/js/osqa.admin.js +++ b/forum/skins/default/media/js/osqa.admin.js @@ -58,12 +58,22 @@ $(function() { $input.keyup(rewrite_anchor); rewrite_anchor(); }); + + $('#test_email_settings a.test_button').click(function() { + $('div.test_status').hide('slow') + $('div.ajax_indicator').show('fast') + $.post($(this).attr('href'), function(data) { + $('div.ajax_indicator').hide('fast') + $('div.test_status').html(data) + $('div.test_status').show('slow') + }) + }) }); /* * Autocomplete - jQuery plugin 1.0.3 * - * Copyright (c) 2007 Dylan Verheul, Dan G. Switzer, Anjesh Tuladhar, Jörn Zaefferer + * Copyright (c) 2007 Dylan Verheul, Dan G. Switzer, Anjesh Tuladhar, J�rn Zaefferer * * Dual licensed under the MIT and GPL licenses: * http://www.opensource.org/licenses/mit-license.php diff --git a/forum/skins/default/media/style/djstyle_admin.css b/forum/skins/default/media/style/djstyle_admin.css index abc479b..0ccd4ab 100644 --- a/forum/skins/default/media/style/djstyle_admin.css +++ b/forum/skins/default/media/style/djstyle_admin.css @@ -54,4 +54,10 @@ input.longstring { background-color: #ffffe0; border: 3px double #b8860b; padding: 4px; +} + +.ajax_indicator { + background: transparent url('../images/indicator.gif') top left no-repeat; + padding: 7px 25px; + min-height: 24px; } \ No newline at end of file diff --git a/forum/skins/default/templates/node/reviser_info.html b/forum/skins/default/templates/node/reviser_info.html index 8b46047..ac3df28 100644 --- a/forum/skins/default/templates/node/reviser_info.html +++ b/forum/skins/default/templates/node/reviser_info.html @@ -3,7 +3,7 @@

{% diff_date revision.revised_at %}

- {% gravatar revision.author 32 %} -

{{ revision.author.username }}
+ {% gravatar revision.author 32 %} +

{{ revision.author.username }}
{% get_score_badge revision.author %}

\ No newline at end of file diff --git a/forum/skins/default/templates/osqaadmin/mail_test.html b/forum/skins/default/templates/osqaadmin/mail_test.html new file mode 100644 index 0000000..41bd944 --- /dev/null +++ b/forum/skins/default/templates/osqaadmin/mail_test.html @@ -0,0 +1,22 @@ +{% load i18n extra_tags email_tags %} + +{% declare %} + prefix = settings.EMAIL_SUBJECT_PREFIX + app_name = settings.APP_SHORT_NAME + + exclude_finetune = True +{% enddeclare %} + +{% email %} + {% subject %}{% blocktrans %}{{ prefix }} Your email settings are correct: {{ app_name }}{% endblocktrans %}{% endsubject %} + + {% htmlcontent notifications/base.html %} + {% trans "If you see this content your E-Mail settings are correct." %} + {% endhtmlcontent %} + +{% textcontent notifications/base_text.html %} + {% trans "If you see this content your E-Mail settings are correct." %} +{% endtextcontent %} + +{% endemail %} + diff --git a/forum/skins/default/templates/osqaadmin/test_email_settings.html b/forum/skins/default/templates/osqaadmin/test_email_settings.html new file mode 100644 index 0000000..47a3ac5 --- /dev/null +++ b/forum/skins/default/templates/osqaadmin/test_email_settings.html @@ -0,0 +1,20 @@ +{% load i18n %} + +

+ {% blocktrans %} + An attempt has been made to send email to + {% endblocktrans %} {{ user.email }}. +

+ +

+ {% blocktrans %} + Please, check your inbox and if you see the new test message your email STMP settings are correct. + {% endblocktrans %} +

+ +

+ {% blocktrans %} + If you do not see the new test message check your spam folder, and if you don't find it check your SMTP settings + again. It might be useful to take a look at the log file. + {% endblocktrans %} +

\ No newline at end of file diff --git a/forum/urls.py b/forum/urls.py index 1771e2c..2817521 100644 --- a/forum/urls.py +++ b/forum/urls.py @@ -210,6 +210,9 @@ urlpatterns += patterns('', url(r'^%s%s(?P\w+)/$' % (_('admin/'), _('settings/')), app.admin.settings_set, name="admin_set"), + url(r'%s%s' % (_('admin/'), _('test_email_settings/')), app.admin.test_email_settings, + name="test_email_settings"), + url(r'^feeds/rss[/]?$', app.readers.feed, name="latest_questions_feed"), url(r'^(?P.+)$', app.meta.page, name="static_page"), diff --git a/forum/views/admin.py b/forum/views/admin.py index 40a098a..4b07915 100644 --- a/forum/views/admin.py +++ b/forum/views/admin.py @@ -13,6 +13,7 @@ from forum.settings.base import Setting from forum.forms import MaintenanceModeForm, PageForm, CreateUserForm from forum.settings.forms import SettingsSetForm from forum.utils import pagination, html +from forum.utils.mail import send_template_email from forum.models import Question, Answer, User, Node, Action, Page, NodeState, Tag from forum.models.node import NodeMetaClass @@ -548,7 +549,14 @@ def node_management(request): 'hide_menu': True })) +@super_user_required +def test_email_settings(request): + user = request.user + send_template_email([user,], 'osqaadmin/mail_test.html', { 'user' : user }) - - + return render_to_response( + 'osqaadmin/test_email_settings.html', + { 'user': user, }, + RequestContext(request) + ) \ No newline at end of file diff --git a/forum/views/auth.py b/forum/views/auth.py index 3281fe4..f8eb897 100644 --- a/forum/views/auth.py +++ b/forum/views/auth.py @@ -27,7 +27,10 @@ from forum.authentication.base import InvalidAuthentication from forum.authentication import AUTH_PROVIDERS from forum.models import AuthKeyUserAssociation, ValidationHash, Question, Answer -from forum.actions import UserJoinsAction +from forum.actions import UserJoinsAction, EmailValidationAction +from forum.models.action import ActionRepute + +from forum.settings import REP_GAIN_BY_EMAIL_VALIDATION def signin_page(request): referer = request.META.get('HTTP_REFERER', '/') @@ -299,9 +302,14 @@ def validate_email(request, user, code): user = get_object_or_404(User, id=user) if (ValidationHash.objects.validate(code, user, 'email', [user.email])): - user.email_isvalid = True - user.save() - return login_and_forward(request, user, reverse('index'), _("Thank you, your email is now validated.")) + EmailValidationAction(user=user, ip=request.META['REMOTE_ADDR']).save() + if REP_GAIN_BY_EMAIL_VALIDATION > 0: + message = _("Thank you, your email is now validated and you've got %d points." % int(REP_GAIN_BY_EMAIL_VALIDATION)) + + else: + message = _("Thank you, your email is now validated.") + + return login_and_forward(request, user, reverse('index'), message) else: return render_to_response('auth/mail_already_validated.html', { 'user' : user }, RequestContext(request)) diff --git a/forum/views/readers.py b/forum/views/readers.py index 80709e7..9a6f66e 100644 --- a/forum/views/readers.py +++ b/forum/views/readers.py @@ -6,6 +6,7 @@ from forum import settings as django_settings from django.shortcuts import render_to_response, get_object_or_404 from django.http import HttpResponseRedirect, HttpResponse, Http404, HttpResponsePermanentRedirect from django.core.paginator import Paginator, EmptyPage, InvalidPage +from django.core.exceptions import ObjectDoesNotExist from django.template import RequestContext from django import template from django.utils.html import * @@ -101,8 +102,13 @@ def questions(request): @decorators.render('questions.html') def tag(request, tag): + questions = Question.objects.filter(tags__name=unquote(tag)) + + if not questions: + raise Http404 + return question_list(request, - Question.objects.filter(tags__name=unquote(tag)), + questions, mark_safe(_('questions tagged %(tag)s') % {'tag': tag}), None, mark_safe(_('Questions Tagged With %(tag)s') % {'tag': tag}), diff --git a/forum_modules/sximporter/importer.py b/forum_modules/sximporter/importer.py index 44f90d7..0f7f812 100644 --- a/forum_modules/sximporter/importer.py +++ b/forum_modules/sximporter/importer.py @@ -432,6 +432,7 @@ def postimport(dump, uidmap, tagmap): post.save() all.append(int(post.id)) + create_and_activate_revision(post) del post @@ -480,6 +481,8 @@ def comment_import(dump, uidmap, posts): action_date = oc.added_at ) + create_and_activate_revision(oc) + create_action.save() oc.save() @@ -494,7 +497,6 @@ def add_tags_to_post(post, tagmap): tags = [tag for tag in [tagmap.get(name.strip()) for name in post.tagnames.split(u' ') if name] if tag] post.tagnames = " ".join([t.name for t in tags]).strip() post.tags = tags - create_and_activate_revision(post) def create_and_activate_revision(post): @@ -773,6 +775,8 @@ def pages_import(dump, currid): author_id = 1 ) + create_and_activate_revision(page) + page.save() registry[sxp['url'][1:]] = page.id diff --git a/settings.py b/settings.py index bd76b22..6e7c106 100644 --- a/settings.py +++ b/settings.py @@ -28,6 +28,7 @@ MIDDLEWARE_CLASSES = [ 'forum.middleware.anon_user.ConnectToSessionMessagesMiddleware', 'forum.middleware.request_utils.RequestUtils', 'forum.middleware.cancel.CancelActionMiddleware', + 'forum.middleware.admin_messages.AdminMessagesMiddleware', #'recaptcha_django.middleware.ReCaptchaMiddleware', 'django.middleware.transaction.TransactionMiddleware', ]