Django-fr

Forum

#1 04-01-2011 11:30:53

Sinad
Membre
Lieu : Rouen
Inscription : 03-11-2010
Messages : 7
Site Web

[postgres] primary key

Bonjour,

J'ai un phénomène curieux avec une base Postgres 8.4 et Django 1.2.3 avec le module postgresql_psycopg2.

L'autoincrémentation de la clef primaire ne semble pas fonctionner.

Le SQL de ma classe ressemble à ça:

CREATE TABLE "base_produit" (
    "id" serial NOT NULL PRIMARY KEY,
    "nom" varchar(60) NOT NULL,
    "nom_facture" varchar(35) NOT NULL,
    "categorie_id" integer NOT NULL REFERENCES "base_categorie" ("id") DEFERRABLE INITIALLY DEFERRED,
    "choix_cuisson" boolean NOT NULL,
    "choix_accompagnement" boolean NOT NULL,
    "choix_sauce" boolean NOT NULL,
    "actif" boolean NOT NULL,
    "prix" numeric(7, 2) NOT NULL
)

Donc la clef "id" existe bien.
Si je crée un objet sans affecter l'ID, je ne peux le sauver (IntegrityError sur la clef primaire Id).
Quelqu'un a-t-il déjà rencontré ce problème ?

Hors ligne

#2 04-01-2011 11:48:52

Chamal
Membre
Inscription : 11-08-2010
Messages : 17

Re : [postgres] primary key

Le 4 janv. 2011 à 11:30, S. Bonnegent a écrit :

> Bonjour,
>
> J'ai un phénomène curieux avec une base Postgres 8.4 et Django 1.2.3
> avec le module postgresql_psycopg2.
>
> L'autoincrémentation de la clef primaire ne semble pas fonctionner.
>
> Le SQL de ma classe ressemble à ça:
>
> CREATE TABLE "base_produit" (
>    "id" serial NOT NULL PRIMARY KEY,
>    "nom" varchar(60) NOT NULL,
>    "nom_facture" varchar(35) NOT NULL,
>    "categorie_id" integer NOT NULL REFERENCES "base_categorie" ("id")
> DEFERRABLE INITIALLY DEFERRED,
>    "choix_cuisson" boolean NOT NULL,
>    "choix_accompagnement" boolean NOT NULL,
>    "choix_sauce" boolean NOT NULL,
>    "actif" boolean NOT NULL,
>    "prix" numeric(7, 2) NOT NULL
> )
>
> Donc la clef "id" existe bien.
> Si je crée un objet sans affecter l'ID, je ne peux le sauver
> (IntegrityError sur la clef primaire Id).
> Quelqu'un a-t-il déjà rencontré ce problème ?

Le type SERIAL est équivalent à la création implicite d'une séquence.

Que donne un \d base_produit, vois tu bien le lien vers un objet sequence pour la colonne id ?

Voir également pour lister les séquences : \ds et ensuite \d <nom_sequence>, regardes last_value qui doit être >= au max(id) de ta table.

++ Aymeric

Hors ligne

#3 04-01-2011 13:01:54

Sinad
Membre
Lieu : Rouen
Inscription : 03-11-2010
Messages : 7
Site Web

Re : [postgres] primary key

Merci pour les commandes, la séquence existe bien mais la valeur last_value n'est pas correcte. Elle vaut 6 alors que le max ID est 509.
L'origine du problème est trouvé.

#\d base_produit_id_seq
    Séquence « public.base_produit_id_seq »
    Colonne    |  Type   |       Valeur       
---------------+---------+---------------------
sequence_name | name    | base_produit_id_seq
last_value    | bigint  | 6
start_value   | bigint  | 1
increment_by  | bigint  | 1
max_value     | bigint  | 9223372036854775807
min_value     | bigint  | 1
cache_value   | bigint  | 1
log_cnt       | bigint  | 32
is_cycled     | boolean | f
is_called     | boolean | t

Du coup, la cause est claire aussi. Je récupère les objets d'une ancienne table en sqlite dont les ID sont déjà présent; donc aucun ajout des anciens objects n'a mis à jour la valeur last_value.

Il ne me reste plus qu'à trouver comment mettre à jour les séquences.

Hors ligne

#4 04-01-2011 13:05:02

Sinad
Membre
Lieu : Rouen
Inscription : 03-11-2010
Messages : 7
Site Web

Re : [postgres] primary key

Bon, pour mettre à jour le champs last_value, il faut faire un:
# SELECT setval('base_produit_id_seq', max(id)) FROM base_produit;

avec base_produit_id_seq : le nom de la séquence.


Merci beaucoup pour votre aide précieuse !

Hors ligne

#5 04-01-2011 13:18:46

Sinad
Membre
Lieu : Rouen
Inscription : 03-11-2010
Messages : 7
Site Web

Re : [postgres] primary key

ou directement dans django:

Produit.objects.raw("SELECT setval('base_produit_id_seq', max(id)) FROM base_produit")

Hors ligne

#6 04-01-2011 20:50:31

doddo
Membre
Inscription : 29-12-2010
Messages : 20

Re : [postgres] primary key

Salut,
à connaitre aussi : ALTER SEQUENCE base_produit_id_seq RESTART WITH
700; --par exemple. j'aurai pu tout aussi bien mettre 1000. Une fois
ceci fait, tu peux réutiliser ta base comme tu veux, l'auto incrément
sera ok.

(À moins que ça n'embrouille django, mais y'a pas de raisons. Works
great with php et zend framework en tout cas.)

attention. cette commande est exclusive à postgre.
http://www.postgresql.org/docs/8.4/interactive/sql-altersequence.html

a+
Rodrigue.

On Tue, 04 Jan 2011 12:18:46 +0000, S. Bonnegent wrote:
> ou directement dans django:
>
>  Produit.objects.raw("SELECT setval('base_produit_id_seq', max(id))
> FROM
> base_produit")
> _______________________________________________
> django mailing list
> django _AT_ lists.afpy.org
> http://lists.afpy.org/mailman/listinfo/django

Hors ligne

Pied de page des forums