Clean supportBDS migrations.

- Fix some issues and improve efficiency of some RunPython code in
migrations.
- Merge some migrations.
- To simplify, any RunPython don't get a revert function.
This commit is contained in:
Aurélien Delobelle 2017-09-05 14:41:13 +02:00
parent 131c45e1c7
commit 5d572b3603
14 changed files with 529 additions and 629 deletions

View file

@ -1,60 +1,72 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.contrib.auth.models import Group
from django.db import migrations, models
from django.db.models import F
def create_profile(apps, schema_editor):
CofProfile = apps.get_model("cof", "CofProfile")
Profile = apps.get_model("gestion", "Profile")
for p in CofProfile.objects.all():
profile = Profile.objects.create(
id=p.id,
user=p.user,
login_clipper=p.login_clipper,
phone=p.phone,
occupation=p.occupation,
departement=p.departement,
comments=p.comments
def profiles_to_gestion(apps, schema_editor):
OldProfile = apps.get_model('cof', 'CofProfile')
NewProfile = apps.get_model('gestion', 'Profile')
# New profiles are massively imported from the old profiles.
# IDs are kept identical to ease the migration of models which were
# referencing the CofProfile model.
new_profiles = []
for old_p in OldProfile.objects.values().iterator():
new_profiles.append(
NewProfile(
id=old_p['id'],
user_id=old_p['user_id'],
login_clipper=old_p['login_clipper'],
phone=old_p['phone'],
occupation=old_p['occupation'],
departement=old_p['departement'],
comments=old_p['comments'],
)
)
p.profile = profile
p.save()
NewProfile.objects.bulk_create(new_profiles)
OldProfile.objects.all().update(profile_id=F('id'))
def preserve_perms(apps, schema_editor):
COFProfile = apps.get_model("cof", "CofProfile")
def cof_status_to_gestion(apps, schema_editor):
Association = apps.get_model('gestion', 'Association')
CofProfile = apps.get_model('cof', 'CofProfile')
# create the groups for COF members and staff
member = Group.objects.create(name='cof_members')
buro = Group.objects.create(name='cof_buro')
cof_assoc = Association.objects.get(name='COF')
cprofiles = COFProfile.objects.select_related("profile__user")
for cofp in cprofiles.filter(is_cof=True):
cofp.profile.user.groups.add(member)
for cofp in cprofiles.filter(is_buro=True):
cofp.profile.user.groups.add(buro)
cof_pks = (
CofProfile.objects
.select_related('profile')
.values_list('profile__user_id', flat=True)
)
def remove_profile(apps, schema_editor):
raise NotImplementedError
fuckup_perms = remove_profile
cof_assoc.members_group.user_set.add(
*cof_pks.filter(is_cof=True)
)
cof_assoc.staff_group.user_set.add(
*cof_pks.filter(is_buro=True)
)
class Migration(migrations.Migration):
"""
BDS support changes how users data is organized.
Data is migrated to the new schema.
"""
dependencies = [
('gestion', '0001_initial'),
('cof', '0008_py3'),
('gestion', '0002_create_cof_bds'),
]
operations = [
migrations.RenameField(
model_name='cofprofile',
old_name='mailing_cof',
new_name='mailing',
),
# Temporarly authorize 'profile' as nullable to allow migrating data.
migrations.AddField(
model_name='cofprofile',
name='profile',
@ -66,15 +78,8 @@ class Migration(migrations.Migration):
),
preserve_default=False,
),
migrations.AlterModelOptions(
name='cofprofile',
options={
'permissions': (('member', 'Is a COF member'),
('buro', 'Is part of COF staff')),
'verbose_name': 'Profil COF',
'verbose_name_plural': 'Profils COF'},
),
migrations.RunPython(create_profile, remove_profile),
migrations.RunPython(profiles_to_gestion),
# Data is migrated, unset nullable on 'profile'.
migrations.AlterField(
model_name='cofprofile',
name='profile',
@ -84,6 +89,11 @@ class Migration(migrations.Migration):
related_name='cof'
),
),
# Remove fields no longer used.
migrations.RemoveField(
model_name='cofprofile',
name='user',
),
migrations.RemoveField(
model_name='cofprofile',
name='comments',
@ -104,7 +114,10 @@ class Migration(migrations.Migration):
model_name='cofprofile',
name='phone',
),
migrations.RunPython(preserve_perms, fuckup_perms),
# Keep cof member/staff status.
migrations.RunPython(cof_status_to_gestion),
# Remove the last no longer used fields.
migrations.RemoveField(
model_name='cofprofile',
name='is_cof',
@ -113,8 +126,19 @@ class Migration(migrations.Migration):
model_name='cofprofile',
name='is_buro',
),
migrations.RemoveField(
# Now we are safe, let's do basic operations.
migrations.AlterModelOptions(
name='cofprofile',
options={
'permissions': (('member', 'Is a COF member'),
('buro', 'Is part of COF staff')),
'verbose_name': 'Profil COF',
'verbose_name_plural': 'Profils COF'},
),
migrations.RenameField(
model_name='cofprofile',
name='user',
old_name='mailing_cof',
new_name='mailing',
),
]

View file

@ -0,0 +1,65 @@
from __future__ import unicode_literals
from django.db import migrations
def clubs_to_gestion(apps, schema_editor):
Association = apps.get_model('gestion', 'Association')
Membership = apps.get_model('gestion', 'ClubUser')
OldClub = apps.get_model('cof', 'Club')
NewClub = apps.get_model('gestion', 'Club')
cof_assoc = Association.objects.get(name='COF')
memberships = []
for oldclub in OldClub.objects.all():
newclub = NewClub.objects.create(
name=oldclub.name,
description=oldclub.description,
association=cof_assoc,
)
members = oldclub.membres.values_list('id', flat=True)
respos = oldclub.respos.values_list('id', flat=True)
for user in members:
memberships.append(
Membership(
club=newclub,
user_id=user,
has_paid=True,
is_respo=user in respos,
)
)
Membership.objects.bulk_create(memberships)
class Migration(migrations.Migration):
"""
This migration focus on migrating clubs data to the 'gestion' app.
"""
dependencies = [
('cof', '0009_move_profile'),
('gestion', '0002_create_cof_bds'),
]
operations = [
# Move clubs from cof to gestion.
migrations.RunPython(clubs_to_gestion),
# Delete legacy Club model.
migrations.RemoveField(
model_name='club',
name='membres',
),
migrations.RemoveField(
model_name='club',
name='respos',
),
migrations.DeleteModel(
name='Club',
),
]

View file

@ -0,0 +1,129 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations
def event_to_gestion(apps, schema_editor):
# Fetching the models that have be moved from cof to gestion
OldEvent = apps.get_model('cof', 'Event')
NewEvent = apps.get_model('gestion', 'Event')
Location = apps.get_model('gestion', 'Location')
Association = apps.get_model('gestion', 'Association')
# The old Event.location field becomes a table: we need to create an entry
# in this table for each value of the old `location` field.
locations = set() # A set to prevent duplicate entries
old_events = OldEvent.objects.values()
new_events = []
for event in old_events:
locations.add(event["location"])
new_events.append(event)
Location.objects.bulk_create([Location(name=name) for name in locations])
map_loc = {
loc.name: loc
for loc in Location.objects.all()
}
for event in new_events:
event["location"] = map_loc[event["location"]]
NewEvent.objects.bulk_create([
NewEvent(**event)
for event in new_events
])
# Do not forget to link all the existing event to the COF association
cof_assoc = Association.objects.get(name="COF")
cof_assoc.events.add(*NewEvent.objects.all())
# Migrating the other models is straightforward.
# Keep care to the ordering. A change can lead to DB error because of
# failed checks on foreignkey constraints. The dependencies between these
# models give the following constraints:
# - EventRegistration must precede EventCommentField and EventOption,
# - EventCommentField must precede EventCommentValue,
# - EventOption must precede EventOptionChoice.
model_names = [
'EventRegistration', 'EventCommentField', 'EventCommentValue',
'EventOption', 'EventOptionChoice',
]
cls_models = [
(apps.get_model('cof', name), apps.get_model('gestion', name))
for name in model_names
]
for FromModel, ToModel in cls_models:
ToModel.objects.bulk_create([
ToModel(**values)
for values in FromModel.objects.values()
])
class Migration(migrations.Migration):
dependencies = [
('cof', '0010_move_club'),
('gestion', '0002_create_cof_bds'),
]
operations = [
migrations.RunPython(event_to_gestion),
migrations.RemoveField(
model_name='eventcommentfield',
name='event',
),
migrations.RemoveField(
model_name='eventcommentvalue',
name='commentfield',
),
migrations.RemoveField(
model_name='eventcommentvalue',
name='registration',
),
migrations.RemoveField(
model_name='eventoption',
name='event',
),
migrations.RemoveField(
model_name='eventoptionchoice',
name='event_option',
),
migrations.AlterUniqueTogether(
name='eventregistration',
unique_together=set([]),
),
migrations.RemoveField(
model_name='eventregistration',
name='event',
),
migrations.RemoveField(
model_name='eventregistration',
name='filledcomments',
),
migrations.RemoveField(
model_name='eventregistration',
name='options',
),
migrations.RemoveField(
model_name='eventregistration',
name='user',
),
migrations.DeleteModel(
name='Event',
),
migrations.DeleteModel(
name='EventCommentField',
),
migrations.DeleteModel(
name='EventCommentValue',
),
migrations.DeleteModel(
name='EventOption',
),
migrations.DeleteModel(
name='EventOptionChoice',
),
migrations.DeleteModel(
name='EventRegistration',
),
]

View file

@ -1,13 +1,10 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('cof', '0009_generic_profiles'),
('cof', '0011_move_event'),
]
operations = [

View file

@ -1,23 +0,0 @@
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('cof', '0011_delete_clipper_and_custommail'),
('gestion', '0002_club_support')
]
operations = [
migrations.RemoveField(
model_name='club',
name='membres',
),
migrations.RemoveField(
model_name='club',
name='respos',
),
migrations.DeleteModel(
name='Club',
),
]

View file

@ -0,0 +1,36 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('cof', '0012_remove_clipper_custommail'),
]
operations = [
migrations.AlterField(
model_name='petitcoursattribution',
name='matiere',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='cof.PetitCoursSubject', verbose_name='Matière'),
),
migrations.AlterField(
model_name='petitcoursattributioncounter',
name='matiere',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='cof.PetitCoursSubject', verbose_name='Matiere'),
),
migrations.AlterField(
model_name='petitcoursattributioncounter',
name='user',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL),
),
migrations.AlterField(
model_name='petitcoursdemande',
name='traitee_par',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL),
),
]

View file

@ -1,96 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.3 on 2017-07-26 18:29
from __future__ import unicode_literals
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('cof', '0012_remove_club'),
("gestion", "0003_association_and_events")
]
operations = [
migrations.RemoveField(
model_name='eventcommentfield',
name='event',
),
migrations.RemoveField(
model_name='eventcommentvalue',
name='commentfield',
),
migrations.RemoveField(
model_name='eventcommentvalue',
name='registration',
),
migrations.RemoveField(
model_name='eventoption',
name='event',
),
migrations.RemoveField(
model_name='eventoptionchoice',
name='event_option',
),
migrations.AlterUniqueTogether(
name='eventregistration',
unique_together=set([]),
),
migrations.RemoveField(
model_name='eventregistration',
name='event',
),
migrations.RemoveField(
model_name='eventregistration',
name='filledcomments',
),
migrations.RemoveField(
model_name='eventregistration',
name='options',
),
migrations.RemoveField(
model_name='eventregistration',
name='user',
),
migrations.AlterField(
model_name='petitcoursattribution',
name='matiere',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='cof.PetitCoursSubject', verbose_name='Matière'),
),
migrations.AlterField(
model_name='petitcoursattributioncounter',
name='matiere',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='cof.PetitCoursSubject', verbose_name='Matiere'),
),
migrations.AlterField(
model_name='petitcoursattributioncounter',
name='user',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL),
),
migrations.AlterField(
model_name='petitcoursdemande',
name='traitee_par',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL),
),
migrations.DeleteModel(
name='Event',
),
migrations.DeleteModel(
name='EventCommentField',
),
migrations.DeleteModel(
name='EventCommentValue',
),
migrations.DeleteModel(
name='EventOption',
),
migrations.DeleteModel(
name='EventOptionChoice',
),
migrations.DeleteModel(
name='EventRegistration',
),
]