Django
Migraciones
Buscar..
Parámetros
comando django-admin | Detalles |
---|---|
makemigrations <my_app> | Generar migraciones para my_app |
makemigrations | Generar migraciones para todas las aplicaciones. |
makemigrations --merge | Resolver conflictos de migración para todas las aplicaciones. |
makemigrations --merge <my_app> | Resolver conflictos de migración para my_app |
makemigrations --name <migration_name> <my_app> | Genera una migración para my_app con el nombre migration_name |
migrate <my_app> | Aplicar migraciones pendientes de my_app a la base de datos. |
migrate | Aplicar todas las migraciones pendientes a la base de datos. |
migrate <my_app> <migration_name> | Aplicar o no aplicar hasta el nombre de migration_name |
migrate <my_app> zero | Desplegar todas las migraciones en my_app |
sqlmigrate <my_app> <migration_name> | Imprime el SQL para la migración nombrada. |
showmigrations | Muestra todas las migraciones para todas las aplicaciones. |
showmigrations <my_app> | Muestra todas las migraciones en my_app |
Trabajando con migraciones
Django usa migraciones para propagar los cambios que realiza a sus modelos en su base de datos. La mayoría de las veces, django puede generarlos por ti.
Para crear una migración, ejecute:
$ django-admin makemigrations <app_name>
Esto creará un archivo de migración en el submódulo de migration
de app_name
. La primera migración se llamará 0001_initial.py
, la otra comenzará con 0002_
, luego 0003
, ...
Si omite <app_name>
esto creará migraciones para todas sus INSTALLED_APPS
.
Para propagar migraciones a su base de datos, ejecute:
$ django-admin migrate <app_name>
Para mostrar todas sus migraciones, ejecute:
$ django-admin showmigrations app_name
app_name
[X] 0001_initial
[X] 0002_auto_20160115_1027
[X] 0003_somemodel
[ ] 0004_auto_20160323_1826
-
[X]
significa que la migración se propagó a su base de datos -
[ ]
significa que la migración no se propagó a su base de datos. Usadjango-admin migrate
para propagarlo
También puede llamar a revertir migraciones, esto se puede hacer pasando el nombre de la migrate command
. Dada la lista anterior de migraciones (mostrada por 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
Migraciones manuales
A veces, las migraciones generadas por Django no son suficientes. Esto es especialmente cierto cuando desea realizar migraciones de datos .
Por ejemplo, vamos a tener ese modelo:
class Article(models.Model):
title = models.CharField(max_length=70)
Este modelo ya tiene datos existentes y ahora desea agregar un SlugField
:
class Article(models.Model):
title = models.CharField(max_length=70)
slug = models.SlugField(max_length=70)
Usted creó las migraciones para agregar el campo, pero ahora le gustaría establecer la babosa para todos los artículos existentes, de acuerdo con su title
.
Por supuesto, puedes hacer algo como esto en la terminal:
$ 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()
...
>>>
Pero tendrá que hacer esto en todos sus entornos (es decir, en el escritorio de su oficina, en su computadora portátil, ...), todos sus compañeros de trabajo también deberán hacerlo, y tendrán que pensar en ello durante la puesta en escena y al momento de presionar. vivir.
Para hacerlo de una vez por todas, lo haremos en una migración. Primero crea una migración vacía:
$ django-admin makemigrations --empty app_name
Esto creará un archivo de migración vacío. Ábrelo, contiene un esqueleto base. Digamos que su migración anterior se llamó 0023_article_slug
y esta se llama 0024_auto_20160719_1734
. Esto es lo que escribiremos en nuestro archivo de migración:
# -*- 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.
]
Migraciones falsas
Cuando se ejecuta una migración, Django almacena el nombre de la migración en una tabla django_migrations.
Crear y falsificar las migraciones iniciales para el esquema existente.
Si su aplicación ya tiene modelos y tablas de base de datos, y no tiene migraciones. Primero crea migraciones iniciales para tu aplicación.
python manage.py makemigrations your_app_label
Ahora falsas migraciones iniciales según lo aplicado
python manage.py migrate --fake-initial
Falsas todas las migraciones en todas las aplicaciones.
python manage.py migrate --fake
Falsas migraciones de una sola aplicación.
python manage.py migrate --fake core
Fake único archivo de migración
python manage.py migrate myapp migration_name
Nombres personalizados para archivos de migración
Use la makemigrations --name <your_migration_name>
para permitir nombrar las migraciones en lugar de usar un nombre generado.
python manage.py makemigrations --name <your_migration_name> <app_name>
Resolviendo conflictos migratorios.
Introducción
A veces, las migraciones entran en conflicto, lo que hace que la migración no tenga éxito. Esto puede suceder en muchos escenarios, sin embargo, puede ocurrir de manera regular al desarrollar una aplicación con un equipo.
Los conflictos de migración comunes ocurren mientras se usa el control de origen, especialmente cuando se usa el método de característica por rama. Para este escenario, usaremos un modelo llamado Reporter
con el name
y la address
los atributos.
Dos desarrolladores en este punto van a desarrollar una característica, por lo que ambos obtienen esta copia inicial del modelo Reporter
. El desarrollador A agrega una age
que da como resultado el archivo 0002_reporter_age.py
. El desarrollador B agrega un campo bank_account
que da como resultado 0002_reporter_bank_account
. Una vez que estos desarrolladores fusionan su código e intentan migrar las migraciones, se produjo un conflicto de migración.
Este conflicto se produce porque estas migraciones alteran el mismo modelo, Reporter
. Además de eso, los nuevos archivos comienzan con 0002.
Fusionando migraciones
Hay varias maneras de hacerlo. Lo siguiente está en el orden recomendado:
La solución más simple para esto es ejecutar el comando makemigrations con una marca --merge.
python manage.py makemigrations --merge <my_app>
Esto creará una nueva migración para resolver el conflicto anterior.
Cuando este archivo adicional no es bienvenido en el entorno de desarrollo por razones personales, una opción es eliminar las migraciones en conflicto. Luego, se puede hacer una nueva migración usando el comando regular
makemigrations
. Cuando se escriben migraciones personalizadas, comomigrations.RunPython
, se deben tener en cuenta utilizando este método.
Cambiar un campo de caracteres a una clave foránea
En primer lugar, supongamos que este es su modelo inicial, dentro de una aplicación llamada discography
:
from django.db import models
class Album(models.Model):
name = models.CharField(max_length=255)
artist = models.CharField(max_length=255)
Ahora, te das cuenta de que quieres usar una ForeignKey para el artista. Este es un proceso algo complejo, que se debe realizar en varios pasos.
Paso 1, agregue un nuevo campo para ForeignKey, asegurándose de marcarlo como nulo (tenga en cuenta que el modelo al que estamos vinculando también se incluye ahora):
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)
... y crea una migración para este cambio.
./manage.py makemigrations discography
Paso 2, rellena tu nuevo campo. Para hacer esto, tienes que crear una migración vacía.
./manage.py makemigrations --empty --name transfer_artists discography
Una vez que tenga esta migración vacía, desea agregar una sola operación RunPython
para vincular sus registros. En este caso, podría verse algo como esto:
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()
Ahora que sus datos se transfirieron al nuevo campo, podría terminar y dejar todo como está, usando el nuevo campo artist_link
para todo. O, si desea hacer un poco de limpieza, desea crear dos migraciones más.
Para su primera migración, querrá eliminar su campo original, artist
. Para su segunda migración, cambie el nombre del nuevo campo artist_link
a artist
.
Esto se realiza en varios pasos para garantizar que Django reconozca las operaciones correctamente.