Django migration mit uuid-Feld erzeugt, dupliziert Werte
Ich habe eine uuid
Feld (kein Primärschlüssel). Die generierte migration:
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),
),
...
]
Aber wenn dabei python manage.py migrate
es abstürzt, mit:
django.db.utils.IntegrityError: could not create unique index
"restaurants_device_uuid_key" DETAIL: Schlüssel
(uuid)=(f3858ded-b8e0-4ac0-8436-8a61b10efc73) wird dupliziert.
Seltsam genug, das problem scheint nicht auftreten, mit den primär-Schlüssel (das sind vielleicht, erstellt von der Datenbank, und nicht intern von django?)
Wie kann ich eine uuid-Feld, und stellen Sie sicher, dass Migrationen zu arbeiten?
- Die docs erklären das ziemlich gut, siehe Migrationen, einzigartigen Felder.
- Danke. Das ist erstaunlich. Amaizingly interessant und erstaunlich Komplex. Nur .. zu .. zu generieren .. uuids
- Alternativ, es ist ein hack, sondern bietet eine ähnliche Funktionalität, und die Art und Weise einfacher: str_uuid = Modelle.CharField(max_length=36,default=lambda:str(uuid.uuid4())). Nach der migration führen Sie eine Schleife für jedes Objekt im Modell, und speichern (), um Sie zu erhalten eine eindeutige uuid. Sie brauchen nicht einen eindeutigen index, da die Chancen für die gleiche uuid4 sind nahe null.
- interessanter workaround. Meine Lösung war noch einfacher: entfernen Sie die
unique=True
Einschränkung. Die UUIDs werden kommen aus dem frontend sowieso (Sie beziehen sich auf mobile Geräte), technisch habe ich nicht einmal einen Standard. Es ist ein bisschen komisch, weil Sie wirklich einzigartig sein müssen, aber ich konnte nicht get it to work mitdefault=None
undunique=True
, das ist eigentlich das, was ich wollte: Sie müssen einzigartig sein, solange Sie nicht leer sind. Ich weiß nicht, auch wenn django (oder das Datenbank-backend) unterstützt diese Art von Zwang. - Eigentlich ja, die ganze Idee der UUID ist, dass es ist einzigartig, egal wo Sie erstellt wurde
- aber macht django unterstützt eine "eindeutige oder Keine" Einschränkung?
- hmmm... hätte nie gedacht, dass es der Weg. Aber effektiv, ein uuid Feld, mit leeren, einzigartig ist oder keine index!
- Danke für den Hinweis!, Ich habe mein Problem gelöst, indem er sich alle Skripte aus der Dokumentation zu einzelnen Migrationen-Dateien. Keine Notwendigkeit zu schaffen, 2 leere Migrations-Skripts
- Die Django-Dokumentation schlägt die Schaffung von drei-migration-Dateien hinzufügen, um die neue UUID-Feld. Eine einfachere Möglichkeit ist das hinzufügen der gen_uuid Methode in der ursprünglichen migration, ändern, unique=True, null=True in der AddField Betrieb, fügen Sie die RunPython Betrieb unter und Folgen Sie dann es mit als AlterField Betrieb und ersetzt die null=True mit unique=True. Nur eine einzige migration erforderlich.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Hier ist ein Beispiel tut alles, was in einer einzigen migration Dank einer RunPython nennen.
create_uuid
ausgeführt wird, werden Ihre Daten überschrieben werden (zugegeben, Django versucht, um die Tabelle zu sperren, um zu verhindern, dass). Stattdessen sollte esdevice.save(update_fields=['uuid'])
wie in den Django-docs.cannot ALTER TABLE "table_model" because it has pending trigger events
(Antwort entnommen aus dem ersten Kommentar)
Finden Sie in der django-docs - Migrationen, einzigartigen Felder
Empfehlen Sie ändern Ihre migration in drei separate Migrationen:
In dem Modus, den Sie konfiguriert haben, dass Sie wollen, dass eindeutige Werte für die uuid-Felder, aber mit default-Werten(für alle gleich). Also, wenn Sie zwei 'Gerät' - Objekte in der Datenbank die Migrationen hinzufügen 'uuid' - Feld mit dem Standardwert 'uuid.uuid4' Wert und wenn es versucht, um es an das zweite, es stürzt ab, aufgrund der einzigartigen Einschränkungen.
Wenn Sie drop-db und neue Objekte anzulegen, wahrscheinlich wird es keine Probleme aber das ist keine Lösung für die Produktions-db offensichtlich :D.
Eine bessere Lösung ist das erstellen einer Daten-migration, die setzt andere uuid-Wert (erzeugt durch die Standard - 'uuid' Bibliothek) zu jedem vorhandenen Objekt in der Datenbank. Lesen Sie mehr über Datenmigrationen hier:
https://docs.djangoproject.com/en/1.10/topics/migrations/#data-migrations
Dann, wenn Sie neue Objekte erstellen, django erzeugen unterschiedliche uuid automatisch. 😉
Für die primären Tasten: Django fügt es auf das Modell standardmäßig.