[PYTHON] Lernnotizen für die Migrationsfunktion im Django-Framework (3)

In den beiden vorherigen Notizen habe ich viel über die Migrationsfunktion von Django gelernt. In diesem Abschnitt erfahren Sie mehr über die Fehlerbehebung bei Migrationen, die für Vorgänge hilfreich sind.

Entwicklungsumgebung
Mac OS:Sierra
python2.7.10
django1.11.2
mysql5.7.18

Fügen Sie ein eindeutiges Feld hinzu, um es mit Legacy-Daten anzugeben

Problembeschreibung: Die Daten wurden erstellt, nachdem die Site für einen bestimmten Zeitraum betrieben wurde. Fügen Sie Ihrem Modell nun ein neues eindeutiges Feld hinzu, das nicht nullbar ist. Legacy-Daten (vorhandene Daten) müssen Standardwerte erhalten, damit das Modell in der Datenbank angezeigt wird. Wenn Sie jedoch mehreren Datensätzen denselben Standardwert geben, verstößt dies gegen die Eindeutigkeitsregel und verursacht einen Fehler. Wenn Sie sich in einer Entwicklungsumgebung befinden, können Sie alle Datenbanken und Migrationsdateien löschen und die Datenbank neu erstellen. Lassen Sie uns dieses Problem jedoch auf eine elegantere Weise lösen.

Problemwiedergabe

Rufen Sie die Django-Shell auf und erstellen Sie die Demo-Daten.

python manage.py shell
>>> from polls.models import Category, Article
>>> c = Category(name="game")
>>> c.save()
>>> a1 = Article(title="play Game1", text="Game1 is amazing!", category=c, image_url = "http://url1")
>>> a1.save()
>>> a2 = Article(title="play Game2", text="Game2 is good!", category=c, image_url = "http://url2")
>>> a2.save()
>>> a3 = Article(title="play Game3", text="Game3 is dump!", category=c, image_url = "http://url3")
>>> a3.save()

Sie können die vom MySQL-Client erstellten Daten sehen (geben Sie zuerst die Projektdatenbank an). Zunächst Blog-Kategoriedaten:

mysql> select * from polls_category;
+----+------+
| id | name |
+----+------+
|  1 | game |
+----+------+
1 row in set (0.00 sec)

Als nächstes Satzdaten

mysql> select * from polls_article;
+----+------------+-------------------+-------------+-------------+
| id | title      | text              | category_id | image_url   |
+----+------------+-------------------+-------------+-------------+
|  1 | play Game1 | Game1 is amazing! |           1 | http://url1 |
|  2 | play Game2 | Game2 is good!    |           1 | http://url2 |
|  3 | play Game3 | Game3 is dump!    |           1 | http://url3 |
+----+------------+-------------------+-------------+-------------+
3 rows in set (0.00 sec)

Fügen Sie nun dem Artikelmodell ein Feld article_id hinzu, um den Artikel eindeutig zu identifizieren (im Gegensatz zum automatisch erstellten Primärschlüssel). Dieses Feld erfüllt die folgenden Anforderungen: --non-nullable (Null ist nicht zulässig, da es sich um einen Bezeichner handelt. Ein Standardwert ist erforderlich.) --unique (macht es eindeutig identifizierbar) Wenn Sie die Modelldatei gemäß Ihren Anforderungen ändern:

models.py


class Article(models.Model):
    title = models.CharField(max_length=100)
    text = models.CharField(max_length=1000)
    category = models.ForeignKey(Category, on_delete=models.CASCADE)
    image_url = models.URLField(max_length=200, default='toBeImplement')
    article_id = models.UUIDField(default=uuid.uuid4(), unique=True)

(Es wird nur die Artikelklasse angezeigt.) Migrationsdatei erstellen:

python manage.py makemigrations polls

Erfolg

Migrations for 'polls':
  polls/migrations/0003_article_article_id.py
    - Add field article_id to article

Versuch, in der Datenbank zu reflektieren:

python manage.py migrate polls

Ich erhalte eine Fehlermeldung (Teilprotokoll)

...
django.db.utils.IntegrityError: (1062, "Duplicate entry '3059fd8259254f0693ce8d91cf1198cc' for key 'article_id'")

Sehen Sie sich die Migrationsdatei 0003_article_article_id.py an, um den Fehler zu beheben:

0003_article_article_id.py


# -*- coding: utf-8 -*-
# Generated by Django 1.11.2 on 2017-07-18 08:25
from __future__ import unicode_literals

from django.db import migrations, models
import uuid


class Migration(migrations.Migration):

    dependencies = [
        ('polls', '0002_article_image_url'),
    ]

    operations = [
        migrations.AddField(
            model_name='article',
            name='article_id',
            field=models.UUIDField(default=uuid.UUID('3059fd82-5925-4f06-93ce-8d91cf1198cc'), unique=True),
        ),
    ]

Der Grund für den Fehler ist, dass ich beim Hinzufügen von article_id zu einem vorhandenen Datendatensatz (Article) denselben Standardwert angegeben und die eindeutige Anforderung verletzt habe.

Wie repariert man

Wenn Sie über Legacy-Daten verfügen, sind drei Schritte erforderlich, um nicht nullfähige und eindeutige Felder hinzuzufügen. Siehe offizielle Website

Überblick

Annahme: Das entsprechende Feld wurde zur Modelldatei hinzugefügt.

  1. Erstellen Sie eine Migrationsdatei, die der Modelländerung entspricht, und ändern Sie die Feldattribute von eindeutig in nullwertfähig.
  2. Erstellen Sie eine leere Migrationsdatei und geben Sie den Altdaten einen Standardwert.
  3. Erstellen Sie eine leere Migrationsdatei und setzen Sie die Feldattribute wieder auf eindeutig.

Einzelheiten

Schritt 1: Wie oben erwähnt, wurden die Felder bereits zum Artikelmodell hinzugefügt und die Migrationsdatei 0003_article_article_id.py wurde ebenfalls erstellt. Ändern Sie daher die Migrationsdatei 0003_article_article_id.py.

0003_article_article_id.py


# -*- coding: utf-8 -*-
# Generated by Django 1.11.2 on 2017-07-18 08:25
from __future__ import unicode_literals

from django.db import migrations, models
import uuid


class Migration(migrations.Migration):

    dependencies = [
        ('polls', '0002_article_image_url'),
    ]

    operations = [
        migrations.AddField(
            model_name='article',
            name='article_id',
            field=models.UUIDField(default=uuid.UUID('3059fd82-5925-4f06-93ce-8d91cf1198cc'), null=True),
        ),
    ]

Ändern Sie also "unique = True" in der Klasse Migration-> operation-> migrations.AddField () in "null = True". Sie können jetzt dieselben Standardwerte in die neue Spalte der Altdaten einfügen.

Schritt 2: Erstellen Sie eine leere Migrationsdatei.

python manage.py makemigrations polls --empty

Fügen Sie nun einen eindeutigen Wert für jeden Datensatz von Altdaten in eine neue Spalte ein

0004_auto_20170718_0901.py


# -*- coding: utf-8 -*-
# Generated by Django 1.11.2 on 2017-07-18 09:01
from __future__ import unicode_literals

from django.db import migrations
import uuid


def gen_uuid(apps, schema_editor):
    Article = apps.get_model('polls', 'Article')
    for row in Article.objects.all():
        row.article_id = uuid.uuid4()
        row.save(update_fields=['article_id'])


class Migration(migrations.Migration):

    dependencies = [
        ('polls', '0003_article_article_id'),
    ]

    operations = [
        migrations.RunPython(gen_uuid, reverse_code=migrations.RunPython.noop)
    ]

Schritt 3: Erstellen Sie abschließend erneut eine leere Migrationsdatei und setzen Sie die Spaltenattribute wieder auf eindeutig. Jetzt können Sie die Spalten des neu erstellten Datensatzes einschränken.

0005_auto_20170718_0901.py


# -*- coding: utf-8 -*-
# Generated by Django 1.11.2 on 2017-07-18 09:01
from __future__ import unicode_literals

from django.db import migrations, models
import uuid


class Migration(migrations.Migration):

    dependencies = [
        ('polls', '0004_auto_20170718_0901'),
    ]

    operations = [
        migrations.AlterField(
            model_name='article',
            name='article_id',
            field=models.UUIDField(default=uuid.uuid4, unique=True),
        ),
    ]

Sobald die Migrationsdatei fertig ist, spiegeln Sie die Änderungen am Modell und an den Altdaten wider.

(a_site) IT-02085-M:m_Migrate ruofan.ye$ python manage.py migrate polls
Operations to perform:
  Apply all migrations: polls
Running migrations:
  Applying polls.0003_article_article_id... OK
  Applying polls.0004_auto_20170718_0901... OK
  Applying polls.0005_auto_20170718_0901... OK

Erfolg, und wenn Sie sich die Datenbank ansehen

mysql> select * from polls_article;
+----+------------+-------------------+-------------+-------------+----------------------------------+
| id | title      | text              | category_id | image_url   | article_id                       |
+----+------------+-------------------+-------------+-------------+----------------------------------+
|  1 | play Game1 | Game1 is amazing! |           1 | http://url1 | 7347eab9e4df47eb989de30fc6baeec9 |
|  2 | play Game2 | Game2 is good!    |           1 | http://url2 | c4bac1cc1d3242aa934c9cb16f1cf5a9 |
|  3 | play Game3 | Game3 is dump!    |           1 | http://url3 | e6094b7b24fc46e7a59a7b90aaca298c |
+----+------------+-------------------+-------------+-------------+----------------------------------+
3 rows in set (0.00 sec)

Sie haben Ihrer Tabelle und Ihren Altdaten erfolgreich eine neue Spalte hinzugefügt. Neue Artikeldaten erstellen:

>>> a4 = Article(title="play Game4", text="Game4 is new-feeling!", category=c, image_url = "http://url4")
>>> a4.save()

Blick in die Datenbank:

mysql> select * from polls_article;
+----+------------+-----------------------+-------------+-------------+----------------------------------+
| id | title      | text                  | category_id | image_url   | article_id                       |
+----+------------+-----------------------+-------------+-------------+----------------------------------+
|  1 | play Game1 | Game1 is amazing!     |           1 | http://url1 | 7347eab9e4df47eb989de30fc6baeec9 |
|  2 | play Game2 | Game2 is good!        |           1 | http://url2 | c4bac1cc1d3242aa934c9cb16f1cf5a9 |
|  3 | play Game3 | Game3 is dump!        |           1 | http://url3 | e6094b7b24fc46e7a59a7b90aaca298c |
|  4 | play Game4 | Game4 is new-feeling! |           1 | http://url4 | 0f1fcf070c544784b2a11ba2a4661cd7 |
+----+------------+-----------------------+-------------+-------------+----------------------------------+
4 rows in set (0.00 sec)

Das Feld article_id wurde wie erwartet implementiert.

Recommended Posts

Lernnotizen für die Migrationsfunktion im Django-Framework (2)
Lernnotizen für die Migrationsfunktion im Django-Framework (3)
Lernnotizen für die Migrationsfunktion im Django-Framework (1)
Verschiedene Hinweise zum Django REST-Framework
Listenmethode für verschachtelte Ressourcen im Django REST-Framework
Zusammenfassung der Stolperpunkte in Django zum ersten Mal
Starten Sie Notizen für vorhandene Django-Anwendungen
Lernverlauf für die Teilnahme an der Team-App-Entwicklung mit Python ~ Django Tutorial 5 ~
Lernverlauf für die Teilnahme an der Entwicklung von Team-Apps mit Python ~ Django Tutorial 4 ~
Schleife Für umgekehrte Anweisung in HTML-Datei auf Django
Lernverlauf für die Teilnahme an der Team-App-Entwicklung mit Python ~ Django Tutorial 1, 2, 3 ~
Wechseln Sie die in Django 1.9 angezeigte Sprache
Lernverlauf für die Teilnahme an der Team-App-Entwicklung mit Python ~ Django Tutorial 6 ~
Lernverlauf für die Teilnahme an der Team-App-Entwicklung mit Python ~ Django Tutorial 7 ~
Starten Sie Django zum ersten Mal
Zusammenfassung der Seiten, die zum Studium des Deep Learning Framework Chainer nützlich sind
Holen Sie sich die Abfragezeichenfolge (Abfragezeichenfolge) mit Django
Holen Sie sich die IP-Adresse des Kunden mit Django
Einführung in das BOT-Framework Minette für Python
Logisches Löschen in Django, DRF (Django REST Framework)
Verstehen Sie den Komfort des Django Rest Framework
Django ~ Lass es uns im Browser anzeigen ~
Anmerkung von nfc.ContactlessFrontend () von nfcpy von Python
Notizen vom Anfang von Python 1 lernen
Hinweise zum Erstellen statischer Dateien mit Django
Ändern Sie die Liste in der for-Anweisung
Same-Site-Attributeinstellung des Cookies in Django
Abfrageparameter für GET-Anforderungen mit Django abrufen
MongoDB mit Python zum ersten Mal
Hinweise zur Verwendung von Python (Pydev) mit Eclipse
Notizen vom Anfang von Python 2 lernen
Versuchen Sie, die Spotify-API in Django zu aktivieren.
[Lernen stärken] Suche nach der besten Route
Wiederholen Sie alles für den Django-Anmeldebildschirm
Django Memo
Ich habe versucht, die Veränderung der Schneemenge für 2 Jahre durch maschinelles Lernen vorherzusagen
Feature Engineering für maschinelles Lernen Beginnend mit dem 4. Google Colaboratory - Interacting Features
Django Memo
So installieren Sie das Deep Learning Framework Tensorflow 1.0 in der Windows Anaconda-Umgebung
Die Funktion _authenticate_with_backend wurde in django auth.autenticate nicht mehr unterstützt
CERTIFICATE_VERIFY_FAILED in Python 3.6, dem offiziellen Installationsprogramm für macOS
Die Geschichte, dass die Lernkosten von Python niedrig sind
Tipps zum Erreichen der ATND-API mit Python
Hinweise zur Implementierung einer einfachen Co-Filterung in Python
Geben Sie die Ansichts-URL in der Django-Vorlage an
Die Geschichte der Anzeige von Mediendateien in Django
Implementieren Sie die JWT-Anmeldefunktion im Django REST-Framework
[Implementierung zum Lernen] Implementieren Sie Stratified Sampling in Python (1)
[Django] CSS im Projekt kann nicht gelesen werden
Führen Sie eine mehrdeutige Suche nach MySQL in Django durch
Wissensnotizen erforderlich, um das Python-Framework zu verstehen
Implementierung der Authentifizierungsfunktion in Django REST Framework mit djoser
[Für Anfänger] Einführung in die Vektorisierung beim maschinellen Lernen
Ich habe den Deep Learning Framework Chainer installiert
Lassen Sie uns das arithmetische Lehrmittel "Jamaica" ❗️ Vol.02 "Hinweise zum Erstellen von Funktionen in Python" reproduzieren.
Lassen Sie uns das arithmetische Lehrmittel "Jamaica" ❗️ Vol.01 "Hinweise zum Anzeigen von Bildern in Python" reproduzieren.