Ich möchte eine der Möglichkeiten vorstellen, das Datenmodell von einer Anwendung auf eine andere zu übertragen.
Ich stelle gleich fest, dass diese Option zum Übertragen des Datenmodells nicht zu 100% funktioniert und möglicherweise eine zusätzliche manuelle Bearbeitung der Tabellen erforderlich ist, um den Inhaltstyp richtig einzustellen. Da solche Änderungen mit Datenverlust für GenericForeignKey-Beziehungen behaftet sind.
In meinem Fall wurde GenericForeignKey nicht verwendet, daher gab es kein solches Problem.
Ausgangsdaten
Angenommen, Sie haben einen alten Artikel Artikel mit einem Artikelmodell. Sie müssen eine Bloganwendung erstellen und das Artikelmodell in diese Anwendung übertragen. Verwendet eine PostgreSQL-Datenbank.
Modell verschieben
Erstellen Sie eine Sicherungskopie der Datenbank (Backup), Sie können einen Datenbank-Dump erstellen und auf diesem Dump auf dem Entwicklungsserver üben.
Verschieben Sie den Modellcode Artikel von article.models.py nach blog.models.py . Das heißt, der Code aus dem alten Modell muss entfernt werden.
Ändern Sie die Meta -Klasse im Artikel -Modell, um den alten Tabellennamen beizubehalten. In diesem Fall war es article_artilce
Klasse Meta: db_table = 'article_article'
Ändern Sie alle Verweise auf Datenmodelle im gesamten Projekt. Dies bedeutet, dass alle Importe und ForeignKey geändert werden.
Erstellen Sie Migrationen für beide Anwendungen in der folgenden Reihenfolge.
python manage.py makemigrations-Blog python manage.py makemigrations Artikel
- Wenden Sie die Migration im gefälschten Modus an. Auf diese Weise können Sie Migrationen hinzufügen, während sie angewendet werden, es werden jedoch keine Änderungen vorgenommen.
python manage.py migrieren --fake
An diesem Punkt ist die Datenbank in dem Sinne angreifbar, dass sie nicht von ContentType für Ihr übergebenes Datenmodell erstellt wurde.
- Dies kann durch die folgenden Schritte korrigiert werden. Jetzt müssen wir den Namen der Tabelle ändern, und dies kann durch Entfernen von db_table aus dem Datenmodell und Erstellen und Anwenden einer neuen Migration auf die neue Anwendung erfolgen. Inhaltstyp wird automatisch erstellt, wenn Sie die Migration anwenden.
python manage.py makemigrations-Blog python manage.py migrieren
Tatsächlich funktioniert die Datenbank nach diesen Schritten und die Daten werden gespeichert. Möglicherweise sind jedoch zusätzliche Schritte erforderlich, um die Datenbank einzurichten.
Aufräumen und Aktualisieren der Datenbank
Je nachdem, wo und wie das übergebene Datenmodell verwendet wurde. Möglicherweise müssen Sie etwas unternehmen. Beispiel: Anpassen von Content Type für GenericForeignKey .
Ich hatte den einfachsten Fall – das ist das Entfernen des alten Inhaltstyps . Dazu müssen Sie sich mit der Datenbank verbinden und Informationen aus allen Tabellen löschen, die möglicherweise auf den Inhaltstyp des alten Modells verweisen.
Solche Tabellen können sein:
- auth_user_user_permissions
- auth_permission
- django_content_type
- usw. andere Modelle, die vor der Übergabe ältere Modelle verwenden könnten
Ich werde ein Beispiel eines alten Inhaltstyps aus meiner Datenbank zeigen.
Reinigungsvorgang
- Verbinden Sie sich mit der Datenbank
sudo -u postgres psql \c meineprojektdb
- Schauen wir uns die Tabelle django_content_type an, um zu sehen, welche IDs den Legacy-Inhaltstyp haben.
SELECT * FROM django_content_type;
Tabellenausgabe
ID | app_label | Modell ----+-------------+------------------------------- 1 | Konten | Benutzerprofil 2 | Wissen | Sektion 3 | Wissen | Artikel 4 | Administrator | Log Eintrag 5 | Authentifizierung | Erlaubnis 6 | Authentifizierung | Gruppe 7 | Authentifizierung | Benutzer 8 | Inhaltstypen | Inhaltstyp 9 | Sitzungen | Sitzung
- Nachdem wir die alte ID gefunden haben, können wir versuchen, sie zu löschen (z. B. 50 und 51).
DELETE FROM django_content_type WO ID ZWISCHEN 50 UND 51;
- Wenn es nicht geklappt hat, müssen Sie herausfinden, wo die ID-Daten verwendet werden. Der Fehler gibt an, an welchen Tabellen sie beteiligt sind. In meinem Fall waren es auth_permission und auth_user_user_permissions.
SELECT * FROM auth_permission WO content_type_id ZWISCHEN 50 UND 51;
Tabellenausgabe
ID | Name | content_type_id | Code Name -----+--------------------+----------------+----- ----------- 154 | Kann Chat hinzufügen | 50 | add_chat 155 | Kann den Chat ändern | 50 | change_chat 156 | Kann Chat löschen | 50 | delete_chat 157 | Kann Nachricht hinzufügen | 51 | Nachricht hinzufügen 158 | Kann Nachricht ändern | 51 | change_message 159 | Kann Nachricht löschen | 51 | Nachricht löschen 276 | Kann Chat anzeigen | 50 | view_chat 277 | Kann Nachricht anzeigen | 51 | Nachricht ansehen
Suchen Sie als Nächstes nach der gewünschten ID in auth_user_user_permissions
SELECT * FROM auth_user_user_permissions WHERE permission_id=154;
Tabellenausgabe
ID | Benutzer-ID | Berechtigungs-ID -----+---------+--------------- 102 | 2 | 154
- Entfernen Sie alle Berechtigungen für den alten Inhaltstyp aus der Tabelle auth_user_user_permissions.
DELETE FROM auth_user_user_permissions WHERE permission_id=154;
- Entfernen Sie die Berechtigung aus der Tabelle auth_permission.
DELETE FROM auth_permission WO content_type_id ZWISCHEN 50 UND 51;
- Inhaltstypen entfernen.
DELETE FROM django_content_type WO ID ZWISCHEN 50 UND 51;
Fazit
Auf diese Weise können Sie das gewünschte Datenmodell von einer Anwendung in eine andere verschieben und die Datenbank von veralteten Inhalten befreien. Es ist jedoch notwendig, sehr sorgfältig mit der Datenbank zu arbeiten, um ihre Integrität nicht zu verletzen.
Für Django empfehle ich Timeweb VDS-Server .
Дружище, ну подскажи. Совершенно не понял 7-й пункт. А именно, а что происходит с данными, которые в таблице? Или всё делалось, когда в таблице нет данных?
Дело в том, что у меня как раз похожая ситуация. Только нужно перенести три модели, в другое приложение. Понимаю, что всё начинается с одной. Но вот незадача. Все эти таблицы уже заполнены. И связь с этими данными уже достаточно прочная (по факту нужно перенесети каталог, из данных которого уже полно действующих заказов).
И вот мне не ясен такой момент. Вот была article_article. Я из META убираю строчку. Делаю makemigrations и migrate. Так и что происходит с таблицей? Она становиться новенькой, или просто переименовывается?
Я понимаю, что бэкапы и всё такое, но как-то честно сказать очково. Буду потом плясать с этим бэкапом.
Всё делалось, когда данные были в таблице. Сам очковал по полной, когда впервые так делал, раз на десять издевался над дампом на дев сервере, чтобы ничего не поломать.
Суть в том, что старая модель данных переносится в другое приложение, но с помощью db_table = 'article_article' старая таблица сохраняется.
Когда удаляется article_article то в миграции создаётся новое имя таблицы. То есть старая таблица переименовывается, а данные в ней сохраняются.
При этом в шаге 3 таблица условно была удалена из старого приложения, за счёт fake миграции. То есть информация о миграции добавилась, но при этом изменений не произошло.
А вот шаг 7 как раз переименовывает таблицу, чтобы она фактически лежала в новом приложении. Так что ДА - она переименовывается с сохранением данных.
Ну я на свой страх и риск, ночью всё попробовал локально, а потом уже удалил таблицы базы на сервере и залил обновлённый дамп. Спасибо большое. Инструкция реально помогла. Правда пришлось поплясать с сылками на разные роуты. Но оно того стоило. Порядок в папках и в базе радует глаз.
Сам долго колупал форумы, чтобы найти полноценное решение, как это сделать и ничего не поломать.
Иногда там ещё бывают циклические зависимости - вот это реально проблема. Но в итоге тоже нашёл решение через сброс всех миграций и создание одной initial миграции и применение её через fake. Подробнее в этой статье .
у меня была проблема что у меня в кубере автоматом миграция запускалась сделал так (как вариант решения, добовлял каждой миграции RunSQL):