J'ai un champ uuid
(pas une clé primaire). La migration générée est:
from __future__ import unicode_literals
from Django.db import migrations, models
import uuid
class Migration(migrations.Migration):
dependencies = [
....
]
operations = [
...
migrations.AddField(
model_name='device',
name='uuid',
field=models.UUIDField(default=uuid.uuid4, unique=True),
),
...
]
Mais en faisant python manage.py migrate
il plante avec:
Django.db.utils.IntegrityError: impossible de créer un index unique "restaurants_device_uuid_key" DÉTAIL: La clé (uuid) = (f3858ded-b8e0-4ac0-8436-8a61b10efc73) est dupliquée.
Curieusement, le problème ne semble pas se produire avec les clés primaires (qui sont peut-être créées par la base de données, et non en interne par Django?)
Comment puis-je ajouter un champ uuid et m'assurer que les migrations fonctionnent?
Voici un exemple faisant tout en une seule migration grâce à un appel RunPython.
# -*- coding: utf-8 -*
from __future__ import unicode_literals
from Django.db import migrations, models
import uuid
def create_uuid(apps, schema_editor):
Device = apps.get_model('device_app', 'Device')
for device in Device.objects.all():
device.uuid = uuid.uuid4()
device.save()
class Migration(migrations.Migration):
dependencies = [
('device_app', 'XXXX'),
]
operations = [
migrations.AddField(
model_name='device',
name='uuid',
field=models.UUIDField(blank=True, null=True),
),
migrations.RunPython(create_uuid),
migrations.AlterField(
model_name='device',
name='uuid',
field=models.UUIDField(unique=True)
)
]
(Réponse tirée du premier commentaire)
Voir la documentation Django - Migrations qui ajoutent des champs uniques
Ils recommandent de changer votre migration unique en trois migrations distinctes:
Dans le mode, vous avez configuré que vous voulez des valeurs uniques pour les champs uuid, mais avec des valeurs par défaut (les mêmes pour tous). Donc, si vous avez deux objets 'device' dans la base de données, les migrations leur ajoutent le champ 'uuid' avec la valeur par défaut 'uuid.uuid4' et quand il essaie de le définir sur le second, il se bloque à cause des contraintes uniques .
Si vous déposez votre db et créez de nouveaux objets, il n'y aura probablement pas de problèmes mais ce n'est pas une solution pour la production de db évidemment: D.
Une meilleure solution consiste à créer une migration de données qui définit une valeur uuid différente (générée par la bibliothèque "uuid" par défaut) pour chaque objet existant dans la base de données. Vous pouvez en savoir plus sur les migrations de données ici: https://docs.djangoproject.com/en/1.10/topics/migrations/#data-migrations
Ensuite, lorsque vous créez de nouveaux objets, Django générera automatiquement différents uuid.;)
Pour les clés primaires: Django l'ajoute au modèle par défaut.