Repository: translate/pootle

Issue:
Alter the virtual_path for existing announcements on core
This is necessary to avoid virtual_path clashes when creating announcements for languages and TPs.



Discussion:

Resolving patch:
diff --git a/pootle/apps/pootle_translationproject/views.py b/pootle/apps/pootle_translationproject/views.py
--- a/pootle/apps/pootle_translationproject/views.py
+++ b/pootle/apps/pootle_translationproject/views.py
@@ -70,7 +70,7 @@ def overview(request, translation_project, dir_path, filename=None):
 
     # TODO: cleanup and refactor, retrieve from cache
     try:
-        ann_virtual_path = 'announcements/' + project.code
+        ann_virtual_path = 'announcements/projects/' + project.code
         announcement = StaticPage.objects.live(request.user).get(
             virtual_path=ann_virtual_path,
         )
diff --git a/pootle/apps/staticpages/migrations/0002_alter_project_announcements_virtual_path.py b/pootle/apps/staticpages/migrations/0002_alter_project_announcements_virtual_path.py
new file mode 100644
--- /dev/null
+++ b/pootle/apps/staticpages/migrations/0002_alter_project_announcements_virtual_path.py
@@ -0,0 +1,106 @@
+# -*- coding: utf-8 -*-
+from south.utils import datetime_utils as datetime
+from south.db import db
+from south.v2 import DataMigration
+from django.db import models
+
+
+ANN_VPATH = u'announcements/'
+
+
+class Migration(DataMigration):
+
+    def forwards(self, orm):
+        announcements = orm.StaticPage.objects.filter(
+            virtual_path__startswith=ANN_VPATH
+        )
+
+        for ann in announcements:
+            project_code = ann.virtual_path[len(ANN_VPATH):]
+            ann.virtual_path = u'announcements/projects/' + project_code
+            ann.save()
+
+    def backwards(self, orm):
+        announcements = orm.StaticPage.objects.filter(
+            virtual_path__startswith=u'announcements/projects/'
+        )
+
+        for ann in announcements:
+            project_code = ann.virtual_path[len(u'announcements/projects/'):]
+            ann.virtual_path = ANN_VPATH + project_code
+            ann.save()
+
+    models = {
+        'pootle.user': {
+            'Meta': {'object_name': 'User'},
+            'alt_src_langs': ('django.db.models.fields.related.ManyToManyField', [], {'db_index': 'True', 'to': u"orm['pootle_language.Language']", 'symmetrical': 'False', 'blank': 'True'}),
+            'bio': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+            'currency': ('django.db.models.fields.CharField', [], {'max_length': '3', 'null': 'True', 'blank': 'True'}),
+            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '255'}),
+            'full_name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
+            'hourly_rate': ('django.db.models.fields.FloatField', [], {'default': '0'}),
+            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+            'is_employee': ('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'}),
+            'linkedin': ('django.db.models.fields.URLField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
+            'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
+            'rate': ('django.db.models.fields.FloatField', [], {'default': '0'}),
+            'review_rate': ('django.db.models.fields.FloatField', [], {'default': '0'}),
+            'score': ('django.db.models.fields.FloatField', [], {'default': '0'}),
+            'twitter': ('django.db.models.fields.CharField', [], {'max_length': '15', 'null': 'True', 'blank': 'True'}),
+            'unit_rows': ('django.db.models.fields.SmallIntegerField', [], {'default': '9'}),
+            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}),
+            'website': ('django.db.models.fields.URLField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'})
+        },
+        'pootle_app.directory': {
+            'Meta': {'ordering': "['name']", 'object_name': 'Directory'},
+            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+            'obsolete': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'child_dirs'", 'null': 'True', 'to': "orm['pootle_app.Directory']"}),
+            'pootle_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'})
+        },
+        u'pootle_language.language': {
+            'Meta': {'ordering': "['code']", 'object_name': 'Language', 'db_table': "'pootle_app_language'"},
+            'code': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '50', 'db_index': 'True'}),
+            'directory': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['pootle_app.Directory']", 'unique': 'True'}),
+            'fullname': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'nplurals': ('django.db.models.fields.SmallIntegerField', [], {'default': '0'}),
+            'pluralequation': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
+            'specialchars': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'})
+        },
+        u'staticpages.agreement': {
+            'Meta': {'unique_together': "(('user', 'document'),)", 'object_name': 'Agreement'},
+            'agreed_on': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now', 'auto_now': 'True', 'auto_now_add': 'True', 'blank': 'True'}),
+            'document': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['staticpages.LegalPage']"}),
+            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['pootle.User']"})
+        },
+        u'staticpages.legalpage': {
+            'Meta': {'object_name': 'LegalPage'},
+            'active': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'body': ('pootle.core.markup.fields.MarkupField', [], {'blank': 'True'}),
+            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'modified_on': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now', 'auto_now_add': 'True', 'blank': 'True'}),
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
+            'virtual_path': ('django.db.models.fields.CharField', [], {'default': "''", 'unique': 'True', 'max_length': '100'})
+        },
+        u'staticpages.staticpage': {
+            'Meta': {'object_name': 'StaticPage'},
+            'active': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'body': ('pootle.core.markup.fields.MarkupField', [], {'blank': 'True'}),
+            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'modified_on': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now', 'auto_now_add': 'True', 'blank': 'True'}),
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
+            'virtual_path': ('django.db.models.fields.CharField', [], {'default': "''", 'unique': 'True', 'max_length': '100'})
+        }
+    }
+
+    complete_apps = ['staticpages']
+    symmetrical = True
diff --git a/pootle/apps/staticpages/views.py b/pootle/apps/staticpages/views.py
--- a/pootle/apps/staticpages/views.py
+++ b/pootle/apps/staticpages/views.py
@@ -135,7 +135,7 @@ def get_form(self, form_class):
         if self.page_type == ANN_TYPE:
             del form.fields['url']
             form.fields['virtual_path'] \
-                .widget.attrs['placeholder'] = u'<project_code>'
+                .widget.attrs['placeholder'] = u'projects/<project_code>'
 
         return form
 


Test patch: