2012-02-15 2 views
9

Спасибо, что нашли время, чтобы прочитать мой вопрос.Ошибка get_or_create с Django и Postgres (дублирующее значение ключа нарушает уникальное ограничение)

У меня есть приложение Джанго со следующей моделью:

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?

+0

http://stackoverflow.com/q/244243/781695 – Medorator

ответ

1

У вас в какой-то момент было уникальное = True, установленное в поле профиля Visit?

Похоже, что существует уникальное ограничение, созданное для postgres, которое все еще действует. «table_visit_profile_id_key» - это то, что было бы автоматически сгенерированным именем, и, естественно, это приведет к этим ошибкам, если вы записываете несколько посещений для пользователя.

Если это так, используете ли вы South для управления изменениями в базе данных? Если вы этого не сделаете, возьмите его!

0

PostgreSQL ведет себя несколько иначе в некоторых тонких запросах, что приводит к ошибкам IntegrityError, особенно после перехода на Django 1.6. Вот решение - вам нужно добавить select_on_save возможности каждую неисправную модели:

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

Это документировано здесь: Options.select_on_save

+1

Что делать, если я использую Django 1.4, и я получаю ошибки целостности? –

3

Я имел проблемы с get_or_create при использовании Postgres. В конце концов я отказался шаблонный код для традиционно:

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

Хотя это решение будет работать на большинстве сайтов, оно не удастся на узлах с интенсивным трафиком, где работает много одновременных запросов. –

0

Другой возможной причиной этих ошибок в get_or_create() является типом данных рассогласования в одном из поисковых полей - например, прохождение False вместо None в обнуляемого поля. .get() внутри .get_or_create() не найдет его, и Django продолжит создание новой строки - это приведет к сбою из-за ограничений PostgreSQL.

+0

Спасибо за ваш ответ :) – Barmi

Смежные вопросы

 Смежные вопросы