diff --git a/common/lib/xmodule/xmodule/course_module.py b/common/lib/xmodule/xmodule/course_module.py index 2473177b3a..8435cfca9e 100644 --- a/common/lib/xmodule/xmodule/course_module.py +++ b/common/lib/xmodule/xmodule/course_module.py @@ -29,6 +29,10 @@ class CourseDescriptor(SequenceDescriptor): @property def instructors(self): return self.get_about_section("instructors").split("\n") + + @property + def wiki_namespace(self): + return self.location.course def get_about_section(self, section_key): """ diff --git a/lms/djangoapps/courseware/courses.py b/lms/djangoapps/courseware/courses.py index 52be6a7cbd..858cdb1c87 100644 --- a/lms/djangoapps/courseware/courses.py +++ b/lms/djangoapps/courseware/courses.py @@ -14,6 +14,7 @@ _FIELDS = ['number', # 6.002x 'path', # /some/absolute/filepath/6.002x --> course.xml is in here. 'instructors', # ['Anant Agarwal'] 'institution', # "MIT" + 'wiki_namespace', 'grader', # a courseware.graders.CourseGrader object #'start', # These should be datetime fields diff --git a/lms/djangoapps/simplewiki/admin.py b/lms/djangoapps/simplewiki/admin.py index b53ace1a7a..8d1094bbc0 100644 --- a/lms/djangoapps/simplewiki/admin.py +++ b/lms/djangoapps/simplewiki/admin.py @@ -34,7 +34,7 @@ class ArticleAdminForm(forms.ModelForm): model = Article class ArticleAdmin(admin.ModelAdmin): - list_display = ('created_by', 'slug', 'modified_on', 'parent') + list_display = ('created_by', 'slug', 'modified_on', 'namespace') search_fields = ('slug',) prepopulated_fields = {'slug': ('title',) } inlines = [RevisionInline] diff --git a/lms/djangoapps/simplewiki/mdx_circuit.py b/lms/djangoapps/simplewiki/mdx_circuit.py index 1f47dd0568..bc58ad91ed 100755 --- a/lms/djangoapps/simplewiki/mdx_circuit.py +++ b/lms/djangoapps/simplewiki/mdx_circuit.py @@ -17,8 +17,6 @@ circuit-schematic:[["r",[128,48,0],{"r":"1","_json_":0},["2","1"]],["view",0,0,2 import markdown import re -import simplewiki.settings as settings - from django.utils.html import escape try: @@ -68,5 +66,7 @@ class CircuitLink(markdown.inlinepatterns.Pattern): return etree.fromstring("
") -def makeExtension(configs=None) : - return CircuitExtension(configs=configs) +def makeExtension(configs=None): + to_return = CircuitExtension(configs=configs) + print "circuit returning " , to_return + return to_return diff --git a/lms/djangoapps/simplewiki/mdx_wikipath.py b/lms/djangoapps/simplewiki/mdx_wikipath.py index 5072526247..d9381e4bee 100755 --- a/lms/djangoapps/simplewiki/mdx_wikipath.py +++ b/lms/djangoapps/simplewiki/mdx_wikipath.py @@ -33,7 +33,7 @@ class WikiPathExtension(markdown.Extension): def __init__(self, configs): # set extension defaults self.config = { - 'base_url' : ['/', 'String to append to beginning or URL.'], + 'default_namespace' : ['edX', 'Default namespace for when one isn\'t specified.'], 'html_class' : ['wikipath', 'CSS hook. Leave blank for none.'] } @@ -62,7 +62,10 @@ class WikiPath(markdown.inlinepatterns.Pattern): if article_title.startswith("/"): article_title = article_title[1:] - url = self.config['base_url'][0] + article_title + if not "/" in article_title: + article_title = self.config['default_namespace'][0] + "/" + article_title + + url = "../" + article_title label = m.group('linkTitle') a = etree.Element('a') a.set('href', url) diff --git a/lms/djangoapps/simplewiki/migrations/0001_initial.py b/lms/djangoapps/simplewiki/migrations/0001_initial.py new file mode 100644 index 0000000000..542c39248c --- /dev/null +++ b/lms/djangoapps/simplewiki/migrations/0001_initial.py @@ -0,0 +1,218 @@ +# -*- 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 'Article' + db.create_table('simplewiki_article', ( + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('title', self.gf('django.db.models.fields.CharField')(max_length=512)), + ('slug', self.gf('django.db.models.fields.SlugField')(max_length=100, blank=True)), + ('created_by', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'], null=True, blank=True)), + ('created_on', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=1, blank=True)), + ('modified_on', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=1, blank=True)), + ('parent', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['simplewiki.Article'], null=True, blank=True)), + ('locked', self.gf('django.db.models.fields.BooleanField')(default=False)), + ('permissions', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['simplewiki.Permission'], null=True, blank=True)), + ('current_revision', self.gf('django.db.models.fields.related.OneToOneField')(blank=True, related_name='current_rev', unique=True, null=True, to=orm['simplewiki.Revision'])), + )) + db.send_create_signal('simplewiki', ['Article']) + + # Adding unique constraint on 'Article', fields ['slug', 'parent'] + db.create_unique('simplewiki_article', ['slug', 'parent_id']) + + # Adding M2M table for field related on 'Article' + db.create_table('simplewiki_article_related', ( + ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), + ('from_article', models.ForeignKey(orm['simplewiki.article'], null=False)), + ('to_article', models.ForeignKey(orm['simplewiki.article'], null=False)) + )) + db.create_unique('simplewiki_article_related', ['from_article_id', 'to_article_id']) + + # Adding model 'ArticleAttachment' + db.create_table('simplewiki_articleattachment', ( + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('article', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['simplewiki.Article'])), + ('file', self.gf('django.db.models.fields.files.FileField')(max_length=255)), + ('uploaded_by', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'], null=True, blank=True)), + ('uploaded_on', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True)), + )) + db.send_create_signal('simplewiki', ['ArticleAttachment']) + + # Adding model 'Revision' + db.create_table('simplewiki_revision', ( + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('article', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['simplewiki.Article'])), + ('revision_text', self.gf('django.db.models.fields.CharField')(max_length=255, null=True, blank=True)), + ('revision_user', self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='wiki_revision_user', null=True, to=orm['auth.User'])), + ('revision_date', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True)), + ('contents', self.gf('django.db.models.fields.TextField')()), + ('contents_parsed', self.gf('django.db.models.fields.TextField')(null=True, blank=True)), + ('counter', self.gf('django.db.models.fields.IntegerField')(default=1)), + ('previous_revision', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['simplewiki.Revision'], null=True, blank=True)), + ('deleted', self.gf('django.db.models.fields.IntegerField')(default=0)), + )) + db.send_create_signal('simplewiki', ['Revision']) + + # Adding model 'Permission' + db.create_table('simplewiki_permission', ( + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('permission_name', self.gf('django.db.models.fields.CharField')(max_length=255)), + )) + db.send_create_signal('simplewiki', ['Permission']) + + # Adding M2M table for field can_write on 'Permission' + db.create_table('simplewiki_permission_can_write', ( + ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), + ('permission', models.ForeignKey(orm['simplewiki.permission'], null=False)), + ('user', models.ForeignKey(orm['auth.user'], null=False)) + )) + db.create_unique('simplewiki_permission_can_write', ['permission_id', 'user_id']) + + # Adding M2M table for field can_read on 'Permission' + db.create_table('simplewiki_permission_can_read', ( + ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), + ('permission', models.ForeignKey(orm['simplewiki.permission'], null=False)), + ('user', models.ForeignKey(orm['auth.user'], null=False)) + )) + db.create_unique('simplewiki_permission_can_read', ['permission_id', 'user_id']) + + + def backwards(self, orm): + # Removing unique constraint on 'Article', fields ['slug', 'parent'] + db.delete_unique('simplewiki_article', ['slug', 'parent_id']) + + # Deleting model 'Article' + db.delete_table('simplewiki_article') + + # Removing M2M table for field related on 'Article' + db.delete_table('simplewiki_article_related') + + # Deleting model 'ArticleAttachment' + db.delete_table('simplewiki_articleattachment') + + # Deleting model 'Revision' + db.delete_table('simplewiki_revision') + + # Deleting model 'Permission' + db.delete_table('simplewiki_permission') + + # Removing M2M table for field can_write on 'Permission' + db.delete_table('simplewiki_permission_can_write') + + # Removing M2M table for field can_read on 'Permission' + db.delete_table('simplewiki_permission_can_read') + + + 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']", '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_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_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'}), + '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'}), + 'silver': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}), + 'status': ('django.db.models.fields.CharField', [], {'default': "'w'", 'max_length': '2'}), + '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': '30'}), + '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'}) + }, + 'simplewiki.article': { + 'Meta': {'unique_together': "(('slug', 'parent'),)", 'object_name': 'Article'}, + 'created_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}), + 'created_on': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': '1', 'blank': 'True'}), + 'current_revision': ('django.db.models.fields.related.OneToOneField', [], {'blank': 'True', 'related_name': "'current_rev'", 'unique': 'True', 'null': 'True', 'to': "orm['simplewiki.Revision']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'locked': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'modified_on': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': '1', 'blank': 'True'}), + 'parent': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['simplewiki.Article']", 'null': 'True', 'blank': 'True'}), + 'permissions': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['simplewiki.Permission']", 'null': 'True', 'blank': 'True'}), + 'related': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'related_rel_+'", 'null': 'True', 'to': "orm['simplewiki.Article']"}), + 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '100', 'blank': 'True'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '512'}) + }, + 'simplewiki.articleattachment': { + 'Meta': {'object_name': 'ArticleAttachment'}, + 'article': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['simplewiki.Article']"}), + 'file': ('django.db.models.fields.files.FileField', [], {'max_length': '255'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'uploaded_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}), + 'uploaded_on': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}) + }, + 'simplewiki.permission': { + 'Meta': {'object_name': 'Permission'}, + 'can_read': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'read'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['auth.User']"}), + 'can_write': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'write'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['auth.User']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'permission_name': ('django.db.models.fields.CharField', [], {'max_length': '255'}) + }, + 'simplewiki.revision': { + 'Meta': {'object_name': 'Revision'}, + 'article': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['simplewiki.Article']"}), + 'contents': ('django.db.models.fields.TextField', [], {}), + 'contents_parsed': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'counter': ('django.db.models.fields.IntegerField', [], {'default': '1'}), + 'deleted': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'previous_revision': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['simplewiki.Revision']", 'null': 'True', 'blank': 'True'}), + 'revision_date': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'revision_text': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), + 'revision_user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'wiki_revision_user'", 'null': 'True', 'to': "orm['auth.User']"}) + } + } + + complete_apps = ['simplewiki'] \ No newline at end of file diff --git a/lms/djangoapps/simplewiki/migrations/0002_unique_slugs.py b/lms/djangoapps/simplewiki/migrations/0002_unique_slugs.py new file mode 100644 index 0000000000..f81d8d3431 --- /dev/null +++ b/lms/djangoapps/simplewiki/migrations/0002_unique_slugs.py @@ -0,0 +1,135 @@ +# -*- coding: utf-8 -*- +import datetime +from south.db import db +from south.v2 import DataMigration +from django.db import models + +class Migration(DataMigration): + + def forwards(self, orm): + # We collect every article slug in a set. Any time we see a duplicate, we change the duplicate's name + unique_slugs = set() + for article in orm.Article.objects.all(): + if article.slug in unique_slugs: + i = 2 + new_name = article.slug + str(i) + while new_name in unique_slugs: + i += 1 + new_name = article.slug + str(i) + print "Changing" , article.slug , "to" , new_name + article.slug = new_name + article.save() + + unique_slugs.add( article.slug ) + + 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']", '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_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_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'}), + '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'}), + 'silver': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}), + 'status': ('django.db.models.fields.CharField', [], {'default': "'w'", 'max_length': '2'}), + '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': '30'}), + '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'}) + }, + 'simplewiki.article': { + 'Meta': {'unique_together': "(('slug', 'parent'),)", 'object_name': 'Article'}, + 'created_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}), + 'created_on': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': '1', 'blank': 'True'}), + 'current_revision': ('django.db.models.fields.related.OneToOneField', [], {'blank': 'True', 'related_name': "'current_rev'", 'unique': 'True', 'null': 'True', 'to': "orm['simplewiki.Revision']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'locked': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'modified_on': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': '1', 'blank': 'True'}), + 'parent': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['simplewiki.Article']", 'null': 'True', 'blank': 'True'}), + 'permissions': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['simplewiki.Permission']", 'null': 'True', 'blank': 'True'}), + 'related': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'related_rel_+'", 'null': 'True', 'to': "orm['simplewiki.Article']"}), + 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '100', 'blank': 'True'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '512'}) + }, + 'simplewiki.articleattachment': { + 'Meta': {'object_name': 'ArticleAttachment'}, + 'article': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['simplewiki.Article']"}), + 'file': ('django.db.models.fields.files.FileField', [], {'max_length': '255'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'uploaded_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}), + 'uploaded_on': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}) + }, + 'simplewiki.permission': { + 'Meta': {'object_name': 'Permission'}, + 'can_read': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'read'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['auth.User']"}), + 'can_write': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'write'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['auth.User']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'permission_name': ('django.db.models.fields.CharField', [], {'max_length': '255'}) + }, + 'simplewiki.revision': { + 'Meta': {'object_name': 'Revision'}, + 'article': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['simplewiki.Article']"}), + 'contents': ('django.db.models.fields.TextField', [], {}), + 'contents_parsed': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'counter': ('django.db.models.fields.IntegerField', [], {'default': '1'}), + 'deleted': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'previous_revision': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['simplewiki.Revision']", 'null': 'True', 'blank': 'True'}), + 'revision_date': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'revision_text': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), + 'revision_user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'wiki_revision_user'", 'null': 'True', 'to': "orm['auth.User']"}) + } + } + + complete_apps = ['simplewiki'] + symmetrical = True diff --git a/lms/djangoapps/simplewiki/migrations/0003_auto__add_namespace__del_field_article_parent__add_field_article_names.py b/lms/djangoapps/simplewiki/migrations/0003_auto__add_namespace__del_field_article_parent__add_field_article_names.py new file mode 100644 index 0000000000..0ad2bb6cae --- /dev/null +++ b/lms/djangoapps/simplewiki/migrations/0003_auto__add_namespace__del_field_article_parent__add_field_article_names.py @@ -0,0 +1,163 @@ +# -*- 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): + # Removing unique constraint on 'Article', fields ['slug', 'parent'] + db.delete_unique('simplewiki_article', ['slug', 'parent_id']) + + # Adding model 'Namespace' + db.create_table('simplewiki_namespace', ( + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('name', self.gf('django.db.models.fields.CharField')(max_length=30)), + )) + db.send_create_signal('simplewiki', ['Namespace']) + + # Deleting field 'Article.parent' + db.delete_column('simplewiki_article', 'parent_id') + + # Adding field 'Article.namespace' + db.add_column('simplewiki_article', 'namespace', + self.gf('django.db.models.fields.related.ForeignKey')(default=1, to=orm['simplewiki.Namespace']), + keep_default=False) + + # Adding unique constraint on 'Article', fields ['namespace', 'slug'] + db.create_unique('simplewiki_article', ['namespace_id', 'slug']) + + + def backwards(self, orm): + # Removing unique constraint on 'Article', fields ['namespace', 'slug'] + db.delete_unique('simplewiki_article', ['namespace_id', 'slug']) + + # Deleting model 'Namespace' + db.delete_table('simplewiki_namespace') + + # Adding field 'Article.parent' + db.add_column('simplewiki_article', 'parent', + self.gf('django.db.models.fields.related.ForeignKey')(to=orm['simplewiki.Article'], null=True, blank=True), + keep_default=False) + + # Deleting field 'Article.namespace' + db.delete_column('simplewiki_article', 'namespace_id') + + # Adding unique constraint on 'Article', fields ['slug', 'parent'] + db.create_unique('simplewiki_article', ['slug', 'parent_id']) + + + 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']", '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_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_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'}), + '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'}), + 'silver': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}), + 'status': ('django.db.models.fields.CharField', [], {'default': "'w'", 'max_length': '2'}), + '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': '30'}), + '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'}) + }, + 'simplewiki.article': { + 'Meta': {'unique_together': "(('slug', 'namespace'),)", 'object_name': 'Article'}, + 'created_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}), + 'created_on': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': '1', 'blank': 'True'}), + 'current_revision': ('django.db.models.fields.related.OneToOneField', [], {'blank': 'True', 'related_name': "'current_rev'", 'unique': 'True', 'null': 'True', 'to': "orm['simplewiki.Revision']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'locked': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'modified_on': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': '1', 'blank': 'True'}), + 'namespace': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['simplewiki.Namespace']"}), + 'permissions': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['simplewiki.Permission']", 'null': 'True', 'blank': 'True'}), + 'related': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'related_rel_+'", 'null': 'True', 'to': "orm['simplewiki.Article']"}), + 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '100', 'blank': 'True'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '512'}) + }, + 'simplewiki.articleattachment': { + 'Meta': {'object_name': 'ArticleAttachment'}, + 'article': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['simplewiki.Article']"}), + 'file': ('django.db.models.fields.files.FileField', [], {'max_length': '255'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'uploaded_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}), + 'uploaded_on': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}) + }, + 'simplewiki.namespace': { + 'Meta': {'object_name': 'Namespace'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '30'}) + }, + 'simplewiki.permission': { + 'Meta': {'object_name': 'Permission'}, + 'can_read': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'read'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['auth.User']"}), + 'can_write': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'write'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['auth.User']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'permission_name': ('django.db.models.fields.CharField', [], {'max_length': '255'}) + }, + 'simplewiki.revision': { + 'Meta': {'object_name': 'Revision'}, + 'article': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['simplewiki.Article']"}), + 'contents': ('django.db.models.fields.TextField', [], {}), + 'contents_parsed': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'counter': ('django.db.models.fields.IntegerField', [], {'default': '1'}), + 'deleted': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'previous_revision': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['simplewiki.Revision']", 'null': 'True', 'blank': 'True'}), + 'revision_date': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'revision_text': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), + 'revision_user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'wiki_revision_user'", 'null': 'True', 'to': "orm['auth.User']"}) + } + } + + complete_apps = ['simplewiki'] \ No newline at end of file diff --git a/lms/djangoapps/simplewiki/migrations/0004_multicourse_data_migration.py b/lms/djangoapps/simplewiki/migrations/0004_multicourse_data_migration.py new file mode 100644 index 0000000000..5f61eb9d1d --- /dev/null +++ b/lms/djangoapps/simplewiki/migrations/0004_multicourse_data_migration.py @@ -0,0 +1,133 @@ +# -*- coding: utf-8 -*- +import datetime +from south.db import db +from south.v2 import DataMigration +from django.db import models + +class Migration(DataMigration): + + def forwards(self, orm): + namespace6002x, created = orm.Namespace.objects.get_or_create(name="6.002xS12") + if created: + namespace6002x.save() + + for article in orm.Article.objects.all(): + article.namespace = namespace6002x + article.save() + + def backwards(self, orm): + raise RuntimeError("Cannot reverse this migration.") + + 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']", '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_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_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'}), + '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'}), + 'silver': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}), + 'status': ('django.db.models.fields.CharField', [], {'default': "'w'", 'max_length': '2'}), + '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': '30'}), + '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'}) + }, + 'simplewiki.article': { + 'Meta': {'unique_together': "(('slug', 'namespace'),)", 'object_name': 'Article'}, + 'created_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}), + 'created_on': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': '1', 'blank': 'True'}), + 'current_revision': ('django.db.models.fields.related.OneToOneField', [], {'blank': 'True', 'related_name': "'current_rev'", 'unique': 'True', 'null': 'True', 'to': "orm['simplewiki.Revision']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'locked': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'modified_on': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': '1', 'blank': 'True'}), + 'namespace': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['simplewiki.Namespace']"}), + 'permissions': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['simplewiki.Permission']", 'null': 'True', 'blank': 'True'}), + 'related': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'related_rel_+'", 'null': 'True', 'to': "orm['simplewiki.Article']"}), + 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '100', 'blank': 'True'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '512'}) + }, + 'simplewiki.articleattachment': { + 'Meta': {'object_name': 'ArticleAttachment'}, + 'article': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['simplewiki.Article']"}), + 'file': ('django.db.models.fields.files.FileField', [], {'max_length': '255'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'uploaded_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}), + 'uploaded_on': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}) + }, + 'simplewiki.namespace': { + 'Meta': {'object_name': 'Namespace'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '30'}) + }, + 'simplewiki.permission': { + 'Meta': {'object_name': 'Permission'}, + 'can_read': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'read'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['auth.User']"}), + 'can_write': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'write'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['auth.User']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'permission_name': ('django.db.models.fields.CharField', [], {'max_length': '255'}) + }, + 'simplewiki.revision': { + 'Meta': {'object_name': 'Revision'}, + 'article': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['simplewiki.Article']"}), + 'contents': ('django.db.models.fields.TextField', [], {}), + 'contents_parsed': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'counter': ('django.db.models.fields.IntegerField', [], {'default': '1'}), + 'deleted': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'previous_revision': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['simplewiki.Revision']", 'null': 'True', 'blank': 'True'}), + 'revision_date': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'revision_text': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), + 'revision_user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'wiki_revision_user'", 'null': 'True', 'to': "orm['auth.User']"}) + } + } + + complete_apps = ['simplewiki'] + symmetrical = True diff --git a/lms/djangoapps/simplewiki/migrations/0005_auto__add_unique_namespace_name.py b/lms/djangoapps/simplewiki/migrations/0005_auto__add_unique_namespace_name.py new file mode 100644 index 0000000000..1ed6b11b67 --- /dev/null +++ b/lms/djangoapps/simplewiki/migrations/0005_auto__add_unique_namespace_name.py @@ -0,0 +1,131 @@ +# -*- 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 unique constraint on 'Namespace', fields ['name'] + db.create_unique('simplewiki_namespace', ['name']) + + + def backwards(self, orm): + # Removing unique constraint on 'Namespace', fields ['name'] + db.delete_unique('simplewiki_namespace', ['name']) + + + 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']", '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_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_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'}), + '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'}), + 'silver': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}), + 'status': ('django.db.models.fields.CharField', [], {'default': "'w'", 'max_length': '2'}), + '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': '30'}), + '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'}) + }, + 'simplewiki.article': { + 'Meta': {'unique_together': "(('slug', 'namespace'),)", 'object_name': 'Article'}, + 'created_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}), + 'created_on': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': '1', 'blank': 'True'}), + 'current_revision': ('django.db.models.fields.related.OneToOneField', [], {'blank': 'True', 'related_name': "'current_rev'", 'unique': 'True', 'null': 'True', 'to': "orm['simplewiki.Revision']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'locked': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'modified_on': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': '1', 'blank': 'True'}), + 'namespace': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['simplewiki.Namespace']"}), + 'permissions': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['simplewiki.Permission']", 'null': 'True', 'blank': 'True'}), + 'related': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'related_rel_+'", 'null': 'True', 'to': "orm['simplewiki.Article']"}), + 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '100', 'blank': 'True'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '512'}) + }, + 'simplewiki.articleattachment': { + 'Meta': {'object_name': 'ArticleAttachment'}, + 'article': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['simplewiki.Article']"}), + 'file': ('django.db.models.fields.files.FileField', [], {'max_length': '255'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'uploaded_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}), + 'uploaded_on': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}) + }, + 'simplewiki.namespace': { + 'Meta': {'object_name': 'Namespace'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) + }, + 'simplewiki.permission': { + 'Meta': {'object_name': 'Permission'}, + 'can_read': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'read'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['auth.User']"}), + 'can_write': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'write'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['auth.User']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'permission_name': ('django.db.models.fields.CharField', [], {'max_length': '255'}) + }, + 'simplewiki.revision': { + 'Meta': {'object_name': 'Revision'}, + 'article': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['simplewiki.Article']"}), + 'contents': ('django.db.models.fields.TextField', [], {}), + 'contents_parsed': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'counter': ('django.db.models.fields.IntegerField', [], {'default': '1'}), + 'deleted': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'previous_revision': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['simplewiki.Revision']", 'null': 'True', 'blank': 'True'}), + 'revision_date': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'revision_text': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), + 'revision_user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'wiki_revision_user'", 'null': 'True', 'to': "orm['auth.User']"}) + } + } + + complete_apps = ['simplewiki'] \ No newline at end of file diff --git a/lms/djangoapps/simplewiki/migrations/0006_auto.py b/lms/djangoapps/simplewiki/migrations/0006_auto.py new file mode 100644 index 0000000000..2f7c698f04 --- /dev/null +++ b/lms/djangoapps/simplewiki/migrations/0006_auto.py @@ -0,0 +1,131 @@ +# -*- 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 index on 'Namespace', fields ['name'] + db.create_index('simplewiki_namespace', ['name']) + + + def backwards(self, orm): + # Removing index on 'Namespace', fields ['name'] + db.delete_index('simplewiki_namespace', ['name']) + + + 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']", '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_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_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'}), + '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'}), + 'silver': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}), + 'status': ('django.db.models.fields.CharField', [], {'default': "'w'", 'max_length': '2'}), + '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': '30'}), + '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'}) + }, + 'simplewiki.article': { + 'Meta': {'unique_together': "(('slug', 'namespace'),)", 'object_name': 'Article'}, + 'created_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}), + 'created_on': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': '1', 'blank': 'True'}), + 'current_revision': ('django.db.models.fields.related.OneToOneField', [], {'blank': 'True', 'related_name': "'current_rev'", 'unique': 'True', 'null': 'True', 'to': "orm['simplewiki.Revision']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'locked': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'modified_on': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': '1', 'blank': 'True'}), + 'namespace': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['simplewiki.Namespace']"}), + 'permissions': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['simplewiki.Permission']", 'null': 'True', 'blank': 'True'}), + 'related': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'related_rel_+'", 'null': 'True', 'to': "orm['simplewiki.Article']"}), + 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '100', 'blank': 'True'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '512'}) + }, + 'simplewiki.articleattachment': { + 'Meta': {'object_name': 'ArticleAttachment'}, + 'article': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['simplewiki.Article']"}), + 'file': ('django.db.models.fields.files.FileField', [], {'max_length': '255'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'uploaded_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}), + 'uploaded_on': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}) + }, + 'simplewiki.namespace': { + 'Meta': {'object_name': 'Namespace'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30', 'db_index': 'True'}) + }, + 'simplewiki.permission': { + 'Meta': {'object_name': 'Permission'}, + 'can_read': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'read'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['auth.User']"}), + 'can_write': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'write'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['auth.User']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'permission_name': ('django.db.models.fields.CharField', [], {'max_length': '255'}) + }, + 'simplewiki.revision': { + 'Meta': {'object_name': 'Revision'}, + 'article': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['simplewiki.Article']"}), + 'contents': ('django.db.models.fields.TextField', [], {}), + 'contents_parsed': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'counter': ('django.db.models.fields.IntegerField', [], {'default': '1'}), + 'deleted': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'previous_revision': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['simplewiki.Revision']", 'null': 'True', 'blank': 'True'}), + 'revision_date': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'revision_text': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), + 'revision_user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'wiki_revision_user'", 'null': 'True', 'to': "orm['auth.User']"}) + } + } + + complete_apps = ['simplewiki'] \ No newline at end of file diff --git a/lms/djangoapps/simplewiki/migrations/__init__.py b/lms/djangoapps/simplewiki/migrations/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/lms/djangoapps/simplewiki/models copy.py b/lms/djangoapps/simplewiki/models copy.py new file mode 100644 index 0000000000..ade95ed491 --- /dev/null +++ b/lms/djangoapps/simplewiki/models copy.py @@ -0,0 +1,367 @@ +import difflib +import os + +from django import forms +from django.contrib.auth.models import User +from django.core.urlresolvers import reverse +from django.db import models +from django.db.models import signals +from django.utils.translation import ugettext_lazy as _ +from markdown import markdown + +from wiki_settings import * +from util.cache import cache + + +class ShouldHaveExactlyOneRootSlug(Exception): + pass + +class Article(models.Model): + """Wiki article referring to Revision model for actual content. + 'slug' and 'parent' field should be maintained centrally, since users + aren't allowed to change them, anyways. + """ + + title = models.CharField(max_length=512, verbose_name=_('Article title'), + blank=False) + slug = models.SlugField(max_length=100, verbose_name=_('slug'), + help_text=_('Letters, numbers, underscore and hyphen.'), + blank=True) + created_by = models.ForeignKey(User, verbose_name=_('Created by'), blank=True, null=True) + created_on = models.DateTimeField(auto_now_add = 1) + modified_on = models.DateTimeField(auto_now_add = 1) + parent = models.ForeignKey('self', verbose_name=_('Parent article slug'), + help_text=_('Affects URL structure and possibly inherits permissions'), + null=True, blank=True) + locked = models.BooleanField(default=False, verbose_name=_('Locked for editing')) + permissions = models.ForeignKey('Permission', verbose_name=_('Permissions'), + blank=True, null=True, + help_text=_('Permission group')) + current_revision = models.OneToOneField('Revision', related_name='current_rev', + blank=True, null=True, editable=True) + related = models.ManyToManyField('self', verbose_name=_('Related articles'), symmetrical=True, + help_text=_('Sets a symmetrical relation other articles'), + blank=True, null=True) + + def attachments(self): + return ArticleAttachment.objects.filter(article__exact = self) + + @classmethod + def get_root(cls): + """Return the root article, which should ALWAYS exist.. + except the very first time the wiki is loaded, in which + case the user is prompted to create this article.""" + try: + return Article.objects.filter(slug__exact = "")[0] + except: + raise ShouldHaveExactlyOneRootSlug() + + def get_url(self): + """Return the Wiki URL for an article""" + url = self.slug + "/" + if self.parent_id: + parent_url = cache.get("wiki_url-" + str(self.parent_id)) + if parent_url is None: + parent_url = self.parent.get_url() + + url = parent_url + url + + cache.set("wiki_url-" + str(self.id), url, 60*60) + + return url + + def get_abs_url(self): + """Return the absolute path for an article. This is necessary in cases + where the template system isn't used for generating URLs...""" + # TODO: Remove and create a reverse() lookup. + return WIKI_BASE + self.get_url() + + @models.permalink + def get_absolute_url(self): + return ('wiki_view', [self.get_url()]) + + @classmethod + def get_url_reverse(cls, path, article, return_list=[]): + """Lookup a URL and return the corresponding set of articles + in the path.""" + if path == []: + return return_list + [article] + # Lookup next child in path + try: + a = Article.objects.get(parent__exact = article, slug__exact=str(path[0])) + return cls.get_url_reverse(path[1:], a, return_list+[article]) + except Exception, e: + return None + + def can_read(self, user): + """ Check read permissions and return True/False.""" + if user.is_superuser: + return True + if self.permissions: + perms = self.permissions.can_read.all() + return perms.count() == 0 or (user in perms) + else: + return self.parent.can_read(user) if self.parent else True + + def can_write(self, user): + """ Check write permissions and return True/False.""" + if user.is_superuser: + return True + if self.permissions: + perms = self.permissions.can_write.all() + return perms.count() == 0 or (user in perms) + else: + return self.parent.can_write(user) if self.parent else True + + def can_write_l(self, user): + """Check write permissions and locked status""" + if user.is_superuser: + return True + return not self.locked and self.can_write(user) + + def can_attach(self, user): + return self.can_write_l(user) and (WIKI_ALLOW_ANON_ATTACHMENTS or not user.is_anonymous()) + + def __unicode__(self): + if self.slug == '' and not self.parent: + return unicode(_('Root article')) + else: + return self.get_url() + + class Meta: + unique_together = (('slug', 'parent'),) + verbose_name = _('Article') + verbose_name_plural = _('Articles') + +def get_attachment_filepath(instance, filename): + """Store file, appending new extension for added security""" + dir_ = WIKI_ATTACHMENTS + instance.article.get_url() + dir_ = '/'.join(filter(lambda x: x!='', dir_.split('/'))) + if not os.path.exists(WIKI_ATTACHMENTS_ROOT + dir_): + os.makedirs(WIKI_ATTACHMENTS_ROOT + dir_) + return dir_ + '/' + filename + '.upload' + +class ArticleAttachment(models.Model): + article = models.ForeignKey(Article, verbose_name=_('Article')) + file = models.FileField(max_length=255, upload_to=get_attachment_filepath, verbose_name=_('Attachment')) + uploaded_by = models.ForeignKey(User, blank=True, verbose_name=_('Uploaded by'), null=True) + uploaded_on = models.DateTimeField(auto_now_add = True, verbose_name=_('Upload date')) + + def download_url(self): + return reverse('wiki_view_attachment', args=(self.article.get_url(), self.filename())) + + def filename(self): + return '.'.join(self.file.name.split('/')[-1].split('.')[:-1]) + + def get_size(self): + try: + size = self.file.size + except OSError: + size = 0 + return size + + def filename(self): + return '.'.join(self.file.name.split('/')[-1].split('.')[:-1]) + + def is_image(self): + fname = self.filename().split('.') + if len(fname) > 1 and fname[-1].lower() in WIKI_IMAGE_EXTENSIONS: + return True + return False + + def get_thumb(self): + return self.get_thumb_impl(*WIKI_IMAGE_THUMB_SIZE) + + def get_thumb_small(self): + return self.get_thumb_impl(*WIKI_IMAGE_THUMB_SIZE_SMALL) + + def mk_thumbs(self): + self.mk_thumb(*WIKI_IMAGE_THUMB_SIZE, **{'force':True}) + self.mk_thumb(*WIKI_IMAGE_THUMB_SIZE_SMALL, **{'force':True}) + + def mk_thumb(self, width, height, force=False): + """Requires Python Imaging Library (PIL)""" + if not self.get_size(): + return False + + if not self.is_image(): + return False + + base_path = os.path.dirname(self.file.path) + orig_name = self.filename().split('.') + thumb_filename = "%s__thumb__%d_%d.%s" % ('.'.join(orig_name[:-1]), width, height, orig_name[-1]) + thumb_filepath = "%s%s%s" % (base_path, os.sep, thumb_filename) + + if force or not os.path.exists(thumb_filepath): + try: + import Image + img = Image.open(self.file.path) + img.thumbnail((width,height), Image.ANTIALIAS) + img.save(thumb_filepath) + except IOError: + return False + + return True + + def get_thumb_impl(self, width, height): + """Requires Python Imaging Library (PIL)""" + + if not self.get_size(): + return False + + if not self.is_image(): + return False + + self.mk_thumb(width, height) + + orig_name = self.filename().split('.') + thumb_filename = "%s__thumb__%d_%d.%s" % ('.'.join(orig_name[:-1]), width, height, orig_name[-1]) + thumb_url = settings.MEDIA_URL + WIKI_ATTACHMENTS + self.article.get_url() +'/' + thumb_filename + + return thumb_url + + def __unicode__(self): + return self.filename() + +class Revision(models.Model): + + article = models.ForeignKey(Article, verbose_name=_('Article')) + revision_text = models.CharField(max_length=255, blank=True, null=True, + verbose_name=_('Description of change')) + revision_user = models.ForeignKey(User, verbose_name=_('Modified by'), + blank=True, null=True, related_name='wiki_revision_user') + revision_date = models.DateTimeField(auto_now_add = True, verbose_name=_('Revision date')) + contents = models.TextField(verbose_name=_('Contents (Use MarkDown format)')) + contents_parsed = models.TextField(editable=False, blank=True, null=True) + counter = models.IntegerField(verbose_name=_('Revision#'), default=1, editable=False) + previous_revision = models.ForeignKey('self', blank=True, null=True, editable=False) + + # Deleted has three values. 0 is normal, non-deleted. 1 is if it was deleted by a normal user. It should + # be a NEW revision, so that it appears in the history. 2 is a special flag that can be applied or removed + # from a normal revision. It means it has been admin-deleted, and can only been seen by an admin. It doesn't + # show up in the history. + deleted = models.IntegerField(verbose_name=_('Deleted group'), default=0) + + def get_user(self): + return self.revision_user if self.revision_user else _('Anonymous') + + # Called after the deleted fied has been changed (between 0 and 2). This bypasses the normal checks put in + # save that update the revision or reject the save if contents haven't changed + def adminSetDeleted(self, deleted): + self.deleted = deleted + super(Revision, self).save() + + def save(self, **kwargs): + # Check if contents have changed... if not, silently ignore save + if self.article and self.article.current_revision: + if self.deleted == 0 and self.article.current_revision.contents == self.contents: + return + else: + import datetime + self.article.modified_on = datetime.datetime.now() + self.article.save() + + # Increment counter according to previous revision + previous_revision = Revision.objects.filter(article=self.article).order_by('-counter') + if previous_revision.count() > 0: + if previous_revision.count() > previous_revision[0].counter: + self.counter = previous_revision.count() + 1 + else: + self.counter = previous_revision[0].counter + 1 + else: + self.counter = 1 + if (self.article.current_revision and self.article.current_revision.deleted == 0): + self.previous_revision = self.article.current_revision + + # Create pre-parsed contents - no need to parse on-the-fly + ext = WIKI_MARKDOWN_EXTENSIONS + ext += ["wikipath(base_url=%s)" % reverse('wiki_view', args=('/',))] + self.contents_parsed = markdown(self.contents, + extensions=ext, + safe_mode='escape',) + super(Revision, self).save(**kwargs) + + def delete(self, **kwargs): + """If a current revision is deleted, then regress to the previous + revision or insert a stub, if no other revisions are available""" + article = self.article + if article.current_revision == self: + prev_revision = Revision.objects.filter(article__exact = article, + pk__not = self.pk).order_by('-counter') + if prev_revision: + article.current_revision = prev_revision[0] + article.save() + else: + r = Revision(article=article, + revision_user = article.created_by) + r.contents = unicode(_('Auto-generated stub')) + r.revision_text= unicode(_('Auto-generated stub')) + r.save() + article.current_revision = r + article.save() + super(Revision, self).delete(**kwargs) + + def get_diff(self): + if (self.deleted == 1): + yield "Article Deletion" + return + + if self.previous_revision: + previous = self.previous_revision.contents.splitlines(1) + else: + previous = [] + + # Todo: difflib.HtmlDiff would look pretty for our history pages! + diff = difflib.unified_diff(previous, self.contents.splitlines(1)) + # let's skip the preamble + diff.next(); diff.next(); diff.next() + + for d in diff: + yield d + + def __unicode__(self): + return "r%d" % self.counter + + class Meta: + verbose_name = _('article revision') + verbose_name_plural = _('article revisions') + +class Permission(models.Model): + permission_name = models.CharField(max_length = 255, verbose_name=_('Permission name')) + can_write = models.ManyToManyField(User, blank=True, null=True, related_name='write', + help_text=_('Select none to grant anonymous access.')) + can_read = models.ManyToManyField(User, blank=True, null=True, related_name='read', + help_text=_('Select none to grant anonymous access.')) + def __unicode__(self): + return self.permission_name + class Meta: + verbose_name = _('Article permission') + verbose_name_plural = _('Article permissions') + +class RevisionForm(forms.ModelForm): + contents = forms.CharField(label=_('Contents'), widget=forms.Textarea(attrs={'rows':8, 'cols':50})) + class Meta: + model = Revision + fields = ['contents', 'revision_text'] +class RevisionFormWithTitle(forms.ModelForm): + title = forms.CharField(label=_('Title')) + class Meta: + model = Revision + fields = ['title', 'contents', 'revision_text'] +class CreateArticleForm(RevisionForm): + title = forms.CharField(label=_('Title')) + class Meta: + model = Revision + fields = ['title', 'contents',] + +def set_revision(sender, *args, **kwargs): + """Signal handler to ensure that a new revision is always chosen as the + current revision - automatically. It simplifies stuff greatly. Also + stores previous revision for diff-purposes""" + instance = kwargs['instance'] + created = kwargs['created'] + if created and instance.article: + instance.article.current_revision = instance + instance.article.save() + +signals.post_save.connect(set_revision, Revision) diff --git a/lms/djangoapps/simplewiki/models.py b/lms/djangoapps/simplewiki/models.py index ade95ed491..200f161eba 100644 --- a/lms/djangoapps/simplewiki/models.py +++ b/lms/djangoapps/simplewiki/models.py @@ -16,9 +16,23 @@ from util.cache import cache class ShouldHaveExactlyOneRootSlug(Exception): pass +class Namespace(models.Model): + name = models.CharField(max_length=30, db_index=True, unique=True, verbose_name=_('namespace')) + # TODO: We may want to add permissions, etc later + + @classmethod + def ensure_namespace(cls, name): + try: + namespace = Namespace.objects.get(name__exact = name) + except Namespace.DoesNotExist: + new_namespace = Namespace(name=name) + new_namespace.save() + + + class Article(models.Model): """Wiki article referring to Revision model for actual content. - 'slug' and 'parent' field should be maintained centrally, since users + 'slug' and 'title' field should be maintained centrally, since users aren't allowed to change them, anyways. """ @@ -27,12 +41,10 @@ class Article(models.Model): slug = models.SlugField(max_length=100, verbose_name=_('slug'), help_text=_('Letters, numbers, underscore and hyphen.'), blank=True) + namespace = models.ForeignKey(Namespace, verbose_name=_('Namespace')) created_by = models.ForeignKey(User, verbose_name=_('Created by'), blank=True, null=True) created_on = models.DateTimeField(auto_now_add = 1) modified_on = models.DateTimeField(auto_now_add = 1) - parent = models.ForeignKey('self', verbose_name=_('Parent article slug'), - help_text=_('Affects URL structure and possibly inherits permissions'), - null=True, blank=True) locked = models.BooleanField(default=False, verbose_name=_('Locked for editing')) permissions = models.ForeignKey('Permission', verbose_name=_('Permissions'), blank=True, null=True, @@ -45,53 +57,44 @@ class Article(models.Model): def attachments(self): return ArticleAttachment.objects.filter(article__exact = self) + + def get_path(self): + return self.namespace.name + "/" + self.slug + + @classmethod + def get_article(cls, article_path): + """ + Given an article_path like namespace/slug, this returns the article. It may raise + a Article.DoesNotExist if no matching article is found or ValueError if the + article_path is not constructed properly. + """ + #TODO: Verify the path, throw a meaningful error? + namespace, slug = article_path.split("/") + return Article.objects.get( slug__exact = slug, namespace__name__exact = namespace) + @classmethod - def get_root(cls): + def get_root(cls, namespace): """Return the root article, which should ALWAYS exist.. except the very first time the wiki is loaded, in which case the user is prompted to create this article.""" try: - return Article.objects.filter(slug__exact = "")[0] + return Article.objects.filter(slug__exact = "", namespace__name__exact = namespace)[0] except: raise ShouldHaveExactlyOneRootSlug() - def get_url(self): - """Return the Wiki URL for an article""" - url = self.slug + "/" - if self.parent_id: - parent_url = cache.get("wiki_url-" + str(self.parent_id)) - if parent_url is None: - parent_url = self.parent.get_url() - - url = parent_url + url - - cache.set("wiki_url-" + str(self.id), url, 60*60) - - return url - - def get_abs_url(self): - """Return the absolute path for an article. This is necessary in cases - where the template system isn't used for generating URLs...""" - # TODO: Remove and create a reverse() lookup. - return WIKI_BASE + self.get_url() - - @models.permalink - def get_absolute_url(self): - return ('wiki_view', [self.get_url()]) - - @classmethod - def get_url_reverse(cls, path, article, return_list=[]): - """Lookup a URL and return the corresponding set of articles - in the path.""" - if path == []: - return return_list + [article] - # Lookup next child in path - try: - a = Article.objects.get(parent__exact = article, slug__exact=str(path[0])) - return cls.get_url_reverse(path[1:], a, return_list+[article]) - except Exception, e: - return None + # @classmethod + # def get_url_reverse(cls, path, article, return_list=[]): + # """Lookup a URL and return the corresponding set of articles + # in the path.""" + # if path == []: + # return return_list + [article] + # # Lookup next child in path + # try: + # a = Article.objects.get(parent__exact = article, slug__exact=str(path[0])) + # return cls.get_url_reverse(path[1:], a, return_list+[article]) + # except Exception, e: + # return None def can_read(self, user): """ Check read permissions and return True/False.""" @@ -101,7 +104,8 @@ class Article(models.Model): perms = self.permissions.can_read.all() return perms.count() == 0 or (user in perms) else: - return self.parent.can_read(user) if self.parent else True + # TODO: We can inherit namespace permissions here + return True def can_write(self, user): """ Check write permissions and return True/False.""" @@ -111,7 +115,8 @@ class Article(models.Model): perms = self.permissions.can_write.all() return perms.count() == 0 or (user in perms) else: - return self.parent.can_write(user) if self.parent else True + # TODO: We can inherit namespace permissions here + return True def can_write_l(self, user): """Check write permissions and locked status""" @@ -123,13 +128,13 @@ class Article(models.Model): return self.can_write_l(user) and (WIKI_ALLOW_ANON_ATTACHMENTS or not user.is_anonymous()) def __unicode__(self): - if self.slug == '' and not self.parent: + if self.slug == '': return unicode(_('Root article')) else: - return self.get_url() + return self.slug class Meta: - unique_together = (('slug', 'parent'),) + unique_together = (('slug', 'namespace'),) verbose_name = _('Article') verbose_name_plural = _('Articles') @@ -275,7 +280,7 @@ class Revision(models.Model): # Create pre-parsed contents - no need to parse on-the-fly ext = WIKI_MARKDOWN_EXTENSIONS - ext += ["wikipath(base_url=%s)" % reverse('wiki_view', args=('/',))] + ext += ["wikipath(default_namespace=%s)" % self.article.namespace.name ] self.contents_parsed = markdown(self.contents, extensions=ext, safe_mode='escape',) diff --git a/lms/djangoapps/simplewiki/urls.py b/lms/djangoapps/simplewiki/urls.py index a41ce3617b..2d01c06bf9 100644 --- a/lms/djangoapps/simplewiki/urls.py +++ b/lms/djangoapps/simplewiki/urls.py @@ -1,20 +1,19 @@ -from django.conf.urls.defaults import * +from django.conf.urls.defaults import patterns, url + +namespace_regex = r"[a-zA-Z\d._-]+" +article_slug = r'/(?P