【问题标题】:get_or_create failure with Django and Postgres (duplicate key value violates unique constraint)Django 和 Postgres 的 get_or_create 失败(重复键值违反唯一约束)
【发布时间】:2012-03-07 00:47:40
【问题描述】:

感谢您花时间阅读我的问题。

我有一个具有以下型号的 django 应用程序:

class UserProfile(models.Model):
    user = models.OneToOneField(User)
    ...

class Visit(models.Model):
    profile = models.ForeignKey(UserProfile)
    date = models.DateField(auto_now_add=True, db_index=True)
    ip = models.IPAddressField()
    class Meta:
        unique_together = ('profile', 'date', 'ip')

在视图中:

profile = get_object_or_404(Profile, pk = ...)
get, create = Visit.objects.get_or_create(profile=profile, date=now.date(), ip=request.META['REMOTE_ADDR'])
if create: DO SOMETHING

一切正常,除了 Postgres 日志已满且重复键错误:

2012-02-15 14:13:44 CET ERROR:  duplicate key value violates unique constraint "table_visit_profile_id_key"
2012-02-15 14:13:44 CET STATEMENT:  INSERT INTO "table_visit" ("profile_id", "date", "ip") VALUES (1111, E'2012-02-15', E'xx.xx.xxx.xxx') RETURNING "table_visit"."id"

尝试了不同的解决方案,例如

from django.db import transaction 
from django.db import IntegrityError

@transaction.commit_on_success
def my_get_or_create(prof, ip):    
    try:
        object = Visit.objects.create(profile=prof, date=datetime.now().date(), ip=ip)
    except IntegrityError:
        transaction.commit()
        object = Visit.objects.get(profile=prof, date=datetime.now().date(), ip=ip)
    return object

....

created = my_get_or_create(prof, request.META['REMOTE_ADDR'])
if created: DO SOMETHING

这只对 MySQL 有帮助?有谁知道如何避免 postgres 的重复键值错误?

【问题讨论】:

标签: django postgresql


【解决方案1】:

get_or_create() 中出现这些错误的另一个可能原因是其中一个搜索字段中的数据类型不匹配 - 例如,将 False 而不是 None 传递到可空字段。 .get_or_create() 内的 .get() 将找不到它,Django 将继续创建新行 - 由于 PostgreSQL 限制,这将失败。

【讨论】:

  • 感谢您的回答:)
  • 结束了原本让我头疼一上午的事情。
  • 我同意你的观点,当你将查询设置为:obj, created = UserPermission.objects.get_or_create( user=user, boolean_field=boolean_field) 布尔字段为 False 时,它​​总是会尝试创建对象并引发:duplicate key value violates unique constraint,因为你已经定义了@987654328 @
【解决方案2】:

我在使用 postgres 时遇到了 get_or_create 问题。最后我放弃了传统的样板代码:

try:
    jobInvite  = Invite.objects.get(sender=employer.user, job=job)
except Invite.DoesNotExist:
    jobInvite  = Invite(sender=employer.user, job=job)
    jobInvite.save()
# end try

【讨论】:

  • 虽然这个解决方案似乎适用于大多数网站,但它会在大量并发请求在工作的大流量网站上失败。
【解决方案3】:

PostgreSQL 在一些细微查询中的行为有些不同,这会导致IntegrityError 错误,尤其是在您切换到 Django 1.6 之后。这是解决方案 - 您需要为每个失败的模型添加 select_on_save 选项:

class MyModel(models.Model):
     ...
     class Meta:
         select_on_save = True

记录在这里:Options.select_on_save

【讨论】:

  • 如果我在使用 Django 1.4 时遇到完整性错误怎么办?
【解决方案4】:

您是否曾经在 Visit 的个人资料字段中设置了 unique=True?

看起来有一个为 postgres 生成的唯一约束仍然有效。 "table_visit_profile_id_key" 是它自动生成的名称,如果您记录用户的多次访问,自然会导致这些错误。

如果是这种情况,您是否使用South 来管理您的数据库更改?如果你不是,抓住它!

【讨论】:

    猜你喜欢
    • 2012-06-20
    • 2019-03-20
    • 2020-05-28
    • 2016-06-12
    • 2016-11-27
    • 2018-03-14
    • 2012-12-31
    • 2012-03-03
    相关资源
    最近更新 更多