django: sqlite3 --> postgres

Django, Flask, Bottle, WSGI, CGI…
Antworten
robin_
User
Beiträge: 48
Registriert: Montag 3. August 2020, 17:59

Hi zusammen, auf meinem Weg zum publishen meiner ersten App muss ich nun die sqlite3 - DB durch eine andere ersetzten.

Hierfür habe ich mich für postgres entschieden; Heroku bietet das an und die Implementierung dazu scheint soweit relativ einfach zu sein.
Nun habe ich, zum testen, erstmal eine lokale DB (mit pgAdmin 4) erstellt & die Verbindung hergestellt.

Ich dachte eig., dass ich nun nur migrieren muss und alles klappt. Dem ist leider nicht so, anscheinend gibt es dann doch Felder, die in sqlite funktionieren, die es in postgres so nicht gibt?
Konkret, das entnehme ich den Fehlermeldungen, geht es um folgendes Feld:

Code: Alles auswählen

task_choice = models.CharField(max_length=2 ,choices=TaskChoices.choices, default=TaskChoices.TASK_CURRENT)
Wie gesagt, das hat mit der sqlite3-DB gut funktioniert.

Hier die besagte Fehlermeldung ( py manage.py migrate):

Code: Alles auswählen

Operations to perform:
  Apply all migrations: admin, auth, authtoken, contenttypes, crog, sessions
Running migrations:
  Applying crog.0003_auto_20201212_1019...Traceback (most recent call last):
  File "C:\Users\Robin\DEV\crog-project\env\lib\site-packages\django\db\backends\utils.py", line 84, in _execute
    return self.cursor.execute(sql, params)
psycopg2.errors.UndefinedColumn: FEHLER:  Spalte »task_choice« von Relation »crog_task« existiert nicht


The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "C:\Users\Robin\DEV\crog-project\crog-drf\manage.py", line 22, in <module>
    main()
  File "C:\Users\Robin\DEV\crog-project\crog-drf\manage.py", line 18, in main
    execute_from_command_line(sys.argv)
  File "C:\Users\Robin\DEV\crog-project\env\lib\site-packages\django\core\management\__init__.py", line 401, in execute_from_command_line
    utility.execute()
  File "C:\Users\Robin\DEV\crog-project\env\lib\site-packages\django\core\management\__init__.py", line 395, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "C:\Users\Robin\DEV\crog-project\env\lib\site-packages\django\core\management\base.py", line 330, in run_from_argv
    self.execute(*args, **cmd_options)
  File "C:\Users\Robin\DEV\crog-project\env\lib\site-packages\django\core\management\base.py", line 371, in execute
    output = self.handle(*args, **options)
  File "C:\Users\Robin\DEV\crog-project\env\lib\site-packages\django\core\management\base.py", line 85, in wrapped
    res = handle_func(*args, **kwargs)
  File "C:\Users\Robin\DEV\crog-project\env\lib\site-packages\django\core\management\commands\migrate.py", line 243, in handle
    post_migrate_state = executor.migrate(
  File "C:\Users\Robin\DEV\crog-project\env\lib\site-packages\django\db\migrations\executor.py", line 117, in migrate
    state = self._migrate_all_forwards(state, plan, full_plan, fake=fake, fake_initial=fake_initial)
  File "C:\Users\Robin\DEV\crog-project\env\lib\site-packages\django\db\migrations\executor.py", line 147, in _migrate_all_forwards
    state = self.apply_migration(state, migration, fake=fake, fake_initial=fake_initial)
  File "C:\Users\Robin\DEV\crog-project\env\lib\site-packages\django\db\migrations\executor.py", line 227, in apply_migration
    state = migration.apply(state, schema_editor)
  File "C:\Users\Robin\DEV\crog-project\env\lib\site-packages\django\db\migrations\migration.py", line 124, in apply
    operation.database_forwards(self.app_label, schema_editor, old_state, project_state)
  File "C:\Users\Robin\DEV\crog-project\env\lib\site-packages\django\db\migrations\operations\fields.py", line 166, in database_forwards
    schema_editor.remove_field(from_model, from_model._meta.get_field(self.name))
  File "C:\Users\Robin\DEV\crog-project\env\lib\site-packages\django\db\backends\base\schema.py", line 524, in remove_field
    self.execute(sql)
  File "C:\Users\Robin\DEV\crog-project\env\lib\site-packages\django\db\backends\base\schema.py", line 142, in execute
    cursor.execute(sql, params)
  File "C:\Users\Robin\DEV\crog-project\env\lib\site-packages\django\db\backends\utils.py", line 98, in execute
    return super().execute(sql, params)
  File "C:\Users\Robin\DEV\crog-project\env\lib\site-packages\django\db\backends\utils.py", line 66, in execute
    return self._execute_with_wrappers(sql, params, many=False, executor=self._execute)
  File "C:\Users\Robin\DEV\crog-project\env\lib\site-packages\django\db\backends\utils.py", line 75, in _execute_with_wrappers
    return executor(sql, params, many, context)
  File "C:\Users\Robin\DEV\crog-project\env\lib\site-packages\django\db\backends\utils.py", line 84, in _execute
    return self.cursor.execute(sql, params)
  File "C:\Users\Robin\DEV\crog-project\env\lib\site-packages\django\db\utils.py", line 90, in __exit__
    raise dj_exc_value.with_traceback(traceback) from exc_value
  File "C:\Users\Robin\DEV\crog-project\env\lib\site-packages\django\db\backends\utils.py", line 84, in _execute
    return self.cursor.execute(sql, params)
django.db.utils.ProgrammingError: FEHLER:  Spalte »task_choice« von Relation »crog_task« existiert nicht
In pgAdmin wird die Spalte nicht angezeigt, es scheint also tatsächlich nicht zu existieren.

Beim Googlen bin ich auf folgenden "Ersatz" gekommen:

Code: Alles auswählen

from django.contrib.postgres import fields
...
task_choices = fields.ArrayField(
    models.CharField(max_length=2, choices=TaskChoices.choices, default=TaskChoices.TASK_CURRENT),
    default = list,
    blank=True,
    )
Jedoch gibts hier die folgende Meldung:

Code: Alles auswählen

Operations to perform:
  Apply all migrations: admin, auth, authtoken, contenttypes, crog, sessions
Running migrations:
  Applying crog.0003_auto_20201212_1019...Traceback (most recent call last):
  File "C:\Users\Robin\DEV\crog-project\env\lib\site-packages\django\db\backends\utils.py", line 84, in _execute
    return self.cursor.execute(sql, params)
psycopg2.errors.UndefinedColumn: FEHLER:  Spalte »task_choice« von Relation »crog_task« existiert nicht


The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "C:\Users\Robin\DEV\crog-project\crog-drf\manage.py", line 22, in <module>
    main()
  File "C:\Users\Robin\DEV\crog-project\crog-drf\manage.py", line 18, in main
    execute_from_command_line(sys.argv)
  File "C:\Users\Robin\DEV\crog-project\env\lib\site-packages\django\core\management\__init__.py", line 401, in execute_from_command_line
    utility.execute()
  File "C:\Users\Robin\DEV\crog-project\env\lib\site-packages\django\core\management\__init__.py", line 395, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "C:\Users\Robin\DEV\crog-project\env\lib\site-packages\django\core\management\base.py", line 330, in run_from_argv
    self.execute(*args, **cmd_options)
  File "C:\Users\Robin\DEV\crog-project\env\lib\site-packages\django\core\management\base.py", line 371, in execute
    output = self.handle(*args, **options)
  File "C:\Users\Robin\DEV\crog-project\env\lib\site-packages\django\core\management\base.py", line 85, in wrapped
    res = handle_func(*args, **kwargs)
  File "C:\Users\Robin\DEV\crog-project\env\lib\site-packages\django\core\management\commands\migrate.py", line 243, in handle
    post_migrate_state = executor.migrate(
  File "C:\Users\Robin\DEV\crog-project\env\lib\site-packages\django\db\migrations\executor.py", line 117, in migrate
    state = self._migrate_all_forwards(state, plan, full_plan, fake=fake, fake_initial=fake_initial)
  File "C:\Users\Robin\DEV\crog-project\env\lib\site-packages\django\db\migrations\executor.py", line 147, in _migrate_all_forwards
    state = self.apply_migration(state, migration, fake=fake, fake_initial=fake_initial)
  File "C:\Users\Robin\DEV\crog-project\env\lib\site-packages\django\db\migrations\executor.py", line 227, in apply_migration
    state = migration.apply(state, schema_editor)
  File "C:\Users\Robin\DEV\crog-project\env\lib\site-packages\django\db\migrations\migration.py", line 124, in apply
    operation.database_forwards(self.app_label, schema_editor, old_state, project_state)
  File "C:\Users\Robin\DEV\crog-project\env\lib\site-packages\django\db\migrations\operations\fields.py", line 166, in database_forwards
    schema_editor.remove_field(from_model, from_model._meta.get_field(self.name))
  File "C:\Users\Robin\DEV\crog-project\env\lib\site-packages\django\db\backends\base\schema.py", line 524, in remove_field
    self.execute(sql)
  File "C:\Users\Robin\DEV\crog-project\env\lib\site-packages\django\db\backends\base\schema.py", line 142, in execute
    cursor.execute(sql, params)
  File "C:\Users\Robin\DEV\crog-project\env\lib\site-packages\django\db\backends\utils.py", line 98, in execute
    return super().execute(sql, params)
  File "C:\Users\Robin\DEV\crog-project\env\lib\site-packages\django\db\backends\utils.py", line 66, in execute
    return self._execute_with_wrappers(sql, params, many=False, executor=self._execute)
  File "C:\Users\Robin\DEV\crog-project\env\lib\site-packages\django\db\backends\utils.py", line 75, in _execute_with_wrappers
    return executor(sql, params, many, context)
  File "C:\Users\Robin\DEV\crog-project\env\lib\site-packages\django\db\backends\utils.py", line 84, in _execute
    return self.cursor.execute(sql, params)
  File "C:\Users\Robin\DEV\crog-project\env\lib\site-packages\django\db\utils.py", line 90, in __exit__
    raise dj_exc_value.with_traceback(traceback) from exc_value
  File "C:\Users\Robin\DEV\crog-project\env\lib\site-packages\django\db\backends\utils.py", line 84, in _execute
    return self.cursor.execute(sql, params)
django.db.utils.ProgrammingError: FEHLER:  Spalte »task_choice« von Relation »crog_task« existiert nicht
Also genau das selbe. Für einen Tipp wäre ich sehr dankbar :)
Benutzeravatar
noisefloor
User
Beiträge: 4250
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,
anscheinend gibt es dann doch Felder, die in sqlite funktionieren, die es in postgres so nicht gibt?
Nee, SQLite ist die "funktionsärmste" DB mit den wenigsten Datentypen. Eigentlich bieten alle anderen RDBMS mehr.

Ich verstehe den Fehler auch eher so, dass bei der Migration bestimmte Tabellen oder Spalten aus Tabellen nicht angelegt worden sind. Darum funktioniert dann auch die Relation nicht.

Da ich aber selber noch nie bei Django von SQLite auf Postgres migriert habe, kann ich dir da auch nicht wirklich tiefer helfen. Aber gem. z.B. dieser Anleitung sieht das eigentlich ziemlich einfach aus.

Gruß, noisefloor
Benutzeravatar
sparrow
User
Beiträge: 4591
Registriert: Freitag 17. April 2009, 10:28

Ich bin auch etwas verwirrt, weil da überhaupt eine Migration stattfinden muss.
Bei Django bin ich nicht auf dem neuesten Stand, aber Migrationen sind ja eigentlich dazu da, ein bestehendes Datenbankschema anzupassen, weil sich das Schema im Zuge der Entwicklung geändert hat. Aber da die Datenbank ja neu ist, müssten da - meiner Meinung nach - gar keine Migrationen gefahren werden. Da muss das Schema entsprechend per sync erstellt werden.
robin_
User
Beiträge: 48
Registriert: Montag 3. August 2020, 17:59

Also ich werde mir jetzt die Anleitung anschauen, aber das Problem ist tatsächlich, dass die eine Spalte durch Django nicht angelegt wird, der Rest ist da :S

Achja, die Daten sind mir übrigens komplett egal; Die müssen nicht migriert werden. Ich möchte quasi nur die gleiche Funktionalität wie mit der sqlite3 wiederherstellen.
robin_
User
Beiträge: 48
Registriert: Montag 3. August 2020, 17:59

Verzweifle gerade ein wenig :S

Irgendwas scheint nicht zu stimmen. Habe verschiedene Felder angelegt mit verschiedenen Namen, gleichen Attributen. Manche wurden nach

Code: Alles auswählen

py manage.py makemigrations
py manage.py migrate
hinzugefügt, manche nicht. Noch kurioser: Nach dem Auskommentieren & Speichern wurden die Felder nicht mehr gelöscht (Ebenfalls natürlich makemigrations & migrate ausgeführt).

Manchmal konnte ich nicht migrieren, nach dem löschen der migration-Files ging es dann aber wieder.
Bis zuletzt hatte ich in der DB Spalten die nicht mehr existieren (im Model) aber nach wie vor in der DB vorhanden sind.
Auf einmal kriege ich auch Fehler aus anderen Models geworfen, wo Spalten nicht existieren würden.

Wenn ich das ganze wieder in der settings.py auf die sqlite3 - DB ändere klappt wieder alles reibungslos.

Daher meine Frage: Muss ich irgendwas besonderes beachten? Ich dachte eigentlich, das modeling-System wäre extra dafür, um DB relativ einfach austauschen zu können, da man keine spezifischen Befehle der Datenbanken ausführt?

Danke !
Benutzeravatar
sparrow
User
Beiträge: 4591
Registriert: Freitag 17. April 2009, 10:28

Es weiß niemand, was du da tust.
Die Gesschichte mit den Migrationen ist ganz einfach: Wenn du "makemigrations" ausführst, dann wird geschaut, was sch seit der letzten Migration getan hat und die entsprechenden Befehle gespeichert, die die Datenbank so verändern, dass die Datenbank zu den Modellen passt.
Aber das Programm kennt den Zustand der Datenbank nicht. Es verlässt sich darauf, dass der Zustand identisch zu dem Zustand ist, der laut der letzten Migration vorliegen sollte.

Wenn man anfängt die Dateien der Migration zu löschen, könnte dieser Zustand natürlich schwammig werden.

Mach eine Kopie von deinem Projekt.
Lösch darin deine Migrationsdateien.
Leg eine komplett neue und leere Datenbank an.
Führe makemigrations und migrate aus. Das sollte ein initiales Anlegen der Datenbank ausführen.

Wenn das geht und deine Migrationen nicht, dann stimmt mit deine Migrationen etwas nicht.
Benutzeravatar
__blackjack__
User
Beiträge: 14237
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Wenn die Daten komplett egal sind, warum dann überhaupt der Kram mit Migrations? Dann kannst Du doch einfach mit einer leeren DB anfangen und Django nagelneue, leere Tabellen anlegen lassen.
“Ich bin für die Todesstrafe. Wer schreckliche Dinge getan hat, muss eine angemessene Strafe bekommen. So lernt er seine Lektion für das nächste Mal.” — Britney Spears, Interview in der französischen Zeitung Libération, 2. April 2002
DasIch
User
Beiträge: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

Django selbst aber auch 3rd party apps legen Tabellen über Migrations an. Man kann deswegen nicht einfach Migrations komplett ignorieren.

Man sollte auch zumindest verstehen wie dieser ziemlich essentielle Teil von Django funktioniert bevor man sich früher oder später in Production die Datenbank ruiniert.
Antworten