Evgenii Legotckoi
Evgenii Legotckoi24. April 2019 03:42

Django - Tutorial 045. So verschieben Sie das Modell von einer Anwendung in eine andere

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

  1. Erstellen Sie eine Sicherungskopie der Datenbank (Backup), Sie können einen Datenbank-Dump erstellen und auf diesem Dump auf dem Entwicklungsserver üben.

  2. 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.

  3. Ä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'
  1. Ändern Sie alle Verweise auf Datenmodelle im gesamten Projekt. Dies bedeutet, dass alle Importe und ForeignKey geändert werden.

  2. Erstellen Sie Migrationen für beide Anwendungen in der folgenden Reihenfolge.

python manage.py makemigrations-Blog
python manage.py makemigrations Artikel
  1. 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.

  1. 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

  1. Verbinden Sie sich mit der Datenbank
sudo -u postgres psql
\c meineprojektdb
  1. 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
  1. 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;
  1. 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
  1. 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;
  1. Entfernen Sie die Berechtigung aus der Tabelle auth_permission.
DELETE FROM auth_permission WO content_type_id ZWISCHEN 50 UND 51;
  1. 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 .

Рекомендуємо хостинг TIMEWEB
Рекомендуємо хостинг TIMEWEB
Stabiles Hosting des sozialen Netzwerks EVILEG. Wir empfehlen VDS-Hosting für Django-Projekte.

Magst du es? In sozialen Netzwerken teilen!

Дружище, ну подскажи. Совершенно не понял 7-й пункт. А именно, а что происходит с данными, которые в таблице? Или всё делалось, когда в таблице нет данных?

Дело в том, что у меня как раз похожая ситуация. Только нужно перенести три модели, в другое приложение. Понимаю, что всё начинается с одной. Но вот незадача. Все эти таблицы уже заполнены. И связь с этими данными уже достаточно прочная (по факту нужно перенесети каталог, из данных которого уже полно действующих заказов).

И вот мне не ясен такой момент. Вот была article_article. Я из META убираю строчку. Делаю makemigrations и migrate. Так и что происходит с таблицей? Она становиться новенькой, или просто переименовывается?

Я понимаю, что бэкапы и всё такое, но как-то честно сказать очково. Буду потом плясать с этим бэкапом.

Всё делалось, когда данные были в таблице. Сам очковал по полной, когда впервые так делал, раз на десять издевался над дампом на дев сервере, чтобы ничего не поломать.

Суть в том, что старая модель данных переносится в другое приложение, но с помощью db_table = 'article_article' старая таблица сохраняется.

Когда удаляется article_article то в миграции создаётся новое имя таблицы. То есть старая таблица переименовывается, а данные в ней сохраняются.

При этом в шаге 3 таблица условно была удалена из старого приложения, за счёт fake миграции. То есть информация о миграции добавилась, но при этом изменений не произошло.

А вот шаг 7 как раз переименовывает таблицу, чтобы она фактически лежала в новом приложении. Так что ДА - она переименовывается с сохранением данных.

Ну я на свой страх и риск, ночью всё попробовал локально, а потом уже удалил таблицы базы на сервере и залил обновлённый дамп. Спасибо большое. Инструкция реально помогла. Правда пришлось поплясать с сылками на разные роуты. Но оно того стоило. Порядок в папках и в базе радует глаз.

Сам долго колупал форумы, чтобы найти полноценное решение, как это сделать и ничего не поломать.

Иногда там ещё бывают циклические зависимости - вот это реально проблема. Но в итоге тоже нашёл решение через сброс всех миграций и создание одной initial миграции и применение её через fake. Подробнее в этой статье .

bernar92
  • 9. November 2021 00:46
  • (bearbeitet)

у меня была проблема что у меня в кубере автоматом миграция запускалась сделал так (как вариант решения, добовлял каждой миграции RunSQL):

operations = [
        migrations.RunSQL('''
            ALTER TABLE IF EXISTS credits_operatorcreditapplication RENAME TO operator_creditapplication;
            create table credits_operatorcreditapplication();

            delete from auth_group_permissions
            USING (select *
                   from auth_permission
                   join django_content_type dct on dct.id = auth_permission.content_type_id
            ) dct
            where dct.app_label='credits' and dct.model='operatorcreditapplication';

            DELETE FROM auth_permission
            USING django_content_type
            where django_content_type.app_label='credits' and django_content_type.model='operatorcreditapplication';

            DELETE FROM django_admin_log
            USING django_content_type
            where django_content_type.app_label='credits' and django_content_type.model='operatorcreditapplication';

            DELETE FROM django_content_type WHERE app_label='credits' and model='operatorcreditapplication';
        '''),
        migrations.DeleteModel(
            name='OperatorCreditApplication',
        ),
    ]



operations = [
        migrations.CreateModel(
            name='OperatorCreditApplication',
            fields=[
                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('created_at', models.DateTimeField(auto_now_add=True, db_index=True, verbose_name='Время создания')),
                ('changed_at', models.DateTimeField(auto_now=True, db_index=True, verbose_name='Время последнего изменения'))
            ],
            options={
                'verbose_name': '....',
                'verbose_name_plural': '...',
                'ordering': ('created_at'),
            },
        ),
        migrations.RunSQL('''
            DROP TABLE IF EXISTS scoring_operatorcreditapplication;
            ALTER TABLE IF EXISTS operator_creditapplication RENAME TO scoring_operatorcreditapplication;
        ''')

    ]

Kommentare

Nur autorisierte Benutzer können Kommentare posten.
Bitte Anmelden oder Registrieren
Letzte Kommentare
ИМ
Игорь Максимов5. Oktober 2024 07:51
Django – Lektion 064. So schreiben Sie eine Python-Markdown-Erweiterung Приветствую Евгений! У меня вопрос. Можно ли вставлять свои классы в разметку редактора markdown? Допустим имея стандартную разметку: <ul> <li></li> <li></l…
d
dblas55. Juli 2024 11:02
QML - Lektion 016. SQLite-Datenbank und das Arbeiten damit in QML Qt Здравствуйте, возникает такая проблема (я новичок): ApplicationWindow неизвестный элемент. (М300) для TextField и Button аналогично. Могу предположить, что из-за более новой верси…
k
kmssr8. Februar 2024 18:43
Qt Linux - Lektion 001. Autorun Qt-Anwendung unter Linux как сделать автозапуск для флэтпака, который не даёт создавать файлы в ~/.config - вот это вопрос ))
Qt WinAPI - Lektion 007. Arbeiten mit ICMP-Ping in Qt Без строки #include <QRegularExpressionValidator> в заголовочном файле не работает валидатор.
EVA
EVA25. Dezember 2023 10:30
Boost - statisches Verknüpfen im CMake-Projekt unter Windows Ошибка LNK1104 часто возникает, когда компоновщик не может найти или открыть файл библиотеки. В вашем случае, это файл libboost_locale-vc142-mt-gd-x64-1_74.lib из библиотеки Boost для C+…
Jetzt im Forum diskutieren
J
JacobFib17. Oktober 2024 03:27
добавить qlineseries в функции Пользователь может получить любые разъяснения по интересующим вопросам, касающимся обработки его персональных данных, обратившись к Оператору с помощью электронной почты https://topdecorpro.ru…
JW
Jhon Wick1. Oktober 2024 15:52
Indian Food Restaurant In Columbus OH| Layla’s Kitchen Indian Restaurant If you're looking for a truly authentic https://www.laylaskitchenrestaurantohio.com/ , Layla’s Kitchen Indian Restaurant is your go-to destination. Located at 6152 Cleveland Ave, Colu…
КГ
Кирилл Гусарев27. September 2024 09:09
Не запускается программа на Qt: точка входа в процедуру не найдена в библиотеке DLL Написал программу на C++ Qt в Qt Creator, сбилдил Release с помощью MinGW 64-bit, бинарнику напихал dll-ки с помощью windeployqt.exe. При попытке запуска моей сбилженной программы выдаёт три оши…
F
Fynjy22. Juli 2024 04:15
при создании qml проекта Kits есть но недоступны для выбора Поставил Qt Creator 11.0.2. Qt 6.4.3 При создании проекта Qml не могу выбрать Kits, они все недоступны, хотя настроены и при создании обычного Qt Widget приложения их можно выбрать. В чем может …

Folgen Sie uns in sozialen Netzwerken