Django和Postgres的get_or_create失败(重复键值违反了唯一约束)

Bar*_*rmi 9 django postgresql

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

我有一个带有以下型号的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')
Run Code Online (Sandbox Code Playgroud)

在一个视图中:

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
Run Code Online (Sandbox Code Playgroud)

一切正常,但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"
Run Code Online (Sandbox Code Playgroud)

试过不同的解决方案,例如

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
Run Code Online (Sandbox Code Playgroud)

这只对MySQL有帮助吗?有谁知道如何为postgres提供重复的键值错误?

kra*_*etz 8

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


小智 2

您是否曾在访问的个人资料字段中设置过 unique=True ?

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

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