Je poursuis en ce qui concerne une question que j'ai posée précédemment dans laquelle je cherchais à obtenir une conversion d'une requête mysql maladroite/mal écrite en postgresql. Je crois avoir réussi avec ça. Quoi qu'il en soit, j'utilise des données déplacées manuellement d'une base de données mysql vers une base de données postgres. J'utilise une requête qui ressemble à ceci:
"""
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)
)
J'ai des raisons de croire que cela fonctionne bien. Cependant, cela a conduit à un nouveau problème. En essayant de soumettre, Django affiche une erreur qui dit:
IntegrityError at (some url):
duplicate key value violates unique constraint "krypdos_value_pkey"
J'ai examiné plusieurs des réponses publiées ici et je n'ai pas encore trouvé la solution à mon problème (bien que les questions connexes aient fourni une lecture intéressante). Je le vois dans mes journaux, ce qui est intéressant car je n’appelle jamais explicitement insert-Django doit le gérer:
STATEMENT: INSERT INTO "krypdos_value" ("code_round_id", "variable_id", "option_id", "confidence", "freetext")
VALUES (1105935, 11, 55, NULL, E'')
RETURNING "krypdos_value"."id"
Cependant, si vous essayez de l'exécuter, cela entraîne une erreur de clé en double. L'erreur réelle est renvoyée dans le code ci-dessous.
# 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(
J'ai vérifié les séquences et autres et elles semblent être en ordre. À ce stade, je ne sais pas quoi faire - je suppose que c'est quelque chose du côté de Django mais je ne suis pas sûr. Tout retour serait apprécié!
Cela m'est arrivé - il s'avère que vous devez resynchroniser vos champs de clé primaire dans Postgres. La clé est l'instruction SQL:
SELECT setval('tablename_id_seq', (SELECT MAX(id) FROM tablename)+1)
Il semble que ce soit une différence de comportement connue entre MySQL et SQLite (ils mettent à jour la prochaine clé primaire disponible même lors de l'insertion d'un objet avec un identifiant explicite) .
Il existe un ticket décrivant le même problème . Même s'il a été fermé pour invalide, il indique qu'il existe une commande de gestion Django pour mettre à jour la clé disponible suivante.
Pour afficher le code SQL mettant à jour tous les identifiants suivants pour l'application MyApp:
python manage.py sqlsequencereset MyApp
Pour que l'instruction soit exécutée, vous pouvez la fournir comme entrée pour la commande de gestion dbshell. Pour Bash, vous pouvez taper:
python manage.py sqlsequencereset MyApp | python manage.py dbshell
L'avantage des commandes de gestion réside dans l'abstraction du backend de base de données sous-jacent. Ainsi, cela fonctionnera même si vous migrez ultérieurement vers un backend différent.
En plus de zapphods, répondez:
Dans mon cas, l'indexation était en effet incorrecte, car j'avais supprimé toutes les migrations, et la base de données était probablement 10 à 15 fois sous développement, car je n'étais pas encore en train de migrer.
J'obtenais un IntegrityError sur finished_product_template_finishedproduct_pkey
J'utilisais pgadmin3 et quel que soit l'index qui était incorrect et jettais les erreurs de clé en double, j'ai navigué dans la variable constraints
et réindexé.
Et puis réindexé.
J'ai eu le même problème. J'avais une table existante dans mon application "inventaire" et je voulais ajouter de nouveaux enregistrements dans Django admin et j'ai reçu ces messages:
La valeur de clé en double viole la contrainte unique "inventory_part_pkey" DETAIL: La clé (part_id) = (1) existe déjà.
Comme mentionné précédemment, lancez le code ci-dessous pour obtenir une commande SQL permettant de réinitialiser l'id-s:
python manage.py sqlsequencereset inventory
Dans mon cas, python manage.py sqlsequencereset MyApp | python manage.py dbshell
.__ ne fonctionnait pas
Dans mon cas c'était:
COMMENCER; SELECT setval (pg_get_serial_sequence ('"inventaire_signup"', "id"), coalesce (max ("id"), 1), max ("id") IS NON null) FROM "inventaire_signup"; SELECT setval (pg_get_serial_sequence ('"inventaire_supplier"', "id"), coalesce (max ("id"), 1), max ("id") IS NON null) FROM "inventaire_supplier"; COMMETTRE;
Exécuté avec F5.
Cela a corrigé toutes mes tables et finalement ajouté de nouveaux enregistrements à la fin en essayant de ne plus l'ajouter à id = 1.
La solution est que vous devez resynchroniser vos champs de clé primaire comme indiqué par "Hacking Life" qui a écrit un exemple de code SQL mais, comme suggéré par "Ad N", il est préférable d'exécuter la commande Django sqlsequencereset
peut copier et coller ou exécuter avec une autre commande.
Pour améliorer encore ces réponses, je vous recommanderais, ainsi qu’à un autre lecteur, de ne pas copier et coller le code SQL mais, plus sûrement, d’exécuter la requête SQL générée par sqlsequencereset
depuis votre code python de cette manière (using la base de données par défaut):
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)
J'ai testé ce code avec Python3.6 , Django 2.0 et PostgreSQL 10 .
Si vous avez copié manuellement les bases de données, vous risquez de rencontrer le problème décrit ici .
J'ai rencontré cette erreur parce que je transmettais des arguments supplémentaires à la méthode de sauvegarde de manière incorrecte.
Pour tous ceux qui rencontrent cela, essayez de forcer UPDATE avec:
instance_name.save(..., force_update=True)
Si vous obtenez une erreur indiquant que vous ne pouvez pas transmettre force_insert
et force_update
en même temps, vous transmettez probablement des arguments personnalisés de manière incorrecte, comme je l'ai fait.
Si vous voulez réinitialiser le PK sur toutes vos tables, comme moi, vous pouvez utiliser le méthode recommandée par 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;
Après avoir exécuté cette requête, vous devrez exécuter les résultats de la requête. Je copie et colle généralement dans le Bloc-notes. Ensuite, je trouve et remplace "SELECT
par SELECT
et ;"
par ;
. Je copie et colle dans pgAdmin III et lance la requête. Il réinitialise toutes les tables de la base de données. Des instructions plus "professionnelles" sont fournies sur le lien ci-dessus.
J'avais la même erreur que l'OP.
J'avais créé des modèles Django, créé une table Postgres basée sur les modèles et ajouté quelques lignes à la table Postgres via Django Admin. Ensuite, j'ai manipulé certaines des colonnes des modèles (modification de ForeignKeys, etc.), mais j'avais oublié de migrer les modifications.
L'exécution des commandes de migration a résolu mon problème, ce qui est logique compte tenu des réponses SQL ci-dessus.
Pour voir quels changements seraient appliqués, sans les appliquer réellement:python manage.py makemigrations --dry-run --verbosity 3
Si vous êtes satisfait de ces changements, lancez:python manage.py makemigrations
Puis lancez:python manage.py migrate