Ответ 1
Это случилось со мной - оказывается, вам нужно повторно синхронизировать поля первичного ключа в Postgres. Ключ - это оператор SQL:
SELECT setval('tablename_id_seq', (SELECT MAX(id) FROM tablename)+1)
Я слежу за вопросом который я задал ранее, в котором я пытался найти конверсию из тупого/плохо написанного запроса 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, но я не уверен. Любая обратная связь будет высоко оценена!
Это случилось со мной - оказывается, вам нужно повторно синхронизировать поля первичного ключа в Postgres. Ключ - это оператор SQL:
SELECT setval('tablename_id_seq', (SELECT MAX(id) FROM tablename)+1)
Похоже, что это известное различие в поведении между MySQL и SQLite (они обновляют следующий доступный первичный ключ, даже когда вставляют объект с явным id), и другие бэкэнды, такие как Postgres, Oracle,... (они не).
Существует билет, описывающий ту же проблему. Несмотря на то, что он был закрыт как недопустимый, он дает подсказку о том, что есть команда управления Django для обновления следующего доступного ключа.
Чтобы отобразить SQL-обновление всех следующих идентификаторов для приложения MyApp:
python manage.py sqlsequencereset MyApp
Чтобы выполнить оператор, вы можете указать его как вход для команды управления dbshell. Для bash вы можете ввести:
python manage.py sqlsequencereset MyApp | python manage.py dbshell
Преимущество команд управления заключается в том, что он абстрагирует базовый сервер базы данных, поэтому он будет работать, даже если позже будет перенесен на другой бэкэнд.
В дополнение к ответам zapphods:
В моем случае индексирование действительно было неправильным, так как я удалил все миграции, а база данных, вероятно, 10-15 раз при разработке, поскольку я не был в стадии миграции чего-либо.
Я получал IntegrityError на finished_product_template_finishedproduct_pkey
Я использовал pgadmin3 и для того, что индекс был неправильным и выбрасывал повторяющиеся ключевые ошибки, я перешел к constraints
и повторно проиндексирован.
И затем снова проиндексируется.
У меня была такая же проблема. У меня была существующая таблица в моем приложении "inventory", и я хотел добавить новые записи в admin django, и я получил эти сообщения:
Повторяющееся значение ключа нарушает уникальное ограничение "inventory_part_pkey" ДЕТАЛИ: Key (part_id) = (1) уже существует.
Как уже упоминалось выше, выполните следующий код, чтобы получить команду SQL для reset id-s:
python manage.py sqlsequencereset inventory
В моем случае python manage.py sqlsequencereset MyApp | python manage.py dbshell
не работает
В моем случае это было:
НАЧАТЬ; SELECT setval (pg_get_serial_sequence (' "inventory_signup",' id '), coalesce (max ( "id" ), 1), max ( "id" ) НЕ НЕВОЗМОЖНО) FROM "inventory_signup"; SELECT setval (pg_get_serial_sequence (' "inventory_supplier" ', 'id'), coalesce (max ( "id" ), 1), max ( "id" ) НЕ НЕВОЗМОЖНО) FROM "inventory_supplier"; COMMIT;
Выполнено с помощью F5.
Это фиксировало все мои таблицы и, наконец, добавило новые записи в конец, не пытаясь добавить его к id = 1.
Если вы вручную скопировали базы данных, вы можете столкнуться с проблемой описанной здесь.
Решение состоит в том, что вам необходимо sqlsequencereset
поля первичного ключа, как сообщил "Hacking Life", который написал пример кода SQL, но, как это было предложено в "Ad N", лучше запустить команду Django sqlsequencereset
чтобы получить точный код SQL, который вы можно скопировать и пропустить или запустить с другой командой.
В качестве дальнейшего улучшения этих ответов я бы предложил вам и другим читателям не копировать и вставлять код SQL, а более безопасно выполнять запрос SQL, сгенерированный sqlsequencereset
из кода Python таким образом (используя базу данных по умолчанию). ):
from django.core.management.color import no_style
from django.db import connection
from myapps.models import MyModel1, MyModel2
sequence_sql = connection.ops.sequence_reset_sql(no_style(), [MyModel1, MyModel2])
with connection.cursor() as cursor:
for sql in sequence_sql:
cursor.execute(sql)
Я тестировал этот код с Python3.6, Django 2.0 и PostgreSQL 10.
Я столкнулся с этой ошибкой, потому что я передал дополнительные аргументы методу сохранения не так.
Для всех, кто сталкивается с этим, попробуйте форсировать UPDATE с помощью:
instance_name.save(..., force_update=True)
Если вы получите сообщение об ошибке, которое вы не можете передать force_insert
и force_update
одновременно, вы, вероятно, передаете некоторые пользовательские аргументы неправильно, как я.
Если вы хотите сбросить PK во всех ваших таблицах, как и я, вы можете использовать PostgreSQL рекомендуемый способ:
SELECT 'SELECT SETVAL(' ||
quote_literal(quote_ident(PGT.schemaname) || '.' || quote_ident(S.relname)) ||
', COALESCE(MAX(' ||quote_ident(C.attname)|| '), 1) ) FROM ' ||
quote_ident(PGT.schemaname)|| '.'||quote_ident(T.relname)|| ';'
FROM pg_class AS S,
pg_depend AS D,
pg_class AS T,
pg_attribute AS C,
pg_tables AS PGT
WHERE S.relkind = 'S'
AND S.oid = D.objid
AND D.refobjid = T.oid
AND D.refobjid = C.attrelid
AND D.refobjsubid = C.attnum
AND T.relname = PGT.tablename
ORDER BY S.relname;
После выполнения этого запроса вам нужно будет выполнить результаты запроса. Я обычно копирую и вставляю в Блокнот. Затем я нахожу и заменяю "SELECT
на SELECT
и ;"
с ;
, Я копирую и вставляю в pgAdmin III и запускаю запрос. Сбрасывает все таблицы в базе данных. Более "профессиональные" инструкции приведены по ссылке выше.
Я получал ту же ошибку, что и ОП.
Я создал несколько моделей Django, создал таблицу Postgres на основе этих моделей и добавил несколько строк в таблицу Postgres через Django Admin. Затем я возился с некоторыми из столбцов в моделях (переходя на ForeignKeys и т.д.), Но забыл перенести изменения.
Выполнение команд миграции решило мою проблему, которая имеет смысл, учитывая приведенные выше ответы на SQL.
Чтобы увидеть, какие изменения будут применены, фактически не применяя их: python manage.py makemigrations --dry-run --verbosity 3
Если вы довольны этими изменениями, запустите: python manage.py makemigrations
Затем запустите: python manage.py migrate