【问题标题】:Guardian and custom user model: IntegrityError on migration, creating anonymous userGuardian 和自定义用户模型:迁移时的 IntegrityError,创建匿名用户
【发布时间】:2018-03-21 13:20:45
【问题描述】:

我有这个模型文件,其中定义了自定义用户。

class CustomUser(AbstractBaseUser,PermissionsMixin, GuardianUserMixin):
    email = models.EmailField(max_length=50,
            verbose_name='email address', unique=True)
    first_name    = models.CharField('first name', max_length=15,blank=False)
    last_name     = models.CharField('last name', max_length=15,blank=True)
    date_joined   = models.DateTimeField('date joined', auto_now_add=True)
    slug          = models.SlugField('slug', max_length=50, unique=True, null=True) 
    is_active     = models.BooleanField('active',default=True)


    objects = UserManager()

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = []


    class Meta:
    app_label = "latiro_app"
    db_table =  "users"


        permissions = (
                ("view_user", "view User"),
                ("edit_profile", "Edit Profile"),
                )


    def get_full_name(self):
        full_name = '{0} {1}'.format(self.first_name, self.last_name)
        return full_name.strip()

    def get_short_name(self):
        return self.first_name


    def generate_user_slug(self):
        max_length = CustomUser._meta.get_field('slug').max_length
        full_name = self.get_full_name()
        slug = original = slugify(full_name)[:max_length]

        for i in itertools.count(1):
            if not CustomUser.objects.filter(slug=slug).exists():
                break

            slug = '{0}-{1}' .format(original[:max_length - len(str(i)) - 1], i)
        return slug


    def save(self, *args, **kwargs):
        if not self.slug:
            self.slug = self.generate_user_slug()
        super().save()         


def get_anonymous_user_instance(CustomUser):
    return CustomUser(first_name='Anonymous')


class Profile (models.Model):
    user            = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete= models.CASCADE,
                                    null=False, verbose_name='list of users')
    phone_regex   = RegexValidator(regex=r'^\+?1?\d{9,15}')
    phone_number  = models.CharField('phone number', validators=[phone_regex], max_length=50, blank=True)
    country         = models.CharField(max_length=50,blank=True)
    province        = models.CharField(max_length=50)
    city            = models.CharField(max_length=50,blank=True)
    profile_picture = models.ImageField(upload_to='user_profile/%y/%m/%d/', blank=True)
    followers       = models.IntegerField(default=0, null=True)
    following       = models.IntegerField(default=0, null=True)

还有这个信号

def create_user_profile(sender, instance, created, **kwargs):

    if kwargs.get('created', True) and not kwargs.get('raw', False):
        profile = Profile(user=instance)
            profile.save()

post_save.connect(create_user_profile,
              sender = settings.AUTH_USER_MODEL)

当运行第一次迁移时,Django 将我的应用程序很好地迁移到数据库中。但是当我第二次运行迁移时,Django 会抛出这个错误:

django.db.utils.IntegrityError: (1062, "Duplicate entry '' for key '电子邮件'”)。

我正在使用 MySQL。这里出了什么问题?

更新:当我进行第二次迁移时,我发现了引发错误的代码。

我的模型文件中有这段代码:

def get_anonymous_user_instance(CustomUser):
    return CustomUser(first_name='Anonymous')

我将此功能导入到我的设置中,这样当我第一次进行迁移时,将创建匿名用户。并且它确实按预期进行。但是当我再次运行迁移时,django 尝试创建另一个匿名用户,这就是我收到此错误的原因。

当我在我的设置中注释掉这一行时:

" GUARDIAN_GET_INIT_ANONYMOUS_USER = 'latiro_app.models.get_anonymous_user_instance' "

我没有看到这个错误。

【问题讨论】:

  • 显然您正在使用空的email 创建用户,并且由于它是唯一的,因此在添加第二个用户时会失败。如果没有更多关于如何创建用户的详细信息,很难说出它是如何发生的,尤其是在迁移中。
  • 我正在使用 django abstractbaseuser 创建一个自定义用户,我在上面发布了我的代码
  • 您发布了定义用户的代码,但没有发布您实际使用它的方式。您需要确保email 字段不为空。
  • 原谅我,伙计,我的目的是在注册时使用我在上面发布的自定义用户模型创建一个用户,然后使用 Prpfile 模型类编辑用户配置文件与自定义用户类具有一对一的关系。
  • 上面的代码有效,我可以创建用户和超级用户,但是当我想运行我的应用程序的第二次迁移时问题就来了。

标签: mysql django django-guardian


【解决方案1】:

email 是一个唯一字段,因此不能有两个 CustomUsers 具有相同的 e-mail。 Guardian 正在从 GUARDIAN_GET_INIT_ANONYMOUS_USER 设置中的可调用对象返回的对象创建一个新用户,因此它尝试创建相同的用户并失败。您可以使用get_or_create 解决此问题:

def get_anonymous_guardian_user_instance(CustomUser):
    user, _ = CustomUser.objects.get_or_create(
        first_name='Anonymous',
        email='guardian@example.com',
    )
    return user

实际上有一个Guardian issue 关于这个,但不幸的是它没有解决,也不清楚它是否应该是一个问题。文档cautions the user about syncdb,但在我看来,在section about creating anonymous users(它不处理unique 约束)中,可调用对象应该返回什么并不是很清楚。

【讨论】:

  • 感谢您的耐心配合。我试过了,但在运行迁移时我仍然遇到同样的错误。
  • 我删除了我之前的评论,因为同时我看到有一张关于这个的票,我更新了答案。
  • 我认为最新的编辑应该没有变通办法。
  • 奥布里甘多·伊尔茂。它有效,不再有冲突。 “get_or_create”对此很神奇。这行:“return CustomUser(first_name='Anonymous', email='guardian@example.com')”真的让我蒙蔽了双眼。我没有意识到这会导致 django Guardian 执行保存到静态等待保存的实例。
  • 没错,如果你返回一个新创建的CustomUser 给 Guardian,它只会save 它并尝试用它创建一个新对象。这在 Guardian 文档中不是很清楚。他们提醒用户注意syncdb(这可能是很久以前的事了),但他们没有确切说明您返回的实例将做什么。我原以为他们会自己做类似get_or_create 的事情,但他们没有。
猜你喜欢
  • 2016-03-19
  • 1970-01-01
  • 2017-08-05
  • 2019-10-17
  • 2021-05-06
  • 2018-12-12
  • 2015-08-20
  • 1970-01-01
相关资源
最近更新 更多