runpython only one migrations makemigrations inconsistent force exceptions detected createsuperuser changes django django-1.7 django-migrations

only - django runpython



Obtener el modelo ContentType en migraciĆ³n-Django 1.7 (4)

Tengo una migración de datos que actualiza algunos permisos. Sé que hay algunos problemas conocidos con los permisos en las migraciones y pude evitar algunos problemas al crear los permisos en la migración (en lugar de utilizar el acceso directo tupla en el modelo).

La migración:

from __future__ import unicode_literals from django.db import migrations, models from django.conf import settings def create_feature_groups(apps, schema_editor): app = models.get_app(''myauth'') Group = apps.get_model("auth", "Group") pro = Group.objects.create(name=''pro'') Permission = apps.get_model("auth", "Permission") ContentType = apps.get_model("contenttypes", "ContentType") invitation_contenttype = ContentType.objects.get(name=''Invitation'') send_invitation = Permission.objects.create( codename=''send_invitation'', name=''Can send Invitation'', content_type=invitation_contenttype) pro.permissions.add(receive_invitation) class Migration(migrations.Migration): dependencies = [ (''myauth'', ''0002_initial_data''), ] operations = [ migrations.RunPython(create_feature_groups), ]

Después de algunas pruebas y errores, pude hacer que esto funcionara usando manage.py migrate pero recibo errores en la prueba manage.py test .

__fake__.DoesNotExist: ContentType matching query does not exist.

Depurando un poco descubrió que no hay ContentType en este punto de la migración cuando se ejecuta en prueba (no estoy seguro de por qué). Siguiendo los consejos de esta post intenté actualizar manualmente los tipos de contenido en la migración. Adicional :

from django.contrib.contenttypes.management import update_contenttypes update_contenttypes(app, models.get_models())

antes de ir a buscar el tipo de contenido para el modelo de Invitation . Obtuvo el siguiente error

File "C:/Python27/lib/site-packages/django-1.7-py2.7.egg/django/contrib/contenttypes/management.py", line 14, in update_contenttypes if not app_config.models_module: AttributeError: ''module'' object has no attribute ''models_module''

Debe haber alguna forma de crear / actualizar permisos en migraciones de datos de forma comprobable.

Gracias.

EDITAR

Finalmente lo hizo funcionar al agregar

from django.contrib.contenttypes.management import update_all_contenttypes update_all_contenttypes()

Curiosamente, este no era suficiente

update_contenttypes(apps.app_configs[''contenttypes''])

Me encantaría saber por qué todo esto es necesario


Desde que terminé gastando 3-4 horas en esto, estoy agregando mi solución.

El problema era ContentType y los objetos de permiso no se creaban cuando ejecutaba varias migraciones juntas. Dado que estaba haciendo referencia a este tipo de contenido y a la migración en la próxima migración, esto causaba problemas).

Sin embargo, funcionan bien si los ejecuto uno por uno usando el número de migración. (que fueron referenciados en futuras migraciones)

Para resolverlo, agregué una migración adicional para crear ContentType y objetos de permiso.

# -*- coding: utf-8 -*- # Generated by Django 1.10.6 on 2017-03-11 05:59 from __future__ import unicode_literals from django.conf import settings from django.db import migrations def update_all_contenttypes(**kwargs): from django.apps import apps from django.contrib.contenttypes.management import update_contenttypes for app_config in apps.get_app_configs(): update_contenttypes(app_config, **kwargs) def create_all_permissions(**kwargs): from django.contrib.auth.management import create_permissions from django.apps import apps for app_config in apps.get_app_configs(): create_permissions(app_config, **kwargs) def forward(apps, schema_editor): update_all_contenttypes() create_all_permissions() def backward(apps, schema_editor): pass class Migration(migrations.Migration): dependencies = [ migrations.swappable_dependency(settings.AUTH_USER_MODEL), (''contenttypes'', ''0002_remove_content_type_name''), (''MY_APP'', ''0123_LAST_MIGRATION''), ] operations = [ migrations.RunPython(forward, backward) ]


La respuesta es:

apps.get_model (''contenttypes'', ''ContentType'') :) Lo necesitaba yo mismo hoy.


Tener un problema similar al escribir una migración de datos que abarca varias aplicaciones. Resulta que Django solo carga esos modelos en el registro de la aplicación que se ven afectados por lo que dice el miembro de "dependencias" de la migración: https://code.djangoproject.com/ticket/24303

Tuve que, básicamente, agregar una entrada a las dependencias de migración que uso que no está directamente relacionada, por ejemplo, una ForeignKey con la aplicación que se está migrando actualmente.


update_contenttypes(apps.app_configs[''contenttypes''])

actualizará los tipos de contenido de la aplicación de tipos de contenido.

Creo que querrías hacer esto ...

update_contenttypes(apps.app_configs[''app_label''])

donde app_label es la etiqueta de la aplicación para la que vive el modelo de invitación. Esto actualizará los tipos de contenido de su aplicación individual para que esté disponible para consultas según su código original.