You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

自定义Django数据迁移创建allauth EmailAddress记录遇NodeNotFoundError

问题

原本使用Django默认auth系统的项目,通过django.contrib.auth.tokens实现邮箱验证——自定义User模型(继承AbstractUser)的is_active字段初始为False,用户验证邮箱后改为True。

升级到django-allauth后,其他功能正常,但邮箱验证逻辑异常。由于allauth通过EmailAddress模型的verified字段判断邮箱是否已验证,因此编写了自定义数据迁移,将原有用户的is_active状态映射到EmailAddress的verified字段。运行迁移时触发错误:

django.db.migrations.exceptions.NodeNotFoundError: Migration accounts.0003_create_allauth_email_records_for_existing_users dependencies reference nonexistent parent node ('allauth.account', '0002_email_max_length')

自定义迁移文件accounts/migrations/0003_create_allauth_email_records_for_existing_users.py代码:

# Generated by Django 3.2.11 on 2022-12-09 10:56

from django.db import migrations


class Migration(migrations.Migration):

    dependencies = [
        ('accounts', '0002_delete_profile'),
        ('allauth.account', '0002_email_max_length')
    ]

    def create_allauth_email_records_for_existing_users(apps, schema_editor):

        UserModel = apps.get_model("accounts", "User")
        EmailMoldel = apps.get_model("allauth.account", "EmailAddress")

        for user in UserModel.objects.all():
            email_record = EmailMoldel.objects.filter(email=user.email).first()
            
            if email_record == None:

                if user.is_active:
                    email_verified = True
                else:
                    email_verified = False

                new_email = EmailMoldel.objects.create(
                    user = user,
                    email = user.email,
                    verified = email_verified,
                    )
    
    def reverse_func(apps, schema_editor):
        UserModel = apps.get_model("accounts", "User")
        EmailMoldel = apps.get_model("allauth.account", "EmailAddress")

        for email in EmailMoldel.objects.all():
            if not email.primary:
                email.delete()

    operations = [
        migrations.RunPython(
           create_allauth_email_records_for_existing_users, reverse_code= reverse_func
        )
    ]

自定义User模型accounts/models.py代码:

from django.db import models
from django.contrib.auth.models import AbstractUser
from django.utils.translation import gettext_lazy as _

class User(AbstractUser):
    email = models.EmailField(_('email address'), unique=True)

已在INSTALLED_APPS中正确配置allauth相关应用,且不能通过删除迁移或重置数据库解决问题,需修正迁移依赖让Django正确识别allauth.account的迁移节点。


解决方案

1. 确认allauth.account的实际迁移版本

不同版本的django-allauth,其allauth.account的迁移文件编号可能不同。执行命令查看当前环境中allauth.account的可用迁移:

python manage.py showmigrations allauth.account

输出示例:

allauth.account
 [X] 0001_initial
 [X] 0003_username_max_length

根据输出确认存在的迁移节点,比如如果没有0002_email_max_length,则使用0001_initial或其他存在的迁移编号。

2. 修改迁移依赖

将迁移文件的dependencies中的('allauth.account', '0002_email_max_length')替换为实际存在的迁移节点。例如:

dependencies = [
    ('accounts', '0002_delete_profile'),
    ('allauth.account', '0001_initial')
]

3. 完善EmailAddress记录创建逻辑

原代码未设置primary字段,而allauth要求每个用户有一个主邮箱,建议补充该字段:

new_email = EmailMoldel.objects.create(
    user=user,
    email=user.email,
    verified=email_verified,
    primary=True  # 添加主邮箱标记
)

4. 修正拼写错误

原代码中EmailMoldel为拼写错误,建议修正为EmailModel,避免后续维护问题。

5. 重新运行迁移

修改完成后执行:

python manage.py migrate accounts

内容的提问来源于stack exchange,提问作者Del_Wiz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 13:40:26