Рубрики
Без рубрики

22% сайтов Django не могут отказаться от подталкивания, благодаря этим 2 ошибкам

Код проверки доктора Django и автоматические фиксирует антиблокировки Django. Мы проверили 666 проектов Django для MIG … Помечено Django, WebDev, Python, программирование.

Django доктор Код проверки и автоматические исправления Django Anti-Paills. Мы проверили 666 проектов Django для миграций, которые не могут быть возвращены и были шокированы, что 22% кодовых база Django имели следующие проблемы :

  • Миграция данных отсутствует обратный обработчик: миграция имеет обработчик для обновления данных, но не для удаления этого изменения. Читать далее
  • Миграция данных Importing “Hot” Модель: Миграция импортирует модель из кодовой базы вместо того, чтобы делать Apps.get_model (...) Отказ Читать далее

Они предотвращают аварийное восстановление. Картина сцена: это 11 вечера и производство падает. Усталый и подчеркнул и вне вариантов вы решили откатиться к последнему хорошему выпуску. Все, что вам нужно, это обратить вспять миграции базы данных, а затем развернуть и … Подожди, что?

$ python manage.py migrate hounds 0002
Unapplying hounds.0003_auto...
Traceback (most recent call last):
django.db.migrations.exceptions.IrreversibleError:
Operation  in hounds.0003_auto is not reversible

Эти блоки возвращаются к последнему хорошему выпуску, потому что состояние базы данных будет вне фазы с последним хорошим кодом: если вы пытались откатиться к старому коду, то состояние базы данных не будет совместимо со старой кодовой базой.

1. Отсутствие обратной миграции

Данные Django Migrations имеют два аспекта: вперед и назад, но по умолчанию миграция скелетных данных, создаваемых Django, только показывает обработчик вперед, и, следовательно, один из пяти кодовых базах Django имеет по меньшей мере одну миграцию, которая не поддерживает отменить миграцию:

def forwards(apps, schema_editor): 
    ...

class Migration(migrations.Migration):
    dependencies = [("cases", "0009_auto_20200320_1210")]
    operations = [migrations.RunPython(forwards)]

К сожалению, это только один пропавший обратный Чтобы все миграции терпят неудачу при попытке отменить миграцию. Человеческая ошибка во время обзора кода может объяснить то, что многие кодовые базы Django не могут оправиться от катастрофы в производстве: если 100% ошибок были замечены 100% времени на 100% кодовых рецензентов, то нам не понадобится обзор кода в Первое место, потому что такие Übermensch не допустили бы ошибку в первую очередь.

Данные Django Migrations требуют вперед, но назад технически необязательно. Хотя вышеизложенное действительно, ниже бесконечно лучше:

def forwards(apps, schema_editor): 
    ...

def backwards(apps, schema_editor):
    ...

class Migration(migrations.Migration):
    dependencies = [("cases", "0009_auto_20200320_1210")]
    operations = [migrations.RunPython(forwards, backwards)]

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

Исправление тоже очень простое: просто указав Миграция. Munpython.noop может быть достаточно. Как подразумевает название, Django будет ничего не делай Для обратного, просто пропустите миграцию данных, не бросая IrrooversibleError :

class Migration(migrations.Migration):
    dependencies = [("cases", "0009_auto_20200320_1210")]
    operations = [migrations.RunPython(forwards, migrations.RunPython.noop)]

Так что на практике следуйте этим советам:

🦊 Вы можете Включить доктор Django На вашем Github Repos защищает от этой проблемы 100% времени.

Импортируя горячую модель

Можете ли вы увидеть проблемы с этой миграцией Django?

from django.db import migrations
from territory import models

def forwards(apps, schema_editor):
    for item in in models.ChickenCoopLocations.objects.all():
        item.has_chickens = does_have_chickens(item.pk)
        item.save()

class Migration(migrations.Migration):
    dependencies = [("cases", "0005_auto_does_have_chickens.py")]
    operations = [migrations.RunPython(forwards)]


def does_have_chickens(pk):
    ...

Это напрямую импортирует из моделей .py. Учитывая достаточно времени и достаточно изменений кода, в конечном итоге в конечном итоге нарушает миграции в качестве кода отклоняется от исторического состояния базы данных, когда была сгенерирована миграция данных.

Не в ногу

Поля в Джанго Models.py должен согласиться с схемой в базе данных. Когда Django выполняет операции по чтению базы данных, он использует форму модели в Models.py Чтобы определить, какие поля к ВЫБРАТЬ и ВСТАВЛЯТЬ . Если Models.py Включает в себя поля, которые еще не в схеме базы данных, база данных бросит ошибку.

Это легко пропущено, если код проверяется во время спешки, потому что когда 0006_populate_has_chickens RAN Эта ошибка не произойдет. Действительно, в этот момент вовремя Models.py делает Согласитесь с схемой, но что происходит, когда через один раз ваш член команды добавляет новое поле в Цыплята ? С этого момента, когда 0006_populate_has_chickens RAN, Models.py У вас будет иметь поле, которое схема базы данных еще не имеет, поэтому миграции потерпят неудачу. Это произойдет при настройке новой базы данных, когда все миграции выполняются с нуля, например, в CI, когда новый разработчик присоединяется к команде, или когда вы заменили свой кирпичный ноутбук.

На будущее

В 0006_populate_has_chickens.py Лучше использовать Apps.get_model , который просит Django построить упрощенную модель, путешествующую временем, чьи поля будут отражать поля в базе данных Даже если Models.py очень выходит из шага с схемой:

# 0006_populate_has_chickens.py
from django.db import migrations

def forwards(apps, schema_editor):
    ChickenCoopLocations = apps.get_model("territory", "ChickenCoopLocations")
    for item in in ChickenCoopLocations.objects.all():
        item.has_chickens = does_have_chickens(item.pk)
        item.save()

class Migration(migrations.Migration):
    dependencies = [("cases", "0005_auto_foo.py")]
    operations = [migrations.RunPython(forwards)]

def does_have_chickens(pk):
    ...

Поэтому непосредственно импортирующие модели в миграциях – Flaky, и в нескольких миграциях время, вероятно, не удастся, потому что во время миграции код в моделях .py не выходит с схемы базы данных: Models.py Может иметь определенное поле, которое еще не существует в базе данных, потому что требуемая миграция еще не работает.

Ваш код Django предотвращает аварийное восстановление?

Со временем легко проскользнуть в вашей кодовой базе. Я могу проверить это для вас в django.doctor или может Просмотрите свой GitHUB PRS :

Или попробуйте Обрабатывающие рефакторинг Django Отказ

Оригинал: “https://dev.to/djangodoctor/22-of-django-websites-can-t-roll-back-prod-thanks-to-these-2-mistakes-4cln”