09.05.2019       Выпуск 281 (06.05.2019 - 12.05.2019)       Статьи

Django. Перемещение моделей из одного приложения в другое

Читать>>




Экспериментальная функция:

Ниже вы видите текст статьи по ссылке. По нему можно быстро понять ссылка достойна прочтения или нет

Просим обратить внимание, что текст по ссылке и здесь может не совпадать.

Хотелось бы поделиться одним из возможных вариантов перемещения модели данных из одного приложения в другое.

Сразу отмечу, что данный вариант переноса модели данных не является стопроцентно рабочим и может понадобиться дополнительное ручное редактирование таблиц для правильной установки Content Type. Поскольку любые подобные модификации чреваты потерей данных для GenericForeignKey отношений.

В моём случае GenericForeignKey не использовались, поэтому такой проблемы не возникло.

Исходные данные

Допустим, у вас имеется старое приложение article, в котором есть модель Article. Вам нужно создать приложение blog и перенести модель Article в данное приложение. Используется база данных PostgreSQL.

Перемещение модели

  1. Сделать резервную копию базы данных (backup), можете сделать дамп базы данных и потренироваться на данном дампе на development сервере.

  2. Перенести код модели Article из article.models.py в blog.models.py . То есть код из старой модели необходимо удалить.

  3. Отредактировать класс Meta в модели Article , чтобы сохранить старое название таблицы. В данном случае оно было article_artilce

    class Meta:
          db_table = 'article_article'
  4. Изменить все ссылки на модели данных во всём проекте. Это означаете поменять все импорты и ForeignKey .

  5. Создать миграции для обоих приложений в следующем порядке

    python manage.py makemigrations blog
      python manage.py makemigrations article
  6. Применить миграции в режиме фейка. Это позволит добавить миграции как применённые, но при этом никаких изменений производиться не будет.

    python manage.py migrate --fake
    В данный момент база данных будет уязвима в том плане, что не был создан Content Type для вашей перенесённой модели данных.
  7. Исправить это можно будет следующими действиями. Нужно теперь поменять имя таблицы, а сделать это можно будет удалением db_table из модели данных и созданием и применением новой миграции к новому приложению. Content Type будет создан автоматически при применении миграции.

    python manage.py makemigrations blog
      python manage.py migrate

По сути после этих действий база данных будет рабочей, а данные будут сохранены. Но могут понадобиться дополнительные действия для корректировки базы данных.

Чистка базы данных и корректировка

В зависимости от того, где и как использовалась перенесённая модель данных. Могут понадобиться те или иные действия. Например корректировка Content Type для GenericForeignKey .

У меня был наиболее простой случай - это удаление старых Content Type . Для этого нужно подключиться к базе данных и удалить информацию из всех таблиц, которые могут ссылаться на Content Type старой модели.

Такими таблицами могут быть:

  • auth_user_user_permissions
  • auth_permission
  • django_content_type
  • и т.д. остальные модели, в которых могли использоваться старые модели до переноса

Я покажу на примере старых Content Type из своей базы данных.

Процесс чистки

  1. Подключимся к базе данных
    sudo -u postgres psql
      \c myprojectdb
  2. Посмотрим таблицу django_content_type, чтобы понять, какие id имеют устаревшие Content Type.

    SELECT * FROM django_content_type;
    Вывод таблицы
    id |    app_label     |         model         
      ----+------------------+-----------------------
       1 | accounts         | userprofile
       2 | knowledge        | section
       3 | knowledge        | article
       4 | admin            | logentry
       5 | auth             | permission
       6 | auth             | group
       7 | auth             | user
       8 | contenttypes     | contenttype
       9 | sessions         | session
  3. Найдя старые id можем попытаться их удалить (Например 50 и 51)

    DELETE FROM django_content_type WHERE id BETWEEN 50 AND 51;
  4. Если не получилось, то нужно найти, где используются данные ID. В ошибке будет указано, в каких таблицах они задействованы. В моём случае это были auth_permission и auth_user_user_permissions.

    SELECT * FROM auth_permission WHERE content_type_id BETWEEN 50 AND 51;
    Вывод таблицы
    id  |        name        | content_type_id |    codename    
      -----+--------------------+-----------------+----------------
      154 | Can add chat       |              50 | add_chat
      155 | Can change chat    |              50 | change_chat
      156 | Can delete chat    |              50 | delete_chat
      157 | Can add message    |              51 | add_message
      158 | Can change message |              51 | change_message
      159 | Can delete message |              51 | delete_message
      276 | Can view Chat      |              50 | view_chat
      277 | Can view Message   |              51 | view_message
    Далее ищем интересующие id в auth_user_user_permissions
    SELECT * FROM auth_user_user_permissions WHERE permission_id=154;
    Вывод
    id  | user_id | permission_id
      -----+---------+---------------
      102 |       2 |           154
  5. Удаляем из таблицы auth_user_user_permissions все permission для старого Content Type.

    DELETE FROM auth_user_user_permissions WHERE permission_id=154;
  6. Удаляем из таблицы auth_permission сами permission.

    DELETE FROM auth_permission WHERE content_type_id BETWEEN 50 AND 51;
  7. Удаляем Content Types.

    DELETE FROM django_content_type WHERE id BETWEEN 50 AND 51;

Заключение

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

Для Django рекомендую VDS-сервера хостера Timeweb .






Разместим вашу рекламу

Пиши: mail@pythondigest.ru

Нашли опечатку?

Выделите фрагмент и отправьте нажатием Ctrl+Enter.

Система Orphus