Merge pull request #4272 from FinnStutzenstein/motionVersionMigration

seperate motion version migration operations
This commit is contained in:
Jochen Saalfeld 2019-02-07 11:19:34 +01:00 committed by GitHub
commit 70af698528
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 185 additions and 124 deletions

View File

@ -1,107 +0,0 @@
# Generated by Django 2.1 on 2018-08-31 13:17
import django.db.models.deletion
import jsonfield.encoder
import jsonfield.fields
from django.db import migrations, models
def copy_motion_version_content_to_motion(apps, schema_editor):
"""
Move all motion version content of the active version to the motion.
"""
Motion = apps.get_model("motions", "Motion")
for motion in Motion.objects.all():
motion.title = motion.active_version.title
motion.text = motion.active_version.text
motion.reason = motion.active_version.reason
motion.modified_final_version = motion.active_version.modified_final_version
motion.amendment_paragraphs = motion.active_version.amendment_paragraphs
motion.save(skip_autoupdate=True)
def migrate_active_change_recommendations(apps, schema_editor):
"""
Delete all change recommendation of motion versions, that are not active. For active
change recommendations the motion id will be set.
"""
MotionChangeRecommendation = apps.get_model("motions", "MotionChangeRecommendation")
to_delete = []
for cr in MotionChangeRecommendation.objects.all():
# chack if version id matches the active version of the motion
if cr.motion_version.id == cr.motion_version.motion.active_version.id:
cr.motion = cr.motion_version.motion
cr.save(skip_autoupdate=True)
else:
to_delete.append(cr)
# delete non active change recommendations
for cr in to_delete:
cr.delete(skip_autoupdate=True)
class Migration(migrations.Migration):
dependencies = [("motions", "0010_auto_20180822_1042")]
operations = [
# Create new fields. Title and Text have empty defaults, but the values
# should be overwritten by copy_motion_version_content_to_motion. In the next
# migration file these defaults are removed.
migrations.AddField(
model_name="motion",
name="title",
field=models.CharField(max_length=255, default=""),
),
migrations.AddField(
model_name="motion", name="text", field=models.TextField(default="")
),
migrations.AddField(
model_name="motion",
name="reason",
field=models.TextField(blank=True, null=True),
),
migrations.AddField(
model_name="motion",
name="modified_final_version",
field=models.TextField(blank=True, null=True),
),
migrations.AddField(
model_name="motion",
name="amendment_paragraphs",
field=jsonfield.fields.JSONField(
dump_kwargs={
"cls": jsonfield.encoder.JSONEncoder,
"separators": (",", ":"),
},
load_kwargs={},
null=True,
),
),
# Copy old motion version data
migrations.RunPython(copy_motion_version_content_to_motion),
# Change recommendations
migrations.AddField(
model_name="motionchangerecommendation",
name="motion",
field=models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
null=True, # This is reverted in the next migration
related_name="change_recommendations",
to="motions.Motion",
),
),
migrations.RunPython(migrate_active_change_recommendations),
migrations.RemoveField(
model_name="motionchangerecommendation", name="motion_version"
),
# remove motion version references from motion and state.
migrations.RemoveField(model_name="motion", name="active_version"),
migrations.AlterUniqueTogether(name="motionversion", unique_together=set()),
migrations.RemoveField(model_name="motionversion", name="motion"),
migrations.RemoveField(model_name="state", name="leave_old_version_active"),
migrations.RemoveField(model_name="state", name="versioning"),
# Delete motion version.
migrations.DeleteModel(name="MotionVersion"),
]

View File

@ -0,0 +1,83 @@
# Generated by Django 2.1 on 2018-08-31 13:17
import django.db.models.deletion
import jsonfield.encoder
import jsonfield.fields
from django.db import migrations, models
class Migration(migrations.Migration):
"""
This is a series of logically connected migrations that needs to be in separate
files. See issue #4266 and https://docs.djangoproject.com/en/2.1/ref/migration-operations/
`On databases that do support DDL transactions (SQLite and PostgreSQL), RunPython operations
do not have any transactions automatically added besides the transactions created for
each migration. Thus, on PostgreSQL, for example, you should avoid combining schema
changes and RunPython operations in the same migration or you may hit errors like
OperationalError: cannot ALTER TABLE "mytable" because it has pending trigger events.`
Because we need some scheam changes, copy data, schema changes, copy data, ..., we need
to split this up.
Goal: Remove the motion_version. Move all fields to the motion model and keep all data.
This also affects change recommendations, that are linked to versions, not motions. All
change recommendations that are connected to active motions versions must be kept, too.
What is done (migration file):
- Create Title, Text, ... fields and new foreign key from CRs to motion (1)
- Copy data from active version to the motion model (2)
- Migrate change recommendations (2)
- Cleanup1: remove all unnecessary fields and delete motion version model (3)
- Cleanup2: alter some other fields that must be in a seperate migration file (Idk why..) (4)
"""
dependencies = [("motions", "0010_auto_20180822_1042")]
operations = [
# Create new fields. Title and Text have empty defaults, but the values
# should be overwritten by copy_motion_version_content_to_motion in migration step (2).
# In the last migration step these defaults are removed.
migrations.AddField(
model_name="motion",
name="title",
field=models.CharField(max_length=255, default=""),
),
migrations.AddField(
model_name="motion", name="text", field=models.TextField(default="")
),
migrations.AddField(
model_name="motion",
name="reason",
field=models.TextField(blank=True, null=True),
),
migrations.AddField(
model_name="motion",
name="modified_final_version",
field=models.TextField(blank=True, null=True),
),
migrations.AddField(
model_name="motion",
name="amendment_paragraphs",
field=jsonfield.fields.JSONField(
dump_kwargs={
"cls": jsonfield.encoder.JSONEncoder,
"separators": (",", ":"),
},
load_kwargs={},
null=True,
),
),
# Link change recommendations to motions directly
migrations.AddField(
model_name="motionchangerecommendation",
name="motion",
field=models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
null=True, # This is reverted in the next migration
related_name="change_recommendations",
to="motions.Motion",
),
),
]

View File

@ -0,0 +1,49 @@
# Generated by Django 2.1 on 2018-08-31 13:17
from django.db import migrations
def copy_motion_version_content_to_motion(apps, schema_editor):
"""
Move all motion version content of the active version to the motion.
"""
Motion = apps.get_model("motions", "Motion")
for motion in Motion.objects.all():
motion.title = motion.active_version.title
motion.text = motion.active_version.text
motion.reason = motion.active_version.reason
motion.modified_final_version = motion.active_version.modified_final_version
motion.amendment_paragraphs = motion.active_version.amendment_paragraphs
motion.save(skip_autoupdate=True)
def migrate_active_change_recommendations(apps, schema_editor):
"""
Delete all change recommendation of motion versions, that are not active. For active
change recommendations the motion id will be set.
"""
MotionChangeRecommendation = apps.get_model("motions", "MotionChangeRecommendation")
to_delete = []
for cr in MotionChangeRecommendation.objects.all():
# chack if version id matches the active version of the motion
if cr.motion_version.id == cr.motion_version.motion.active_version.id:
cr.motion = cr.motion_version.motion
cr.save(skip_autoupdate=True)
else:
to_delete.append(cr)
# delete non active change recommendations
for cr in to_delete:
cr.delete(skip_autoupdate=True)
class Migration(migrations.Migration):
dependencies = [("motions", "0011_motion_version_1")]
operations = [
# Copy old motion version data
migrations.RunPython(copy_motion_version_content_to_motion),
migrations.RunPython(migrate_active_change_recommendations),
]

View File

@ -0,0 +1,23 @@
# Generated by Django 2.1 on 2018-08-31 13:17
from django.db import migrations
class Migration(migrations.Migration):
""" Cleanup 1 """
dependencies = [("motions", "0011_motion_version_2")]
operations = [
migrations.RemoveField(
model_name="motionchangerecommendation", name="motion_version"
),
# remove motion version references from motion and state.
migrations.RemoveField(model_name="motion", name="active_version"),
migrations.AlterUniqueTogether(name="motionversion", unique_together=set()),
migrations.RemoveField(model_name="motionversion", name="motion"),
migrations.RemoveField(model_name="state", name="leave_old_version_active"),
migrations.RemoveField(model_name="state", name="versioning"),
# Delete motion version.
migrations.DeleteModel(name="MotionVersion"),
]

View File

@ -0,0 +1,29 @@
# Generated by Django 2.1 on 2018-08-31 13:17
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
""" Cleanup 2 """
dependencies = [("motions", "0011_motion_version_3")]
operations = [
# Cleanup from last migration. Somehow cannot be done there.
migrations.AlterField( # remove default=''
model_name="motion", name="text", field=models.TextField()
),
migrations.AlterField( # remove default=''
model_name="motion", name="title", field=models.CharField(max_length=255)
),
migrations.AlterField( # remove null=True
model_name="motionchangerecommendation",
name="motion",
field=models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="change_recommendations",
to="motions.Motion",
),
),
]

View File

@ -93,25 +93,9 @@ def create_comment_sections_from_config_and_move_comments_to_own_model(
class Migration(migrations.Migration):
dependencies = [("users", "0006_user_email"), ("motions", "0011_motion_version")]
dependencies = [("users", "0006_user_email"), ("motions", "0011_motion_version_4")]
operations = [
# Cleanup from last migration. Somehow cannot be done there.
migrations.AlterField( # remove default=''
model_name="motion", name="text", field=models.TextField()
),
migrations.AlterField( # remove default=''
model_name="motion", name="title", field=models.CharField(max_length=255)
),
migrations.AlterField( # remove null=True
model_name="motionchangerecommendation",
name="motion",
field=models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="change_recommendations",
to="motions.Motion",
),
),
# Add extension fields for former "special comments". No hack anymore..
migrations.AddField(
model_name="motion",