Поиск…


параметры

Команда django-admin подробности
makemigrations <my_app> Создание миграции для my_app
makemigrations Создание миграций для всех приложений
makemigrations --merge Устранение конфликтов миграции для всех приложений
makemigrations --merge <my_app> my_app конфликтов миграции для my_app
makemigrations --name <migration_name> <my_app> Сформировать миграции для my_app с именем migration_name
migrate <my_app> Применить ожидающие миграции my_app в базу данных
migrate Применить все ожидающие миграции в базу данных
migrate <my_app> <migration_name> Применить или исключить до migration_name
migrate <my_app> zero Не использовать все миграции в my_app
sqlmigrate <my_app> <migration_name> Распечатывает SQL для указанной миграции
showmigrations Показывает все миграции для всех приложений
showmigrations <my_app> Показывает все миграции в my_app

Работа с миграциями

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

Чтобы создать миграцию, выполните:

$ django-admin makemigrations <app_name>

Это создаст файл migration подмодуле migration app_name . Первая миграция будет называться 0001_initial.py , другая начнется с 0002_ , затем 0003 , ...

Если вы опустите <app_name> это создаст миграцию для всех ваших INSTALLED_APPS .

Чтобы распространять миграцию в вашу базу данных, запустите:

$ django-admin migrate <app_name>

Чтобы показать все ваши миграции, запустите:

$ django-admin showmigrations app_name
app_name
  [X] 0001_initial
  [X] 0002_auto_20160115_1027
  [X] 0003_somemodel
  [ ] 0004_auto_20160323_1826
  • [X] означает, что миграция была передана в вашу базу данных
  • [ ] означает, что миграция не была распространена в вашей базе данных. Используйте django-admin migrate для распространения

Вы также вызываете и возвращаете миграцию, это можно сделать, передав имя migrate command . Учитывая приведенный выше список миграций (показано с помощью django-admin showmigrations ):

$ django-admin migrate app_name 0002  # Roll back to migration 0002
$ django-admin showmigrations app_name
app_name
  [X] 0001_initial
  [X] 0002_auto_20160115_1027
  [ ] 0003_somemodel
  [ ] 0004_auto_20160323_1826

Ручная миграция

Иногда миграций, создаваемых Django, недостаточно. Это особенно актуально, если вы хотите выполнить миграцию данных .

Например, давайте иметь такую ​​модель:

class Article(models.Model):
    title = models.CharField(max_length=70)

У этой модели уже есть существующие данные, и теперь вы хотите добавить SlugField :

class Article(models.Model):
    title = models.CharField(max_length=70)
    slug = models.SlugField(max_length=70)

Вы создали миграцию для добавления поля, но теперь вы хотите установить пул для всей существующей статьи в соответствии с их title .

Конечно, вы можете просто сделать что-то подобное в терминале:

$ django-admin shell
>>> from my_app.models import Article
>>> from django.utils.text import slugify
>>> for article in Article.objects.all():
...     article.slug = slugify(article.title)
...     article.save()
...
>>>

Но вам придется делать это во всех своих средах (например, на рабочем столе вашего офиса, на вашем ноутбуке ...), всем вашим коллегам также придется это делать, и вам придется подумать об этом при постановке и при нажатии жить.

Чтобы сделать это раз и навсегда, мы сделаем это в процессе миграции. Сначала создайте пустую миграцию:

$ django-admin makemigrations --empty app_name

Это создаст пустой файл миграции. Откройте его, он содержит базовый скелет. Предположим, что ваша предыдущая миграция была названа 0023_article_slug и она называется 0024_auto_20160719_1734 . Вот что мы напишем в нашем файле миграции:

# -*- coding: utf-8 -*-
# Generated by Django 1.9.7 on 2016-07-19 15:34
from __future__ import unicode_literals

from django.db import migrations
from django.utils.text import slugify


def gen_slug(apps, schema_editor):
    # We can't import the Article model directly as it may be a newer
    # version than this migration expects. We use the historical version.
    Article = apps.get_model('app_name', 'Article')
    for row in Article.objects.all():
        row.slug = slugify(row.name)
        row.save()


class Migration(migrations.Migration):

    dependencies = [
        ('hosting', '0023_article_slug'),
    ]

    operations = [
        migrations.RunPython(gen_slug, reverse_code=migrations.RunPython.noop),
        # We set `reverse_code` to `noop` because we cannot revert the migration
        # to get it back in the previous state.
        # If `reverse_code` is not given, the migration will not be reversible,
        # which is not the behaviour we expect here.
    ]

Поддельные миграции

Когда миграция выполняется, Django сохраняет имя миграции в таблице django_migrations.

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

Если ваше приложение уже имеет модели и таблицы базы данных и не имеет миграций. Сначала создайте начальные миграции для своего приложения.

python manage.py makemigrations your_app_label

Теперь поддельные начальные миграции применимы

python manage.py migrate --fake-initial

Поддельные все миграции во всех приложениях

python manage.py migrate --fake

Поддельные миграции приложений

python manage.py migrate --fake core

Поддельный файл с одной миграцией

python manage.py migrate myapp migration_name

Пользовательские имена для файлов миграции

Используйте параметр makemigrations --name <your_migration_name> чтобы разрешить именовать миграцию (-и) вместо использования сгенерированного имени.

python manage.py makemigrations --name <your_migration_name> <app_name>

Устранение конфликтов миграции

Вступление

Иногда конфликты конфликтуют, в результате чего миграция не выполняется. Это может произойти во множестве scenerio, однако это может происходить на регулярной основе при разработке одного приложения с командой.

Общие конфликты миграции происходят при использовании контроля источника, особенно когда используется метод «функция-ветвь». Для этого сценария мы будем использовать модель Reporter с name и address атрибутов.

Два разработчика на этом этапе собираются разработать функцию, поэтому они оба получат эту исходную копию модели Reporter . Разработчик A добавляет age который приводит к файлу 0002_reporter_age.py . Разработчик B добавляет поле bank_account которое 0002_reporter_bank_account в 0002_reporter_bank_account . Как только эти разработчики объединит свой код и попытаются перенести миграции, возник конфликт миграции.

Этот конфликт возникает, потому что эти миграции изменяют одну и ту же модель, Reporter . Кроме того, новые файлы начинаются с 0002.

Слияние миграций

Есть несколько способов сделать это. В рекомендуемом порядке:

  1. Самое простое решение для этого - запустить команду makemigrations с флагом -merge.

    python manage.py makemigrations --merge <my_app>
    

    Это создаст новую миграцию, разрешающую предыдущий конфликт.

  2. Когда этот дополнительный файл не приветствуется в среде разработки по личным причинам, опция заключается в удалении конфликтующих миграций. Затем новая миграция может быть выполнена с помощью обычной команды makemigrations . Когда пользовательские миграции записываются, например migrations.RunPython , необходимо учитывать этот метод.

Измените CharField на ForeignKey

Прежде всего, давайте предположим, что это ваша первоначальная модель внутри приложения, называемого discography :

from django.db import models

class Album(models.Model):
    name = models.CharField(max_length=255)
    artist = models.CharField(max_length=255)

Теперь вы понимаете, что вместо этого вы хотите использовать ForeignKey для исполнителя. Это несколько сложный процесс, который необходимо выполнить в несколько этапов.

Шаг 1, добавьте новое поле для ForeignKey, убедившись, что он отмечен как null (обратите внимание, что теперь мы подключаем модель):

from django.db import models

class Album(models.Model):
    name = models.CharField(max_length=255)
    artist = models.CharField(max_length=255)
    artist_link = models.ForeignKey('Artist', null=True)

class Artist(models.Model):
    name = models.CharField(max_length=255)

... и создать миграцию для этого изменения.

./manage.py makemigrations discography

Шаг 2, заполните новое поле. Для этого вам нужно создать пустую миграцию.

./manage.py makemigrations --empty --name transfer_artists discography

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

def link_artists(apps, schema_editor):
    Album = apps.get_model('discography', 'Album')
    Artist = apps.get_model('discography', 'Artist')
    for album in Album.objects.all():
        artist, created = Artist.objects.get_or_create(name=album.artist)
        album.artist_link = artist
        album.save()

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

Для первой миграции вы хотите удалить свое исходное поле, artist . Для вашей второй миграции переименуйте новое поле artist_link в artist .

Это делается несколькими шагами, чтобы гарантировать, что Django правильно распознает операции.



Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow