从South迁移到Django 1.7迁移:可交换依赖

时间:2015-02-11 20:20:12

标签: django django-migrations

我有一个用Django 1.6编写的项目,它使用South迁移,我试图将它移动到Django 1.7。所以我从指示here的说明开始。

  1. 已从south删除INSTALLED_APPS
  2. 删除了旧的迁移文件。
  3. ./manage.py makemigrations
  4. 此时我得到django.db.migrations.graph.CircularDependencyError

    以下是我的模特:

    customer.models.py

    class Customer(models.Model):
        name = models.CharField(
            max_length=128,
        )
    
    class Department(models.Model):
        customer = models.ForeignKey(
            'customer.Customer',
            related_name='departments',
        )
        name = models.CharField(
            max_length=64,
        )
    
    class Representative(models.Model):
        user = models.ForeignKey(
            'userprofile.User',
            related_name='representatives',
        )
        department = models.ForeignKey(
            'customer.Department',
            related_name='representatives',
        )
    

    userprofile.models.py

    class User(AbstractBaseUser, PermissionsMixin):
        customers = models.ManyToManyField(
            'customer.Customer',
            blank=True,
            null=True,
        )
    

    customer应用程序的初始迁移中导致了一个可交换的依赖项:

    dependencies = [
        migrations.swappable_dependency(settings.AUTH_USER_MODEL),
    ]
    

    根据建议here,我编辑了userprofile的初始迁移以及与客户相关的评论行:

    class Migration(migrations.Migration):
    
        dependencies = [
            ('auth', '0001_initial'),
            #('customer', '0001_initial'),
        ]
    
        operations = [
            migrations.CreateModel(
                name='User',
                fields=[
                    ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
                    ('first_name', models.CharField(max_length=128, error_messages={b'min_length': 'El campo "Nombres" debe tener al menos %(limit_value)d caracteres (actualmente tiene %(show_value)d).'}, verbose_name='nombres', validators=[django.core.validators.MinLengthValidator(3)])),
                    ('last_name', models.CharField(max_length=128, error_messages={b'min_length': 'El campo "Apellidos" debe tener al menos %(limit_value)d caracteres (actualmente tiene %(show_value)d).'}, verbose_name='apellidos', validators=[django.core.validators.MinLengthValidator(3)])),
                    ('email', models.EmailField(unique=True, max_length=75, verbose_name='correo electr\xf3nico')),
                    #('customers', models.ManyToManyField(to='customer.Customer', null=True, verbose_name='clientes relacionados', blank=True)),
                ],
                bases=(models.Model,),
            ),
        ]
    

    运行./manage.py migrate并创建另一个添加客户字段的迁移:

    class Migration(migrations.Migration):
    
        dependencies = [
            ('customer', '0001_initial'),
            ('userprofile', '0001_initial'),
        ]
    
        operations = [
            migrations.AddField(
                model_name='user',
                name='customers',
                field=models.ManyToManyField(to='customer.Customer', null=True, verbose_name='clientes relacionados', blank=True),
                preserve_default=True,
            ),
        ]
    

    但是当我运行./manage.py migrate userprofile --fake时,我收到错误

    Running migrations:
      No migrations to apply.
      Your models have changes that are not yet reflected in a migration, and so won't be applied.
      Run 'manage.py makemigrations' to make new migrations, and then re-run 'manage.py migrate' to apply them.
    

    另一方面,如果没有此迁移,我的测试将失败:

    OperationalError: no such table: userprofile_user_customers
    

1 个答案:

答案 0 :(得分:2)

我的错误是运行./manage.py makemigrations userprofile,而不是运行./manage.py makemigrations userprofile --empty。在第一种情况下,Django将其理解为添加contracts字段的迁移(对于第二种情况),对于第二种情况,如果我运行./manage.py migrate userprofile则失败并显示:

django.db.utils.ProgrammingError: relation "userprofile_user_customers" already exists

所以我不得不:

  1. 复制上次迁移的内容:

    class Migration(migrations.Migration):
    
        dependencies = [
            ('customer', '0001_initial'),
            ('userprofile', '0001_initial'),
        ]
    
        operations = [
            migrations.AddField(
                model_name='user',
                name='customers',
                field=models.ManyToManyField(to='customer.Customer', null=True, verbose_name='clientes relacionados', blank=True),
                preserve_default=True,
            ),
        ]
    
  2. 删除该迁移。

  3. 运行./manage.py makemigrations userprofile --empty
  4. 粘贴并运行./manage.py migrate userprofile --fake