Django ошибка повторяющееся значение ключа нарушает ограничение уникальности

I’m following up in regards to a question that I asked earlier in which I sought to seek a conversion from a goofy/poorly written mysql query to postgresql. I believe I succeeded with that. Anyways, I’m using data that was manually moved from a mysql database to a postgres database. I’m using a query that looks like so:

  UPDATE krypdos_coderound cru

  set is_correct = case 
      when t.kv_values1 = t.kv_values2 then True 
      else False 
      end

  from 
  
  (select cr.id, 
    array_agg(
    case when kv1.code_round_id = cr.id 
    then kv1.option_id 
    else null end 
    ) as kv_values1,

    array_agg(
    case when kv2.code_round_id = cr_m.id 
    then kv2.option_id 
    else null end 
    ) as kv_values2

    from krypdos_coderound cr
     join krypdos_value kv1 on kv1.code_round_id = cr.id
     join krypdos_coderound cr_m 
       on cr_m.object_id=cr.object_id 
       and cr_m.content_type_id =cr.content_type_id 
     join krypdos_value kv2 on kv2.code_round_id = cr_m.id

   WHERE
     cr.is_master= False
     AND cr_m.is_master= True 
     AND cr.object_id=%s 
     AND cr.content_type_id=%s 

   GROUP BY cr.id  
  ) t

where t.id = cru.id
    """ % ( self.object_id, self.content_type.id)
  )

I have reason to believe that this works well. However, this has lead to a new issue. When trying to submit, I get an error from django that states:

IntegrityError at (some url): 
duplicate key value violates unique constraint "krypdos_value_pkey"

I’ve looked at several of the responses posted on here and I haven’t quite found the solution to my problem (although the related questions have made for some interesting reading). I see this in my logs, which is interesting because I never explicitly call insert- django must handle it:

   STATEMENT:  INSERT INTO "krypdos_value" ("code_round_id", "variable_id", "option_id", "confidence", "freetext")
   VALUES (1105935, 11, 55, NULL, E'') 
   RETURNING "krypdos_value"."id"

However, trying to run that results in the duplicate key error. The actual error is thrown in the code below.

# Delete current coding
CodeRound.objects.filter(
    object_id=o.id, content_type=object_type, is_master=True
).delete()
code_round = CodeRound(
    object_id=o.id, 
    content_type=object_type, 
    coded_by=request.user, comments=request.POST.get('_comments',None), 
    is_master=True,
)
code_round.save()
for key in request.POST.keys():
    if key[0] != '_' or key != 'csrfmiddlewaretoken':
        options = request.POST.getlist(key)
        for option in options:
            Value(
                code_round=code_round, 
                variable_id=key, 
                option_id=option,
                confidence=request.POST.get('_confidence_'+key, None),
            ).save()  #This is where it dies
# Resave to set is_correct
code_round.save()
o.status = '3' 
o.save()

I’ve checked the sequences and such and they seem to be in order. At this point I’m not sure what to do- I assume it’s something on django’s end but I’m not sure. Any feedback would be much appreciated!

Всем привет. Делаю сайт, конкретно форму добавления постов. При попытке сохранить пост появляется вот такая ошибка:

IntegrityError at /form ОШИБКА: повторяющееся значение ключа нарушает ограничение уникальности "sitelogic_post_post_slug_key" DETAIL: Ключ "(post_slug)=()" уже существует.

База данных — PostgreSQL

Пожалуйста, помогите разобраться в чем проблема. Искал ответ в большом количестве источников, нигде не нашел решения

Models.py:

class Post(models.Model):
    post_title = models.CharField(max_length=250, verbose_name='Заголовок')
    post_slug = models.SlugField(max_length=250, unique=True, verbose_name='URL')
    post_content = models.TextField(max_length=450000, verbose_name='Содержание')
    post_time_create = models.DateTimeField(auto_now_add=True, verbose_name='Время создания')
    post_time_update = models.DateTimeField(auto_now=True, verbose_name='Время обновления')
    post_media = models.ImageField(upload_to='%Y/%m/%d/', default='default.png', blank=True, verbose_name='Медиа')
    cat = models.ForeignKey('PostCategory', on_delete=models.PROTECT, null=True, verbose_name='Категория')

    def __str__(self):
        return self.post_title

    def get_absolute_url(self):
        return reverse('show_post', kwargs={'post_title_slug': self.post_title, 'post_id_slug': self.id})

    class Meta:
        verbose_name = 'Пост'
        verbose_name_plural = 'Посты'

        ordering = ['post_title', 'post_content']

class PostCategory(models.Model):
    category_name = models.CharField(max_length=100, db_index=True)
    slug = models.SlugField(max_length=100, unique=True, verbose_name='URL')

    class Meta:
        verbose_name = 'Категория'
        verbose_name_plural = 'Категории'

        ordering = ['pk']

    def __str__(self):
        return self.category_name

    def get_absolute_url(self):
        return reverse('cat_posts', kwargs={'cat_slug': self.slug})

Forms.py:

class PostForm(forms.ModelForm):
captcha = CaptchaField()

class Meta:
    model = Post
    fields = ['post_title', 'post_content', 'post_media', 'cat']

def clean_post_title(self):
    post_title = self.cleaned_data['post_title']
    if len(post_title) >= 250:
        raise ValidationError('Длина превышает 200 символов')

    return post_title

Views.py:

class FormAdd(View):

    def get(self, request):
        form = PostForm
        return render(request, 'sitelogic/addpost.html', context={'form': form})

    def post(self, request):
        request_keep = PostForm(request.POST)
        if request_keep.is_valid():
            request_keep.save()
            return redirect('home_page')
        return render(request, 'sitelogic/addpost.html', context={'form': request_keep})

Urls.py:

urlpatterns = [
              path('', homepage, name='home_page'),
              path('about', About.as_view(), name='about_site'),
              path('post/<slug:post_title_slug>/<int:post_id_slug>/', ShowPost, name='show_post'),
              path('forums/<slug:cat_slug>', ShowCategory.as_view(), name='cat_posts'),
              path('form', FormAdd.as_view(), name='add_post'),
              path('cabinet', Cabinet.as_view(), name='cabinet'),
              path('auth/', include('djoser.urls')),
              path('api/token/', TokenObtainPairView.as_view(), name='token_obtain_pair'),
              path('api/token/refresh/', TokenRefreshView.as_view(), name='token_refresh'),
              path('api/token/verify/', TokenVerifyView.as_view(), name='token_verify'),
              path('testapi', Base.as_view())
          ] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) 
          + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

Addpost.html:

{% extends 'sitelogic/base.html' %}

{% block body %}
<form action="{% url 'add_post' %}" method="post" enctype="multipart/form-data">
    {% csrf_token %}
    {{ form.as_p }}
    <button type="submit">добавить</button>
</form>
{% endblock %}

#django #postgresql #django-models #django-orm #unique-constraint

#django #postgresql #django-модели #django-orm #уникальное ограничение

Вопрос:

Я использую PostgreSQL с Django, и я пытался получить некоторый объект из БД с помощью Django ORM.

 Medicine.objects.get(unique_item_id=26775)
  

Но во время выборки я столкнулся с ошибкой -> item_medicine.models.DoesNotExist: Medicine matching query does not exist.

Затем я попытался вставить то же самое, используя Django ORM.

 Medicine.objects.create(unique_item_id=26775)
  

Но снова я получаю ошибку psycopg2.errors.UniqueViolation: duplicate key value violates unique constraint "item_medicine_medicine_unique_item_id_key" DETAIL: Key (unique_item_id)=(26775) already exists.

В моих моделях я добавил unique=True unique_item_id поле for .

Я не знаю, почему это происходит. Я пробовал ответы, приведенные на похожие сообщения, но ничего не сработало.

Трассировка:

 Traceback (most recent call last):
  File "/home/rohit/virtualenvs/envmedicine/lib/python3.6/site-packages/django/db/backends/utils.py", line 64, in execute
    return self.cursor.execute(sql, params)
psycopg2.errors.UniqueViolation: duplicate key value violates unique constraint "item_medicine_medicine_unique_item_id_key"
DETAIL:  Key (unique_item_id)=(26775) already exists.
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
  File "/home/rohit/virtualenvs/envmedicine/lib/python3.6/site-packages/IPython/core/interactiveshell.py", line 2963, in run_code
    exec(code_obj, self.user_global_ns, self.user_ns)
  File "<ipython-input-4-46fdec6a582b>", line 1, in <module>
    Medicine.objects.create(unique_item_id=26775)
  File "/home/rohit/virtualenvs/envmedicine/lib/python3.6/site-packages/django/db/models/manager.py", line 85, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "/home/rohit/virtualenvs/envmedicine/lib/python3.6/site-packages/django/db/models/query.py", line 394, in create
    obj.save(force_insert=True, using=self.db)
  File "/home/rohit/Projects/medicine/item_medicine/models.py", line 58, in save
    super(Medicine, self).save(*args, **kwargs)
  File "/home/rohit/virtualenvs/envmedicine/lib/python3.6/site-packages/django/db/models/base.py", line 808, in save
    force_update=force_update, update_fields=update_fields)
  File "/home/rohit/virtualenvs/envmedicine/lib/python3.6/site-packages/django/db/models/base.py", line 838, in save_base
    updated = self._save_table(raw, cls, force_insert, force_update, using, update_fields)
  File "/home/rohit/virtualenvs/envmedicine/lib/python3.6/site-packages/django/db/models/base.py", line 924, in _save_table
    result = self._do_insert(cls._base_manager, using, fields, update_pk, raw)
  File "/home/rohit/virtualenvs/envmedicine/lib/python3.6/site-packages/django/db/models/base.py", line 963, in _do_insert
    using=using, raw=raw)
  File "/home/rohit/virtualenvs/envmedicine/lib/python3.6/site-packages/django/db/models/manager.py", line 85, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "/home/rohit/virtualenvs/envmedicine/lib/python3.6/site-packages/django/db/models/query.py", line 1076, in _insert
    return query.get_compiler(using=using).execute_sql(return_id)
  File "/home/rohit/virtualenvs/envmedicine/lib/python3.6/site-packages/django/db/models/sql/compiler.py", line 1112, in execute_sql
    cursor.execute(sql, params)
  File "/home/rohit/virtualenvs/envmedicine/lib/python3.6/site-packages/django/db/backends/utils.py", line 79, in execute
    return super(CursorDebugWrapper, self).execute(sql, params)
  File "/home/rohit/virtualenvs/envmedicine/lib/python3.6/site-packages/django/db/backends/utils.py", line 64, in execute
    return self.cursor.execute(sql, params)
  File "/home/rohit/virtualenvs/envmedicine/lib/python3.6/site-packages/django/db/utils.py", line 94, in __exit__
    six.reraise(dj_exc_type, dj_exc_value, traceback)
  File "/home/rohit/virtualenvs/envmedicine/lib/python3.6/site-packages/django/utils/six.py", line 685, in reraise
    raise value.with_traceback(tb)
  File "/home/rohit/virtualenvs/envmedicine/lib/python3.6/site-packages/django/db/backends/utils.py", line 64, in execute
    return self.cursor.execute(sql, params)
django.db.utils.IntegrityError: duplicate key value violates unique constraint "item_medicine_medicine_unique_item_id_key"
DETAIL:  Key (unique_item_id)=(26775) already exists.
  

Заранее спасибо, ребята!!

Комментарии:

1. Я не уверен, что вызвало проблему, но вы пробовали Medicine.objects.filter(unique_item_id=26775).first() ?

2. Я попробовал filter, но он возвращает пустой набор запросов

3. попробуйте это Medicine.objects.get(unique_item_id_id =26775)

4. Нет, поле ошибки получения не существует

5. Это немного странно, это происходит только с PostgreSQL? Если да, то можно ли его воспроизвести в новом проекте ? @RohitChopra

Ответ №1:

Если вы выполняете какую-либо фильтрацию в своем Medicine.objects менеджере, вы, вероятно, столкнетесь с этой проблемой. Например, предположим, что у вас определены следующие модель и менеджер.

 class SoftDeleteManager(models.Manager):
    def get_queryset(self):
        return super().get_queryset().filter(deleted_at=None)

class Medecine(models.Model):
    ...
    unique_item_id = models.IntegerField(unique=True)
    deleted_at = models.DateTimeField(null=True)

    objects = SoftDeleteManager()

conflicting = Medecine.objects.create(unique_item_id=26775, deleted_at=some_datetime)

Medecine.objects.get(unique_item_id=26775)  # Results in DoesNotExist
Medecine.objects.create(unique_item_id=26775) # Results in IntegrityError
  

Если это не так, то у вас может быть поврежден индекс PostgreSQL.

Я бы посоветовал вам попробовать запустить REINDEX команду на вашем столе

REINDEX TABLE item_medicine_medicine

Комментарии:

1. Действительно, и я бы посоветовал проверить, что происходит непосредственно в БД, используя psql в консоли или pgAdmin. выберите * из лекарства, где unique_item_id = 26775.

2. «… любой вид фильтрации… тогда вы, вероятно, столкнетесь с этой проблемой …» Не могли бы вы объяснить, почему? В чем основная причина? Я знаю, что это есть в вашем примере, но краткое объяснение было бы очень полезно. 🙂

3. Ошибка фильтрации базового менеджера также упоминается в документах: don-t-filter-away-any-results-in-this-type-of-manager-subclass

Я слежу за вопросом который я задал ранее, в котором я пытался найти конверсию из тупого/плохо написанного запроса mysql в postgresql. Я считаю, что мне это удалось. В любом случае, я использую данные, которые были вручную перемещены из базы данных mysql в базу данных postgres. Я использую запрос, который выглядит так:

  """
  UPDATE krypdos_coderound cru

  set is_correct = case 
      when t.kv_values1 = t.kv_values2 then True 
      else False 
      end

  from 

  (select cr.id, 
    array_agg(
    case when kv1.code_round_id = cr.id 
    then kv1.option_id 
    else null end 
    ) as kv_values1,

    array_agg(
    case when kv2.code_round_id = cr_m.id 
    then kv2.option_id 
    else null end 
    ) as kv_values2

    from krypdos_coderound cr
     join krypdos_value kv1 on kv1.code_round_id = cr.id
     join krypdos_coderound cr_m 
       on cr_m.object_id=cr.object_id 
       and cr_m.content_type_id =cr.content_type_id 
     join krypdos_value kv2 on kv2.code_round_id = cr_m.id

   WHERE
     cr.is_master= False
     AND cr_m.is_master= True 
     AND cr.object_id=%s 
     AND cr.content_type_id=%s 

   GROUP BY cr.id  
  ) t

where t.id = cru.id
    """ % ( self.object_id, self.content_type.id)
  )

У меня есть основания полагать, что это хорошо работает. Однако это привело к новой проблеме. При попытке отправить, я получаю сообщение об ошибке из django, в котором говорится:

IntegrityError at (some url): 
duplicate key value violates unique constraint "krypdos_value_pkey"

Я просмотрел несколько ответов, размещенных здесь, и я не нашел решения моей проблемы (хотя связанные вопросы сделали для некоторого интересного чтения). Я вижу это в своих журналах, что интересно, потому что я никогда не называю insert-django явным образом:

   STATEMENT:  INSERT INTO "krypdos_value" ("code_round_id", "variable_id", "option_id", "confidence", "freetext")
   VALUES (1105935, 11, 55, NULL, E'') 
   RETURNING "krypdos_value"."id"

Тем не менее, попытка выполнить это приводит к дублированию ключевой ошибки. Фактическая ошибка указана в коде ниже.

 # Delete current coding         CodeRound.objects.filter(object_id=o.id,content_type=object_type,is_master=True).delete()
  code_round = CodeRound(object_id=o.id,content_type=object_type,coded_by=request.user,comments=request.POST.get('_comments',None),is_master=True)
  code_round.save()
  for key in request.POST.keys():
    if key[0] != '_' or key != 'csrfmiddlewaretoken':
      options = request.POST.getlist(key)
      for option in options:
        Value(code_round=code_round,variable_id=key,option_id=option,confidence=request.POST.get('_confidence_'+key, None)).save()  #This is where it dies
  # Resave to set is_correct
  code_round.save()
  o.status = '3' 
  o.save(

Я проверил последовательности и такие, и они, похоже, в порядке. На данный момент я не уверен, что делать — я предполагаю, что это что-то на django, но я не уверен. Любая обратная связь будет высоко оценена!

При публикации страницы в django-cms (3.5.0) может возникнуть ошибка:

Exception Type: IntegrityError at /admin/cms/page/312/ru/publish/
Exception Value: ОШИБКА: повторяющееся значение ключа нарушает ограничение уникальности "spec_pageext_extended_object_id_key"
DETAIL: Ключ "(extended_object_id)=(324)" уже существует.

По-английски:

django.db.utils.IntegrityError: duplicate key value violates unique constraint "spec_pageext_extended_object_id_key"
DETAIL:  Key (extended_object_id)=(324) already exists.

Из трейсбека понятно, что ошибка связана с Extension (Расширение страницы).

Ещё нужно сказать, что ошибка не всегда проявляется при публикации страницы. Чтобы воспроизвести ошибку нужно:

  1. Создать расширение (или по-другому «Сохранить» из Меню / Страница / Моё расширение)
  2. Опубликовать страницу
  3. Перейти на черновую версию, щёлкнув «Изменить»
  4. Удалить расширение (Перейдя в Меню / Страница / Моё расширение и щёлкнув «Удалить»)
  5. Снова создать расширение (Меню / Страница / Моё расширение)
  6. И попытаться опубликовать страницу.

На шестом шаге появляется ошибка.

Оказывается при публикации не стирается старый объект Extension и возникает исключение уникальности ключа. Поэтому я написал Mixin, который перед выполнением операций по публикации Extension удалаяет старое Extension со страницы:

class ExtensionFixMixin(object):
    def copy_to_public(self, public_object, language):
        if not self.public_extension:
            try:
                self.__class__.objects.get(extended_object_id=public_object.pk).delete()
            except self.__class__.DoesNotExist:
                pass

        return super(ExtensionFixMixin, self).copy_to_public(public_object, language)

Теперь можно использовать в своих расширениях:

class MyExtension(ExtensionFixMixin, PageExtension):
    ...

Оказывается, есть тикет на гитхабе пакета django-cms , где встречается эта ошибка. Я дополнил тикет своим комментарием. Мое решение — это обходной путь. Как именно в самой django-cms поправить я сильно не смотрел. Надеюсь, разработчики поправят это дело.

Оцените статью

После нажатия кнопки «Отправить» ваше сообщение будет доставлено мне на почту.

Артём Мальцев

Веб-разработчик, владеющий знаниями языка программирования Python, фреймворка Django, системы управления содержимым сайта Django CMS, платформы для создания интернет-магазина Django Shop и многих различных приложений, использующих эти технологии.

Права на использование материала, расположенного на этой странице https://vivazzi.pro/ru/it/extended-object-id-already-exists/:

Разрешается копировать материал с указанием её автора и ссылки на оригинал без использования параметра rel="nofollow" в теге <a>. Использование:

Автор статьи: Артём Мальцев
Ссылка на статью: <a href="https://vivazzi.pro/ru/it/extended-object-id-already-exists/">https://vivazzi.pro/ru/it/extended-object-id-already-exists/</a>

Больше: Правила использования сайта

Представляю вашему вниманию книгу, написанную моим близким другом Максимом Макуриным: Секреты эффективного управления ассортиментом.

Книга предназначается для широкого круга читателей и, по мнению автора, будет полезна специалистам отдела закупок и логистики, категорийным и финансовым менеджерам, менеджерам по продажам, аналитикам, руководителям и директорам, в компетенции которых принятие решений по управлению ассортиментом.

  • Django rest framework обработка ошибок
  • Divinity original sin ошибка msvcp120 dll
  • Django is not importable in this environment ошибка
  • Divinity original sin ошибка msvcp110
  • Django admin ошибка проверки csrf запрос отклонен