为什么初始迁移具有依赖性?

时间:2018-06-28 14:01:30

标签: django database-migration

我没有进行任何先前的迁移,而是在 core 应用程序中添加了自定义 User 模型,以通过遵循文档条目Django 2.0 / Customizing authentication in Django

启用自定义身份验证。

然后我进行了迁移:

$ python manage.py makemigrations

Migrations for 'core':
  core/migrations/0001_initial.py
    - Create model User

0001_initial.py,迁移课程始于:

class Migration(migrations.Migration):

    initial = True

    dependencies = [
        ('auth', '0009_alter_user_last_name_max_length'),
    ]

我浏览了官方文档Django 2.0 / Migrations,由于该文件具有initial = True,因此显然是初始迁移。但是为什么它具有从0009_alter_user_last_name_max_length开始的整个依赖链?我做错了吗?

运行迁移时,这是输出:

$ python manage.py migrate  
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, core, sessions
Running migrations:
  Applying contenttypes.0001_initial... OK
  Applying contenttypes.0002_remove_content_type_name... OK
  Applying auth.0001_initial... OK
  Applying auth.0002_alter_permission_name_max_length... OK
  Applying auth.0003_alter_user_email_max_length... OK
  Applying auth.0004_alter_user_username_opts... OK
  Applying auth.0005_alter_user_last_login_null... OK
  Applying auth.0006_require_contenttypes_0002... OK
  Applying auth.0007_alter_validators_add_error_messages... OK
  Applying auth.0008_alter_user_username_max_length... OK
  Applying auth.0009_alter_user_last_name_max_length... OK
  Applying core.0001_initial... OK
  Applying admin.0001_initial... OK
  Applying admin.0002_logentry_remove_auto_add... OK
  Applying sessions.0001_initial... OK

省略自定义 User 模型时,0001_initial.py开头为:

class Migration(migrations.Migration):

    initial = True

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

此外,我无法很好地解释migrations.swappable_dependency(settings.AUTH_USER_MODEL)的功能。它是做什么的,为什么它甚至被称为“ swappable_dependency”?如果有人也能为我揭开这部分的神秘面纱,或者指出正确的方向自行探索,那将是很好的。

编辑#1

自定义 User 模型的源代码。

class UserManager(BaseUserManager):
    def create_user(self, email, password=None):
        if not email:
            raise ValueError('Email not defined.')

        user = self.model(email=self.normalize_email(email))

        user.set_password(password)
        user.save(using=self._db)
        return user

    def create_superuser(self, email, password):
        user = self.create_user(
            email,
            password=password,
        )
        user.is_staff = True
        user.save(using=self._db)
        return user


class User(AbstractBaseUser, PermissionsMixin):
    email = models.EmailField(unique=True)
    created_at = models.DateTimeField(auto_now_add=True)
    is_staff = models.BooleanField(default=False)
    is_active = models.BooleanField(default=True)

    EMAIL_FIELD = 'email'
    USERNAME_FIELD = 'email'

    objects = UserManager()

    def __str__(self):
        return self.email

    def has_perm(self, perm, obj=None):
        return True

    def has_module_perms(self, app_label):
        return True

1 个答案:

答案 0 :(得分:1)

这是正常现象,是正常现象-您仍然需要将django.contrib.auth的迁移应用于您的数据库。

如果您look at those migrations ,它们将包含身份验证应用所需的其他各种模型-例如PermissionGroupUser模型的字段引用了其他模型,因此您需要进行迁移才能首先设置这些模型。

由于User是可交换的依赖项,因此Django将忽略User应用中的auth迁移,而改为使用您的应用。但是所有其他auth模型的迁移都将从auth.migrations开始应用。

正是由于对auth迁移的这种依赖性,所以very difficult to change是您自定义项目后的{{3}}自定义用户模型:

  

由于Django的可转换模型具有动态依赖功能,因此AUTH_USER_MODEL所引用的模型必须在其应用的首次迁移(通常称为0001_initial)中创建;否则,您将遇到依赖性问题。