diff options
author | Eugene Kim <p.compassion@gmail.com> | 2013-05-22 19:38:14 +0900 |
---|---|---|
committer | Eugene Kim <p.compassion@gmail.com> | 2013-05-22 20:49:07 +0900 |
commit | 5776e61d76aa44801a4dc451b41c3a01e23aa8a4 (patch) | |
tree | dd02204c6a000dd4564fe64db87a98a31d7a93b1 | |
parent | ecda5082e93c9512fe8edabe0411c00d1dd4a7d4 (diff) | |
download | askbot-5776e61d76aa44801a4dc451b41c3a01e23aa8a4.tar.gz askbot-5776e61d76aa44801a4dc451b41c3a01e23aa8a4.tar.bz2 askbot-5776e61d76aa44801a4dc451b41c3a01e23aa8a4.zip |
tag synonyms
model, management command, and test code
-rw-r--r-- | askbot/forms.py | 10 | ||||
-rw-r--r-- | askbot/management/commands/create_tag_synonyms.py | 143 | ||||
-rw-r--r-- | askbot/management/commands/rename_tags_id.py | 16 | ||||
-rw-r--r-- | askbot/migrations/0169_auto__add_tagsynonym.py | 413 | ||||
-rw-r--r-- | askbot/models/__init__.py | 3 | ||||
-rw-r--r-- | askbot/models/question.py | 17 | ||||
-rw-r--r-- | askbot/models/tag.py | 17 | ||||
-rw-r--r-- | askbot/tests/management_command_tests.py | 78 |
8 files changed, 681 insertions, 16 deletions
diff --git a/askbot/forms.py b/askbot/forms.py index 04efb1f3..fcedda18 100644 --- a/askbot/forms.py +++ b/askbot/forms.py @@ -380,15 +380,13 @@ def clean_tag(tag_name): ) if askbot_settings.FORCE_LOWERCASE_TAGS: + tag_name = tag_name.lower() + + if askbot_settings.FORCE_LOWERCASE_TAGS: #a simpler way to handle tags - just lowercase thew all return tag_name.lower() else: - try: - from askbot import models - stored_tag = models.Tag.objects.get(name__iexact=tag_name) - return stored_tag.name - except models.Tag.DoesNotExist: - return tag_name + return tag_name class TagNamesField(forms.CharField): diff --git a/askbot/management/commands/create_tag_synonyms.py b/askbot/management/commands/create_tag_synonyms.py new file mode 100644 index 00000000..ccbb7e0a --- /dev/null +++ b/askbot/management/commands/create_tag_synonyms.py @@ -0,0 +1,143 @@ +"""management command that creates a tag synonym +all corresponding questions are retagged +""" + +import sys +from optparse import make_option +from django.core import management +from django.core.management.base import BaseCommand, CommandError +from askbot import models +from askbot.management.commands.rename_tags import get_admin +from askbot.utils import console +import datetime + + + +def decode_input(input): + decoded_input = input.decode(sys.stdin.encoding) + decoded_input = decoded_input.strip() + return decoded_input + + +class Command(BaseCommand): + + help = """create TagSynonym, +retags questions from source_tag_name to target_tag_name, +remove source_tag""" + + option_list = BaseCommand.option_list + ( + make_option('--from', + action = 'store', + type = 'str', + dest = 'from', + default = None, + help = 'a source tag name which needs to be replaced' + ), + make_option('--to', + action = 'store', + type = 'str', + dest = 'to', + default = None, + help = 'a target tag name that are to be used instead' + ), + make_option('--user-id', + action = 'store', + type = 'int', + dest = 'user_id', + default = None, + help = 'id of the user who will be marked as a performer of this operation' + ), + ) + + def handle(self, *args, **options): + """command handle function. reads tag names, decodes + them using the standard input encoding and attempts to find + the matching tags + + If "from" tag is not resolved, command fails + if "to" tag is not resolved, a new tag is created + """ + + if options['from'] is None: + raise CommandError('the --from argument is required') + if options['to'] is None: + raise CommandError('the --to argument is required') + + source_tag_name = decode_input(options['from']) + target_tag_name = decode_input(options['to']) + + if source_tag_name == target_tag_name: + raise CommandError("source and target tags appear to be the same") + + admin = get_admin(seed_user_id = options['user_id']) + + source_tag = None + is_source_tag_created = False + + try: + source_tag = models.Tag.objects.get(name=source_tag_name) + except models.Tag.DoesNotExist: + if not options.get('is_force', False): + prompt = """source tag %s doesn't exist, are you sure you want to create a TagSynonym + %s ==> %s?""" % (source_tag_name, source_tag_name, target_tag_name) + choice = console.choice_dialog(prompt, choices=('yes', 'no')) + if choice == 'no': + print 'Cancled' + sys.exit() + source_tag = models.Tag.objects.create(name=source_tag_name, + created_by=admin + ) + is_source_tag_created = True + + + # test if target_tag is actually synonym for yet another tag + # when user asked tag2->tag3, we already had tag3->tag4. + try: + tag_synonym_tmp = models.TagSynonym.objects.get(source_tag_name = target_tag_name) + if not options.get('is_force', False): + prompt = """There exists a TagSynonym %s ==> %s, + hence we will create a tag synonym %s ==> %s instead. Proceed?""" % (tag_synonym_tmp.source_tag_name, tag_synonym_tmp.target_tag_name, + source_tag_name, tag_synonym_tmp.target_tag_name) + choice = console.choice_dialog(prompt, choices=('yes', 'no')) + if choice == 'no': + print 'Cancled' + sys.exit() + target_tag_name = tag_synonym_tmp.target_tag_name + options['to'] = target_tag_name + except models.TagSynonym.DoesNotExist: + pass + + try: + models.Tag.objects.get(name=target_tag_name) + except models.Tag.DoesNotExist: + models.Tag.objects.create(name=target_tag_name, + created_by = admin + ) + + tag_synonym_tmp, created = models.TagSynonym.objects.get_or_create(source_tag_name = source_tag_name, + target_tag_name = target_tag_name, + owned_by = admin + ) + + management.call_command('rename_tags', *args, **options) + + # When source_tag_name is a target_tag_name of already existing TagSynonym. + # ie. if tag1->tag2 exists when user asked tag2->tag3 + # we are going to convert all tag1->tag2 to tag1->tag3 as well + existing_tag_synonyms = models.TagSynonym.objects.filter(target_tag_name=source_tag_name) + for existing_tag_synonym in existing_tag_synonyms: + new_options = options.copy() + new_options['from'] = existing_tag_synonym.source_tag_name + new_options['user_id'] = admin.id + new_options['is_force'] = True # this is mandatory conversion + new_options['timestamp'] = datetime.datetime.now() + existing_tag_synonym.delete() # no longer needed + self.handle(*args, **new_options) + + # delete source Tag + if is_source_tag_created: + source_tag.delete() + else: + source_tag.deleted = True + source_tag.deleted_at = options.get('timestamp', datetime.datetime.now()) + source_tag.deleted_by = admin diff --git a/askbot/management/commands/rename_tags_id.py b/askbot/management/commands/rename_tags_id.py index f6fe05ae..c584ba3a 100644 --- a/askbot/management/commands/rename_tags_id.py +++ b/askbot/management/commands/rename_tags_id.py @@ -126,14 +126,16 @@ or repost a bug, if that does not help""" from_tag_names = format_tag_name_list(from_tags) to_tag_names = format_tag_name_list(to_tags) - prompt = 'Rename tags %s --> %s?' % (from_tag_names, to_tag_names) - choice = console.choice_dialog(prompt, choices=('yes', 'no')) - if choice == 'no': - print 'Canceled' - sys.exit() + if not options.get('is_force', False): + prompt = 'Rename tags %s --> %s?' % (from_tag_names, to_tag_names) + choice = console.choice_dialog(prompt, choices=('yes', 'no')) + if choice == 'no': + print 'Canceled' + sys.exit() else: - sys.stdout.write('Processing:') - + print 'Renaming tags %s --> %s' % (from_tag_names, to_tag_names) + sys.stdout.write('Processing:') + #actual processing stage, only after this point we start to #modify stuff in the database, one question per transaction from_tag_names = get_tag_names(from_tags) diff --git a/askbot/migrations/0169_auto__add_tagsynonym.py b/askbot/migrations/0169_auto__add_tagsynonym.py new file mode 100644 index 00000000..bd217056 --- /dev/null +++ b/askbot/migrations/0169_auto__add_tagsynonym.py @@ -0,0 +1,413 @@ +# -*- coding: 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 model 'TagSynonym' + db.create_table('askbot_tagsynonym', ( + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('source_tag_name', self.gf('django.db.models.fields.CharField')(unique=True, max_length=255)), + ('target_tag_name', self.gf('django.db.models.fields.CharField')(max_length=255)), + ('created_at', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True)), + ('owned_by', self.gf('django.db.models.fields.related.ForeignKey')(related_name='tag_synonyms', to=orm['auth.User'])), + ('auto_rename_count', self.gf('django.db.models.fields.IntegerField')(default=0)), + ('last_auto_rename_at', self.gf('django.db.models.fields.DateTimeField')(auto_now=True, blank=True)), + )) + db.send_create_signal('askbot', ['TagSynonym']) + + + def backwards(self, orm): + # Deleting model 'TagSynonym' + db.delete_table('askbot_tagsynonym') + + + models = { + 'askbot.activity': { + 'Meta': {'object_name': 'Activity', 'db_table': "u'activity'"}, + 'active_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'activity_type': ('django.db.models.fields.SmallIntegerField', [], {}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_auditted': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}), + 'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['askbot.Post']", 'null': 'True'}), + 'receiving_users': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'received_activity'", 'symmetrical': 'False', 'to': "orm['auth.User']"}), + 'recipients': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'incoming_activity'", 'symmetrical': 'False', 'through': "orm['askbot.ActivityAuditStatus']", 'to': "orm['auth.User']"}), + 'summary': ('django.db.models.fields.TextField', [], {'default': "''"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) + }, + 'askbot.activityauditstatus': { + 'Meta': {'unique_together': "(('user', 'activity'),)", 'object_name': 'ActivityAuditStatus'}, + 'activity': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['askbot.Activity']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'status': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) + }, + 'askbot.anonymousanswer': { + 'Meta': {'object_name': 'AnonymousAnswer'}, + 'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'author': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'ip_addr': ('django.db.models.fields.IPAddressField', [], {'max_length': '15'}), + 'question': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'anonymous_answers'", 'to': "orm['askbot.Post']"}), + 'session_key': ('django.db.models.fields.CharField', [], {'max_length': '40'}), + 'text': ('django.db.models.fields.TextField', [], {}), + 'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False'}) + }, + 'askbot.anonymousquestion': { + 'Meta': {'object_name': 'AnonymousQuestion'}, + 'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'author': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'ip_addr': ('django.db.models.fields.IPAddressField', [], {'max_length': '15'}), + 'is_anonymous': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'session_key': ('django.db.models.fields.CharField', [], {'max_length': '40'}), + 'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}), + 'text': ('django.db.models.fields.TextField', [], {}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}), + 'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False'}) + }, + 'askbot.askwidget': { + 'Meta': {'object_name': 'AskWidget'}, + 'group': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['askbot.Group']", 'null': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'include_text_field': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'inner_style': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'outer_style': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'tag': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['askbot.Tag']", 'null': 'True', 'blank': 'True'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + 'askbot.award': { + 'Meta': {'object_name': 'Award', 'db_table': "u'award'"}, + 'awarded_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'badge': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'award_badge'", 'to': "orm['askbot.BadgeData']"}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'notified': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'award_user'", 'to': "orm['auth.User']"}) + }, + 'askbot.badgedata': { + 'Meta': {'ordering': "('slug',)", 'object_name': 'BadgeData'}, + 'awarded_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'awarded_to': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'badges'", 'symmetrical': 'False', 'through': "orm['askbot.Award']", 'to': "orm['auth.User']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '50'}) + }, + 'askbot.bulktagsubscription': { + 'Meta': {'ordering': "['-date_added']", 'object_name': 'BulkTagSubscription'}, + 'date_added': ('django.db.models.fields.DateField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['askbot.Group']", 'symmetrical': 'False'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'tags': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['askbot.Tag']", 'symmetrical': 'False'}), + 'users': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.User']", 'symmetrical': 'False'}) + }, + 'askbot.draftanswer': { + 'Meta': {'object_name': 'DraftAnswer'}, + 'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'draft_answers'", 'to': "orm['auth.User']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'text': ('django.db.models.fields.TextField', [], {'null': 'True'}), + 'thread': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'draft_answers'", 'to': "orm['askbot.Thread']"}) + }, + 'askbot.draftquestion': { + 'Meta': {'object_name': 'DraftQuestion'}, + 'author': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125', 'null': 'True'}), + 'text': ('django.db.models.fields.TextField', [], {'null': 'True'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '300', 'null': 'True'}) + }, + 'askbot.emailfeedsetting': { + 'Meta': {'unique_together': "(('subscriber', 'feed_type'),)", 'object_name': 'EmailFeedSetting'}, + 'added_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'feed_type': ('django.db.models.fields.CharField', [], {'max_length': '16'}), + 'frequency': ('django.db.models.fields.CharField', [], {'default': "'n'", 'max_length': '8'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'reported_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}), + 'subscriber': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'notification_subscriptions'", 'to': "orm['auth.User']"}) + }, + 'askbot.favoritequestion': { + 'Meta': {'object_name': 'FavoriteQuestion', 'db_table': "u'favorite_question'"}, + 'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'thread': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['askbot.Thread']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_favorite_questions'", 'to': "orm['auth.User']"}) + }, + 'askbot.group': { + 'Meta': {'object_name': 'Group', '_ormbases': ['auth.Group']}, + 'description': ('django.db.models.fields.related.OneToOneField', [], {'blank': 'True', 'related_name': "'described_group'", 'unique': 'True', 'null': 'True', 'to': "orm['askbot.Post']"}), + 'group_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.Group']", 'unique': 'True', 'primary_key': 'True'}), + 'is_vip': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'logo_url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'null': 'True'}), + 'moderate_answers_to_enquirers': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'moderate_email': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'openness': ('django.db.models.fields.SmallIntegerField', [], {'default': '2'}), + 'preapproved_email_domains': ('django.db.models.fields.TextField', [], {'default': "''", 'null': 'True', 'blank': 'True'}), + 'preapproved_emails': ('django.db.models.fields.TextField', [], {'default': "''", 'null': 'True', 'blank': 'True'}) + }, + 'askbot.groupmembership': { + 'Meta': {'object_name': 'GroupMembership', '_ormbases': ['auth.AuthUserGroups']}, + 'authusergroups_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.AuthUserGroups']", 'unique': 'True', 'primary_key': 'True'}), + 'level': ('django.db.models.fields.SmallIntegerField', [], {'default': '1'}) + }, + 'askbot.markedtag': { + 'Meta': {'object_name': 'MarkedTag'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'reason': ('django.db.models.fields.CharField', [], {'max_length': '16'}), + 'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'user_selections'", 'to': "orm['askbot.Tag']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tag_selections'", 'to': "orm['auth.User']"}) + }, + 'askbot.post': { + 'Meta': {'object_name': 'Post'}, + 'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'approved': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'db_index': 'True'}), + 'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'posts'", 'to': "orm['auth.User']"}), + 'comment_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'db_index': 'True'}), + 'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_posts'", 'null': 'True', 'to': "orm['auth.User']"}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'group_posts'", 'symmetrical': 'False', 'through': "orm['askbot.PostToGroup']", 'to': "orm['askbot.Group']"}), + 'html': ('django.db.models.fields.TextField', [], {'null': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_anonymous': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'language_code': ('django.db.models.fields.CharField', [], {'default': "'en'", 'max_length': '16'}), + 'last_edited_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'last_edited_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'last_edited_posts'", 'null': 'True', 'to': "orm['auth.User']"}), + 'locked': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'locked_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'locked_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'locked_posts'", 'null': 'True', 'to': "orm['auth.User']"}), + 'offensive_flag_count': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}), + 'old_answer_id': ('django.db.models.fields.PositiveIntegerField', [], {'default': 'None', 'unique': 'True', 'null': 'True', 'blank': 'True'}), + 'old_comment_id': ('django.db.models.fields.PositiveIntegerField', [], {'default': 'None', 'unique': 'True', 'null': 'True', 'blank': 'True'}), + 'old_question_id': ('django.db.models.fields.PositiveIntegerField', [], {'default': 'None', 'unique': 'True', 'null': 'True', 'blank': 'True'}), + 'parent': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'comments'", 'null': 'True', 'to': "orm['askbot.Post']"}), + 'points': ('django.db.models.fields.IntegerField', [], {'default': '0', 'db_column': "'score'"}), + 'post_type': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'summary': ('django.db.models.fields.TextField', [], {'null': 'True'}), + 'text': ('django.db.models.fields.TextField', [], {'null': 'True'}), + 'thread': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'posts'", 'null': 'True', 'blank': 'True', 'to': "orm['askbot.Thread']"}), + 'vote_down_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'vote_up_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'wiki': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'wikified_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}) + }, + 'askbot.postflagreason': { + 'Meta': {'object_name': 'PostFlagReason'}, + 'added_at': ('django.db.models.fields.DateTimeField', [], {}), + 'author': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}), + 'details': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'post_reject_reasons'", 'to': "orm['askbot.Post']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '128'}) + }, + 'askbot.postrevision': { + 'Meta': {'ordering': "('-revision',)", 'unique_together': "(('post', 'revision'),)", 'object_name': 'PostRevision'}, + 'approved': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'db_index': 'True'}), + 'approved_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'approved_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}), + 'author': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'postrevisions'", 'to': "orm['auth.User']"}), + 'by_email': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'email_address': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'null': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_anonymous': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'post': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'revisions'", 'null': 'True', 'to': "orm['askbot.Post']"}), + 'revised_at': ('django.db.models.fields.DateTimeField', [], {}), + 'revision': ('django.db.models.fields.PositiveIntegerField', [], {}), + 'summary': ('django.db.models.fields.CharField', [], {'max_length': '300', 'blank': 'True'}), + 'tagnames': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '125', 'blank': 'True'}), + 'text': ('django.db.models.fields.TextField', [], {}), + 'title': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '300', 'blank': 'True'}) + }, + 'askbot.posttogroup': { + 'Meta': {'unique_together': "(('post', 'group'),)", 'object_name': 'PostToGroup', 'db_table': "'askbot_post_groups'"}, + 'group': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['askbot.Group']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'post': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['askbot.Post']"}) + }, + 'askbot.questionview': { + 'Meta': {'object_name': 'QuestionView'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'question': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'viewed'", 'to': "orm['askbot.Post']"}), + 'when': ('django.db.models.fields.DateTimeField', [], {}), + 'who': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'question_views'", 'to': "orm['auth.User']"}) + }, + 'askbot.questionwidget': { + 'Meta': {'object_name': 'QuestionWidget'}, + 'group': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['askbot.Group']", 'null': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'order_by': ('django.db.models.fields.CharField', [], {'default': "'-added_at'", 'max_length': '18'}), + 'question_number': ('django.db.models.fields.PositiveIntegerField', [], {'default': '7'}), + 'search_query': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '50', 'null': 'True', 'blank': 'True'}), + 'style': ('django.db.models.fields.TextField', [], {'default': '"\\n@import url(\'http://fonts.googleapis.com/css?family=Yanone+Kaffeesatz:300,400,700\');\\nbody {\\n overflow: hidden;\\n}\\n\\n#container {\\n width: 200px;\\n height: 350px;\\n}\\nul {\\n list-style: none;\\n padding: 5px;\\n margin: 5px;\\n}\\nli {\\n border-bottom: #CCC 1px solid;\\n padding-bottom: 5px;\\n padding-top: 5px;\\n}\\nli:last-child {\\n border: none;\\n}\\na {\\n text-decoration: none;\\n color: #464646;\\n font-family: \'Yanone Kaffeesatz\', sans-serif;\\n font-size: 15px;\\n}\\n"', 'blank': 'True'}), + 'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '50'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + 'askbot.replyaddress': { + 'Meta': {'object_name': 'ReplyAddress'}, + 'address': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '25'}), + 'allowed_from_email': ('django.db.models.fields.EmailField', [], {'max_length': '150'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'post': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reply_addresses'", 'null': 'True', 'to': "orm['askbot.Post']"}), + 'reply_action': ('django.db.models.fields.CharField', [], {'default': "'auto_answer_or_comment'", 'max_length': '32'}), + 'response_post': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'edit_addresses'", 'null': 'True', 'to': "orm['askbot.Post']"}), + 'used_at': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) + }, + 'askbot.repute': { + 'Meta': {'object_name': 'Repute', 'db_table': "u'repute'"}, + 'comment': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'negative': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}), + 'positive': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}), + 'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['askbot.Post']", 'null': 'True', 'blank': 'True'}), + 'reputation': ('django.db.models.fields.IntegerField', [], {'default': '1'}), + 'reputation_type': ('django.db.models.fields.SmallIntegerField', [], {}), + 'reputed_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) + }, + 'askbot.tag': { + 'Meta': {'ordering': "('-used_count', 'name')", 'object_name': 'Tag', 'db_table': "u'tag'"}, + 'created_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'created_tags'", 'to': "orm['auth.User']"}), + 'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'deleted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'deleted_by': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'deleted_tags'", 'null': 'True', 'to': "orm['auth.User']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), + 'status': ('django.db.models.fields.SmallIntegerField', [], {'default': '1'}), + 'suggested_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'suggested_tags'", 'symmetrical': 'False', 'to': "orm['auth.User']"}), + 'tag_wiki': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'described_tag'", 'unique': 'True', 'null': 'True', 'to': "orm['askbot.Post']"}), + 'used_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}) + }, + 'askbot.tagsynonym': { + 'Meta': {'object_name': 'TagSynonym'}, + 'auto_rename_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'last_auto_rename_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), + 'owned_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tag_synonyms'", 'to': "orm['auth.User']"}), + 'source_tag_name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), + 'target_tag_name': ('django.db.models.fields.CharField', [], {'max_length': '255'}) + }, + 'askbot.thread': { + 'Meta': {'object_name': 'Thread'}, + 'accepted_answer': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'+'", 'null': 'True', 'to': "orm['askbot.Post']"}), + 'added_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'answer_accepted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'answer_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'approved': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'db_index': 'True'}), + 'close_reason': ('django.db.models.fields.SmallIntegerField', [], {'null': 'True', 'blank': 'True'}), + 'closed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'closed_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'closed_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}), + 'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'db_index': 'True'}), + 'favorited_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'unused_favorite_threads'", 'symmetrical': 'False', 'through': "orm['askbot.FavoriteQuestion']", 'to': "orm['auth.User']"}), + 'favourite_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'followed_by': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'followed_threads'", 'symmetrical': 'False', 'to': "orm['auth.User']"}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'group_threads'", 'symmetrical': 'False', 'through': "orm['askbot.ThreadToGroup']", 'to': "orm['askbot.Group']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'language_code': ('django.db.models.fields.CharField', [], {'default': "'en'", 'max_length': '16'}), + 'last_activity_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'last_activity_by': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'unused_last_active_in_threads'", 'to': "orm['auth.User']"}), + 'points': ('django.db.models.fields.IntegerField', [], {'default': '0', 'db_column': "'score'"}), + 'tagnames': ('django.db.models.fields.CharField', [], {'max_length': '125'}), + 'tags': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'threads'", 'symmetrical': 'False', 'to': "orm['askbot.Tag']"}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '300'}), + 'view_count': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}) + }, + 'askbot.threadtogroup': { + 'Meta': {'unique_together': "(('thread', 'group'),)", 'object_name': 'ThreadToGroup', 'db_table': "'askbot_thread_groups'"}, + 'group': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['askbot.Group']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'thread': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['askbot.Thread']"}), + 'visibility': ('django.db.models.fields.SmallIntegerField', [], {'default': '1'}) + }, + 'askbot.vote': { + 'Meta': {'unique_together': "(('user', 'voted_post'),)", 'object_name': 'Vote', 'db_table': "u'vote'"}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'votes'", 'to': "orm['auth.User']"}), + 'vote': ('django.db.models.fields.SmallIntegerField', [], {}), + 'voted_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'voted_post': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'votes'", 'to': "orm['askbot.Post']"}) + }, + 'auth.authusergroups': { + 'Meta': {'unique_together': "(('group', 'user'),)", 'object_name': 'AuthUserGroups', 'db_table': "'auth_user_groups'", 'managed': 'False'}, + 'group': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.Group']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) + }, + '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']", 'symmetrical': 'False', 'blank': 'True'}) + }, + 'auth.permission': { + 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', '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'}, + 'about': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'avatar_type': ('django.db.models.fields.CharField', [], {'default': "'n'", 'max_length': '1'}), + 'bronze': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}), + 'consecutive_days_visit_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'country': ('django_countries.fields.CountryField', [], {'max_length': '2', 'blank': 'True'}), + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'date_of_birth': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}), + 'display_tag_filter_strategy': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), + 'email_isvalid': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'email_key': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}), + 'email_signature': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'email_tag_filter_strategy': ('django.db.models.fields.SmallIntegerField', [], {'default': '1'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'gold': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}), + 'gravatar': ('django.db.models.fields.CharField', [], {'max_length': '32'}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'ignored_tags': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'interesting_tags': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'is_fake': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'languages': ('django.db.models.fields.CharField', [], {'default': "'en'", 'max_length': '128'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'last_seen': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'location': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}), + 'new_response_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'questions_per_page': ('django.db.models.fields.SmallIntegerField', [], {'default': '10'}), + 'real_name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}), + 'reputation': ('django.db.models.fields.PositiveIntegerField', [], {'default': '1'}), + 'seen_response_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'show_country': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'show_marked_tags': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'silver': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}), + 'social_sharing_mode': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'status': ('django.db.models.fields.CharField', [], {'default': "'w'", 'max_length': '2'}), + 'subscribed_tags': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'twitter_access_token': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '256'}), + 'twitter_handle': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '32'}), + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), + 'website': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}) + }, + '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'}) + } + } + + complete_apps = ['askbot']
\ No newline at end of file diff --git a/askbot/models/__init__.py b/askbot/models/__init__.py index 325f06d6..8e3e3d01 100644 --- a/askbot/models/__init__.py +++ b/askbot/models/__init__.py @@ -42,7 +42,7 @@ from askbot.mail import messages from askbot.models.question import QuestionView, AnonymousQuestion from askbot.models.question import DraftQuestion from askbot.models.question import FavoriteQuestion -from askbot.models.tag import Tag, MarkedTag +from askbot.models.tag import Tag, MarkedTag, TagSynonym from askbot.models.tag import format_personal_group_name from askbot.models.user import EmailFeedSetting, ActivityAuditStatus, Activity from askbot.models.user import GroupMembership @@ -3767,6 +3767,7 @@ __all__ = [ 'Vote', 'PostFlagReason', 'MarkedTag', + 'TagSynonym', 'BadgeData', 'Award', diff --git a/askbot/models/question.py b/askbot/models/question.py index 3dd9fc6b..ecb7185a 100644 --- a/askbot/models/question.py +++ b/askbot/models/question.py @@ -19,7 +19,7 @@ import askbot from askbot.conf import settings as askbot_settings from askbot import mail from askbot.mail import messages -from askbot.models.tag import Tag +from askbot.models.tag import Tag, TagSynonym from askbot.models.tag import get_tags_by_names from askbot.models.tag import filter_accepted_tags, filter_suggested_tags from askbot.models.tag import separate_unused_tags @@ -1200,6 +1200,8 @@ class Thread(models.Model): Tag use counts are recalculated A signal tags updated is sent + TagSynonym is used to replace tag names + *IMPORTANT*: self._question_post() has to exist when update_tags() is called! """ @@ -1209,9 +1211,20 @@ class Thread(models.Model): previous_tags = list(self.tags.filter(status = Tag.STATUS_ACCEPTED)) ordered_updated_tagnames = [t for t in tagnames.strip().split(' ')] + updated_tagnames_tmp = set(ordered_updated_tagnames) + + #apply TagSynonym + updated_tagnames = set() + for tag_name in updated_tagnames_tmp: + try: + tag_synonym = TagSynonym.objects.get(source_tag_name=tag_name) + updated_tagnames.add(tag_synonym.target_tag_name) + tag_synonym.auto_rename_count += 1 + tag_synonym.save() + except TagSynonym.DoesNotExist: + updated_tagnames.add(tag_name) previous_tagnames = set([tag.name for tag in previous_tags]) - updated_tagnames = set(ordered_updated_tagnames) removed_tagnames = previous_tagnames - updated_tagnames #remove tags from the question's tags many2many relation diff --git a/askbot/models/tag.py b/askbot/models/tag.py index 455995e0..6de83412 100644 --- a/askbot/models/tag.py +++ b/askbot/models/tag.py @@ -318,3 +318,20 @@ class MarkedTag(models.Model): class Meta: app_label = 'askbot' + + +class TagSynonym(models.Model): + + source_tag_name = models.CharField(max_length=255, unique=True) + target_tag_name = models.CharField(max_length=255) + created_at = models.DateTimeField(auto_now_add=True) + owned_by = models.ForeignKey(User, related_name='tag_synonyms') + auto_rename_count = models.IntegerField(default=0) + last_auto_rename_at = models.DateTimeField(auto_now=True) + + class Meta: + app_label = 'askbot' + + def __unicode__(self): + return u'%s -> %s' % (self.source_tag_name, self.target_tag_name) + diff --git a/askbot/tests/management_command_tests.py b/askbot/tests/management_command_tests.py index e9341a8b..db45b405 100644 --- a/askbot/tests/management_command_tests.py +++ b/askbot/tests/management_command_tests.py @@ -2,6 +2,7 @@ from django.core import management from django.contrib import auth from askbot.tests.utils import AskbotTestCase from askbot import models +from django.contrib.auth.models import User class ManagementCommandTests(AskbotTestCase): def test_add_askbot_user(self): @@ -51,3 +52,80 @@ class ManagementCommandTests(AskbotTestCase): user_two = models.User.objects.get(pk=2) self.assertEqual(user_two.gold, number_of_gold) self.assertEqual(user_two.reputation, reputation) + + def test_create_tag_synonym(self): + + admin = User.objects.create_superuser('test_admin', 'admin@admin.com', 'admin_pass') + + options = { + 'from': 'tag1', # ok.. 'from' is a bad keyword argument name.. + 'to': 'tag2', + 'user_id': admin.id, + 'is_force': True + } + management.call_command( + 'create_tag_synonyms', + **options + ) + + options['from'] = 'tag3' + options['to'] = 'tag4' + management.call_command( + 'create_tag_synonyms', + **options + ) + + options['from']='tag5' + options['to']='tag4' + management.call_command( + 'create_tag_synonyms', + **options + ) + + options['from']='tag2' + options['to']='tag3' + management.call_command( + 'create_tag_synonyms', + **options + ) + + self.assertEqual(models.TagSynonym.objects.filter(source_tag_name = 'tag1', + target_tag_name = 'tag4' + ).count(), 1) + self.assertEqual(models.TagSynonym.objects.filter(source_tag_name = 'tag2', + target_tag_name = 'tag4' + ).count(), 1) + self.assertEqual(models.TagSynonym.objects.filter(source_tag_name = 'tag3', + target_tag_name = 'tag4' + ).count(), 1) + self.assertEqual(models.TagSynonym.objects.filter(source_tag_name = 'tag5', + target_tag_name = 'tag4' + ).count(), 1) + self.assertEqual(models.TagSynonym.objects.count(), 4) + + options['from']='tag4' + options['to']='tag6' + management.call_command( + 'create_tag_synonyms', + **options + ) + + self.assertEqual(models.TagSynonym.objects.filter(source_tag_name = 'tag1', + target_tag_name = 'tag6' + ).count(), 1) + self.assertEqual(models.TagSynonym.objects.filter(source_tag_name = 'tag2', + target_tag_name = 'tag6' + ).count(), 1) + self.assertEqual(models.TagSynonym.objects.filter(source_tag_name = 'tag3', + target_tag_name = 'tag6' + ).count(), 1) + self.assertEqual(models.TagSynonym.objects.filter(source_tag_name = 'tag4', + target_tag_name = 'tag6' + ).count(), 1) + self.assertEqual(models.TagSynonym.objects.filter(source_tag_name = 'tag5', + target_tag_name = 'tag6' + ).count(), 1) + self.assertEqual(models.TagSynonym.objects.count(), 5) + + print 'done create_tag_synonym_test' + |