从Django用户模型迁移到自定义用户模型

41

我正在遵循这两个参考资料(onetwo),以创建自定义用户模型,以便通过电子邮件进行身份验证,并添加一个额外的字段。

class User(AbstractBaseUser, PermissionsMixin):
    email = models.EmailField(
        unique=True,
        max_length=254,
    )
    mobile_number = models.IntegerField(unique=True)
    is_active = models.BooleanField(default=True)
    is_admin = models.BooleanField(default=False)

    objects = UserManager()
    ...
    ...    
    class Meta:
        db_table = 'auth_user'
    ...
    ...

正如你所看到的,我已将db_table='auth_user'添加到类的元字段中。此外,我在settings.py中将AUTH_USER_MODEL = 'accounts.User'和用户模型应用程序(即accounts)添加到了INSTALLED_APPS中。此外,我还从应用程序中删除了迁移文件夹。

然后尝试进行迁移:

$ python manage.py makemigrations accounts
Migrations for 'accounts':
  accounts/migrations/0001_initial.py:
    - Create model User

$ python manage.py migrate accounts

这给了我一个错误:

django.db.migrations.exceptions.InconsistentMigrationHistory: Migration admin.0001_initial 在其依赖 accounts.0001_initial 之前应用于数据库 'default'。

如何从现有的 Django 用户模型迁移到自定义用户模型?


2
你清除过 django_migrations 表内的旧条目吗? - nik_m
3
清空它。只为确保你有一个全新的数据表。之后运行makemigrations然后再次迁移。 - nik_m
1
@nik_m 我没有清空数据库。实际上,数据库中有一些数据。难道没有其他方法可以迁移而不删除数据库吗? - Kakar
@nik_m 不,我不知道如何截断 django_migrations。这是否意味着要这样做 User.objects.all().delete() - Kakar
不,完全不是。这是“用户”表。我不是在谈论那个。我在谈论名为“django_migrations”的表。你使用的是PostgreSQL吗? - nik_m
显示剩余6条评论
12个回答

45

您需要清除迁移历史中的 admin,auth,contenttypes 和 sessions,并删除这些表。首先,删除应用程序的迁移文件夹,然后键入以下内容:

python manage.py migrate admin zero
python manage.py migrate auth zero
python manage.py migrate contenttypes zero
python manage.py migrate sessions zero

随后,您可以运行makemigrations accountsmigrate accounts


43

解决方法是撤销依赖于AUTH_USER_MODEL的现有迁移,如此答案中所述。如果您尝试撤销管理、认证、内容类型和会话的迁移,并出现以下错误:

错误信息: auth.User.groups: (fields.E304) Reverse accessor for 'User.groups' clashes with reverse accessor for 'Profile.groups'. ....

  • 首先,在settings.py文件中注释掉/撤销A UTH_USER_MODEL,如果您已经更改了它。
  • 其次,在settings.py文件中从INSTALLED_APPS中注释掉/撤销包含新AUTH_MODEL的Django应用程序。
  • 现在,您应该能够撤销auth、admin、contenttypes和sessions的迁移,如下所示:
python manage.py migrate admin zero
python manage.py migrate auth zero
python manage.py migrate contenttypes zero
python manage.py migrate sessions zero
  • 现在将您的认证模型应用程序添加到 INSTALLED_APPS 中,并再次在您的 settings.py 中设置 AUTH_USER_MODEL
  • 运行:python manage.py migrate AUTH_APP,您可能还需要为您的认证模型应用程序进行迁移:python manage.py makemigrations AUTH_APP

  • 通过以下方式应用您撤消的所有迁移:python manage.py migrate

您已经全部完成了。

注意: 您将失去数据库中存在的所有现有用户。


1
这是正确的答案,因为它保留了现有的数据。 - infiniteloop

9
在我的情况下,其他答案没有帮助(即使我尝试使用“迁移...零”删除表并删除迁移文件夹后,错误仍然发生),以下内容有所帮助,但我还处于非常初步的阶段,因此删掉在第一次迁移时创建的“db.sqlite3”文件并不成问题(根据您的settings.py,您可能有一个不同的数据库文件)。
只有在您确定不会丢失重要数据(例如,您尚未在数据库中存储大量信息,并且重新开始不是很困难)时才能这样做,并且您需要再次进行迁移。

5

从数据库中删除所有现有的表格。[注意:数据将会丢失]

从所有应用程序中删除pycache和migrations。

为您的相关应用程序运行迁移。

python manage.py makemigrations users

将表迁移到数据库
python manage.py migrate

4

在您之前的迁移后,您的数据库中有一个django_migrations表,这是不一致的原因。

解决方案:从您的数据库中删除django_migrations表。 从您的应用程序中删除迁移文件夹。

然后执行相应操作。

python3 manage.py makemigrations 
python3 manage.py migrate

4

你需要执行:

python manage.py makemigrations accounts

在执行初始的 manage.py migrate 之前(初始指在您的项目上第一次运行migrate时),建议您在项目开始时设置自定义用户模型,这样您就可以在创建管理员、授权、内容类型和会话表的同时迁移“账户”应用程序。
但是,如果您已经创建了您的表格,则应按照@krishna-chandak的说明进行操作:https://dev59.com/xFgQ5IYBdhLWcg3wazS_#53599345 您可以阅读文档:https://docs.djangoproject.com/en/2.0/topics/auth/customizing/#using-a-custom-user-model-when-starting-a-project

3

1

我找到的解决方案是从这里提供的不同解决方案中拼凑出来的。

我检查数据库是否存在,因为我只有在数据库为空时才会遇到问题,而对于已存在的数据库没有问题。

# check if the database exists
db_ok=false
if python ./manage.py check; then
  db_ok=true
fi

if [ $db_ok = true ]; then
  # database exists: do a normal migrate
  python ./manage.py migrate
else
  # database does not exists, make and migrate users then a migrate and cleanup of the users migraton
  python ./manage.py makemigrations users
  python ./manage.py migrate users
  python ./manage.py migrate
  rm -r users/migrations/
fi

1
我也遇到了同样的问题。我按照以下步骤进行操作:
  1. models.py 中,我设置了基本的 User 模型。
# accounts/models.py
class User(AbstractBaseUser):
    class Meta:
        db_table = 'auth_user'
  1. 接着,我运行了makemigrations命令来生成迁移文件。
$ python manage.py makemigrations accounts
Migrations for 'accounts':
  accounts/migrations/0001_initial.py:
    - Create model User
  1. 下一步,我将记录0001_initial插入到django_migrations表中。
$ echo "INSERT INTO django_migrations (app, name, applied) VALUES ('accounts', '0001_initial', CURRENT_TIMESTAMP);" | python manage.py dbshell
  1. 更新模型中的最新内容
# accounts/models.py
class User(AbstractBaseUser, PermissionsMixin):
    email = models.EmailField(
        unique=True,
        max_length=254,
    )
    mobile_number = models.IntegerField(unique=True)
    is_active = models.BooleanField(default=True)
    is_admin = models.BooleanField(default=False)

    objects = UserManager()
    ...
    ...    
    class Meta:
        db_table = 'auth_user'
    ...
    ...
  1. 我需要再次执行makemigrations

运行makemigrations之后,我得到了下一个迁移文件。

0002_....py
  1. Migrate agains
python manage.py migrate.

0

我曾经遇到过类似的问题,即在项目进行中间阶段引入自定义用户模型。以下步骤帮助我解决了这个问题,而不需要删除表格或数据丢失。

(1) 为应用程序(“账户”)创建一个初始的空迁移。

python manage.py makemigrations accounts --empty

(2) 运行迁移

python manage.py migrate

(3)在数据库的django_migrations表中更新时间戳,将“accounts”初始迁移更新为“admin”初始时间戳。

UPDATE django_migrations SET applied=<<admin 0001_initial date>> WHERE app='accounts' and name='0001_initial'; 

(4)现在创建您的自定义用户模型(派生自AbstractUser),不需要任何字段,并将表名设置为auth_user。您基本上正在重用数据库中现有的auth用户表。
class User(AbstractUser):
    class Meta:
        db_table = 'auth_user'

(4) 現在運行遷移,並將遷移複製到 0001_initial,從依賴數組中刪除 '0001_initial'。同時刪除新建的遷移文件。

python manage.py makemigrations accounts
cp accounts/migrations/0002_user.py accounts/migrations/0001_initial.py
edit the file 0001_initial.py
rm accounts/migrations/0002_user.py  (remove migration file)

(5) 现在添加自定义字段,按照惯例运行makemigrations并迁移。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接