【发布时间】:2014-06-05 14:35:55
【问题描述】:
我正在测试一个小应用程序,我在其中扩展了用户模型以添加一些附加信息。用户可以通过 django-allauth (google OAuth2) 很好地注册,并将条目添加到他们的数据库中。
class LabUser(models.Model):
user = models.OneToOneField(User)
verified = models.BooleanField(default=False, blank=False)
phone_number = models.CharField(max_length=30, verbose_name="Phone Number", null=True, blank=True)
home_phone = models.CharField(max_length=30,verbose_name="Home Phone", null=True, blank=True)
def __unicode__(self):
return self.user.username
但是,当我尝试使用 django-admin 面板添加另一个用户时,我收到以下数据库错误:
IntegrityError: duplicate key value violates unique constraint "lab_manager_labuser_user_id_key"
DETAIL: Key (user_id)=(24) already exists.
检查 psql 中的表后,我看到以下内容:
l=# select id, username from auth_user;
id | username
----+----------------
13 | xxxx
23 | xxxx
18 | xxxx
12 | xxxx
21 | xxxx
14 | xxxx
22 | xxxx
1 | xxxx
(8 rows)
l=# select id, user_id from lab_manager_labuser;
id | user_id
----+---------
9 | 13
1 | 1
16 | 18
8 | 12
10 | 14
21 | 21
22 | 22
23 | 23
(8 rows)
查看我的序列表,我可以看到这些值高于它们各自的模型表中的值:
l=# SELECT sequence_name, last_value FROM auth_user_id_seq;
sequence_name | last_value
------------------+------------
auth_user_id_seq | 24
(1 row)
l=# SELECT sequence_name, last_value FROM lab_manager_labuser_id_seq;
sequence_name | last_value
----------------------------+------------
lab_manager_labuser_id_seq | 25
(1 row)
我查看了this 类似的问题,但找不到在我的情况下应该发生这种冲突的原因。这两个序列似乎都领先于我表中的值。
即我尝试了以下方法,虽然它增加了我的密钥,但它仍然会导致所谓的完整性错误,而这些密钥显然不存在于数据库中。
SELECT setval('lab_manager_labuser_id_seq', (SELECT MAX(user_id) from lab_manager_labuser)+1)")
任何帮助将不胜感激。
更新:
我设置了一个接收器来创建一个labuser模型,如下所示,也许我这样做不正确,导致数据库不匹配:
@receiver(post_save, sender=User)
def add_labuser(sender, created, instance, **kwargs):
if created:
LabUser.objects.create(user=instance)
我认为这一定是问题的一部分,因为我可以在 shell 中使用以下代码成功创建用户对象:
a = User()
##(add fields)##
a.save()
LabUser.objects.create(user=a)
重复键错误发生的原因是因为我通过管理面板添加用户,内联如下:
class LabUserInline(admin.StackedInline):
model = LabUser
can_delete = False
显然,当通过 Admin 创建用户时,会在调用 save 之前通过内联自动创建 LabUser 记录。然后当接收到 post_save 信号时,django 会尝试为同一个 User 对象创建另一个 LabUser 记录,在该记录上发生键冲突。
有人知道如何规避这种冗余吗?
【问题讨论】:
-
看来这个问题的原因不在贴出的代码中。我猜
lab_manager_labuser被插入了两次,导致了这个问题。没有user_id=24的条目让我认为您正在使用事务并且错误时所有内容都会回滚。 -
我认为您正在做一些事情,但这似乎也与我在创建新用户时保存连接的 LabUser 对象的方式有关。我意识到我实际上可以从外壳创建对象。在@ElmoVanKielmo 上方查看我的更新
-
您更新中的代码是有意义的,应该不会导致这个问题...
-
@ElmoVanKielmo 进行了更新。任何建议表示赞赏。
标签: python database django postgresql django-allauth