Mise à jour avec ajout des UUID

La version 20190128 implante la création automatique d’identifiants uniques universels (uuidv4) sur l’ensemble des tables caractérisant une donnée (observateurs, localités, sessions, observations et observations détaillées).

Pour les instances déjà existantes, cette manipulation est délicate car elle nécessite d’intervenir dans le processus de mise à jour en modifiant manuellement les fichiers générés dans les dossiers migrations des applications.

Préalablement à ces manipulations, lancez la commande suivante:

python manage.py makemigrations --settings=dbchiro.settings.production

App « Accounts »

  1. Modifier le fichier autogénéré en assignant null=true

# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import migrations, models
import uuid


class Migration(migrations.Migration):

    dependencies = [("accounts", "MA_MISE_A_JOUR_PRECEDENTE")]

    operations = [
        migrations.AddField(
            model_name="profile",
            name="uuid",
            field=models.UUIDField(
                default=uuid.uuid4, editable=False, null=True
            ),
        )
    ]
  1. Crééez un premier fichier supplémentaire qui générera pour chaque donnée son UUID

from __future__ import unicode_literals

from django.db import migrations
import uuid
from django.apps import apps


app_models = apps.get_app_config("accounts").get_models()


def gen_uuid(apps, schema_editor):
    for MyModel in app_models:
        if "uuid" in [f.name for f in MyModel._meta.get_fields()]:
            tablename = MyModel.objects.model._meta.db_table
            print("Début du traitement de la table {}".format(tablename))
            i = 0
            MyModel.objects.filter(uuid__isnull=False).update(uuid=None)
            while MyModel.objects.filter(uuid__isnull=True).exists():
                print(
                    "Datas to update for {}: {} over {}".format(
                        tablename,
                        MyModel.objects.filter(uuid__isnull=True).count(),
                        MyModel.objects.count(),
                    )
                )
                with transaction.atomic():
                    for row in MyModel.objects.filter(uuid__isnull=True)[:1000]:
                        row.uuid = uuid.uuid4()
                        row.save()


class Migration(migrations.Migration):

    dependencies = [("accounts", "MA_MISE_A_JOUR_PRECEDENTE")]

    operations = [
        # omit reverse_code=... if you don't want the migration to be reversible.
        migrations.RunPython(gen_uuid, reverse_code=migrations.RunPython.noop)
    ]
  1. Crééez un troisième fichier supplémentaire pour rétablir les configurations d’origines du champ uuid avec null=false et unique=true

# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import migrations, models
import uuid


class Migration(migrations.Migration):

    dependencies = [("accounts", "MA_MISE_A_JOUR_PRECEDENTE")]

    operations = [
        migrations.AlterField(
            model_name="profile",
            name="uuid",
            field=models.UUIDField(
                default=uuid.uuid4, editable=False, unique=True, null=false
            ),
        )
    ]

App « sightings »

Même procédé que pour l’app accounts.

  1. Modifier le fichier autogénéré en assignant null=true et en supprimant unique=true

# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import migrations, models
import django.db.models.deletion
import uuid


class Migration(migrations.Migration):

    dependencies = [("sights", "MA_MISE_A_JOUR_PRECEDENTE")]

    operations = [
        migrations.AddField(
            model_name="countdetail",
            name="uuid",
            field=models.UUIDField(
                default=uuid.uuid4, editable=False, null=True
            ),
        ),
        migrations.AddField(
            model_name="place",
            name="uuid",
            field=models.UUIDField(
                default=uuid.uuid4, editable=False, null=True
            ),
        ),
        migrations.AddField(
            model_name="session",
            name="uuid",
            field=models.UUIDField(
                default=uuid.uuid4, editable=False, null=True
            ),
        ),
        migrations.AddField(
            model_name="sighting",
            name="uuid",
            field=models.UUIDField(
                default=uuid.uuid4, editable=False, null=True
            ),
        ),
        migrations.AlterField(
            model_name="session",
            name="contact",
            field=models.ForeignKey(
                default=10,
                on_delete=django.db.models.deletion.DO_NOTHING,
                to="dicts.Contact",
                verbose_name="Type de contact",
            ),
        ),
    ]
  1. Crééez un premier fichier supplémentaire qui générera pour chaque donnée son UUID

# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import migrations, transaction
from django.apps import apps

import uuid

app_models = apps.get_app_config("sights").get_models()


def gen_uuid(apps, schema_editor):
    for MyModel in app_models:
        if "uuid" in [f.name for f in MyModel._meta.get_fields()]:
            tablename = MyModel.objects.model._meta.db_table
            print("Début du traitement de la table {}".format(tablename))
            i = 0
            MyModel.objects.filter(uuid__isnull=False).update(uuid=None)
            while MyModel.objects.filter(uuid__isnull=True).exists():
                print(
                    "Datas to update for {}: {} over {}".format(
                        tablename,
                        MyModel.objects.filter(uuid__isnull=True).count(),
                        MyModel.objects.count(),
                    )
                )
                with transaction.atomic():
                    for row in MyModel.objects.filter(uuid__isnull=True)[:1000]:
                        row.uuid = uuid.uuid4()
                        row.save()

class Migration(migrations.Migration):
    atomic = False

    dependencies = [("sights", "MA_MISE_A_JOUR_PRECEDENTE")]

    operations = [migrations.RunPython(gen_uuid)]
  1. Crééez un troisième fichier supplémentaire pour rétablir les configurations d’origines du champ uuid avec null=false et unique=true

# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import migrations, models
import uuid


class Migration(migrations.Migration):

    dependencies = [("sights", "MA_MISE_A_JOUR_PRECEDENCE")]

    operations = [
        migrations.AlterField(
            model_name="countdetail",
            name="uuid",
            field=models.UUIDField(editable=False, unique=True),
        ),
        migrations.AlterField(
            model_name="place",
            name="uuid",
            field=models.UUIDField(editable=False, unique=True),
        ),
        migrations.AlterField(
            model_name="session",
            name="uuid",
            field=models.UUIDField(editable=False, unique=True),
        ),
        migrations.AlterField(
            model_name="sighting",
            name="uuid",
            field=models.UUIDField(editable=False, unique=True),
        ),
    ]