Forum Programmation.python Peewee et les clés étrangères

Posté par . Licence CC by-sa.
2
10
août
2018

Bonjour,

Afin de progresser en Python, j'essaye d'apprendre à utiliser peewee.
J'ai une petite base de données sqlite que j'ai créé à la mano.
Voici un schéma de cette dernière :

Personne
    id = clé primaire
    nom
    prenom
    mail

Voiture
    personne_id (clé étrangère qui référence la colonne id de Personne)
    nombre_kilometre
    couleur

Je n'ai donc pas de clé primaire sur la table Voiture.
Une personne peut avoir plusieurs voiture mais une voiture ne peut pas appartenir à plusieurs personnes.

J'aimerai retranscrire ce modèle avec peewee.
J'arrive à sélectionner ce que je veux dans la table Personne, mais j'ai un problème lorsque je tape sur la table Voiture.
Voici ma déclaration de classe qui sont supposé représenter ma base de données

class BaseModel(peewee.Model):
    class Meta:
        db_path="base_de_donnees.db"
        database = peewee.SqliteDatabase(db_path, pragmas={'foreign_keys': 1})

class Personne(BaseModel):
    id = peewee.IntegerField(primary_key=True)
    nom = peewee.CharField()
    prenom = peewee.CharField()
    mail = peewee.CharField()

class Voiture(BaseModel):
    personne_id = peewee.ForeignKey(Personne)
    nombre_kilometre = peewee.IntegerField()
    couleur = peewee.CharField()

Ensuite, je veux sélectionner tout les infos sur les voitures qui ont un personne_id égal à 5 (maximum 10 résultats), je fais donc.

result = Voiture.select().where(Voiture.personne_id==5).limit(10)

Si je fais un

print result.count()

ça me retourne bien 10 (au vue des données dans ma base c'est logique).
Par contre, si je tente d'afficher les résultats avec la boucle :

for element in result:
   print result

Je me prends cette erreur : OperationalError: no such column: t1.id

J'ai essayé de regarder d'autre bout de code sur internet mais impossible de résoudre mon problème.
Je pense que le problème viens du fait que j'ai mal déclarer la clé étrangère de la table Voiture.

Est ce que quelqu’un pourrait m'aider à comprendre d’où viens le problème, et surtout me donner une piste pour essayer de le corriger.

Merci d'avance :)

  • # typo ?

    Posté par . Évalué à 5.

    la doc peewee parle d'un type ForeignKeyField, pas ForeignKey pour la déclaration de personne_id dans la classe Voiture.

    • [^] # Re: typo ?

      Posté par . Évalué à 6.

      la doc dit aussi que si tu veux une table sans clef primaire, tu dois préciser primary_key = False dans la class.

      En passant, je comprends que, sur un exemple simple, tu aies choisis de ne pas mettre de clef primaire sur la table voiture. Mais dans la pratique, je déconseille très fortement. J'ai fait pas mal de DB relationnel, et jusqu'à présent, je n'ai pas d'exemple pour lequel c'était clair qu'il ne fallait pas avoir de clef primaire.

      Pour ton exemple, dès que tu vas chercher à enrichir un peu ton modèle, l'absence de clef primaire sur Voiture risque de se faire sentir.

  • # base créée par peewee ?

    Posté par (page perso) . Évalué à 2.

    Bonjour,
    on dirait que vous avez créé la base puis vous vous y connectez avec avec peewee. Or on dirait que peewee fait quelques trucs quand c'est lui qui crée les tables (notamment il rajoute des clés primaires même si elles ne sont pas explicitement définies dans les modèles). C'est probablement cette clé primaire manquante qui provoque l'erreur.
    L'exemple suivant se comporte comme prévu :

    from peewee import *
    
    db = SqliteDatabase('test.db', pragmas={'foreign_keys': 1})
    
    class BaseModel(Model):
        class Meta:
            database = db
    
    
    class Person(BaseModel):
        name = CharField()
    
    
    class Car(BaseModel):
        name = CharField()
        person_id = ForeignKeyField(Person)
    
    db.connect()
    db.create_tables([Person, Car])
    
    alice = Person.create(name='Alice')
    bob = Person.create(name='Bob')
    
    for person in Person.select():
        print(person.id, person.name)
    
    # sortie
    # 1 Alice
    # 2 Bob
    
    twingo = Car.create(name='Twingo', person_id=alice)
    agila = Car.create(name='Agila', person_id=bob)
    mustang = Car.create(name='Mustang', person_id=alice)
    
    for car in Car.select():
        print(car.id, car.name, car.person_id)
    
    # sortie
    # 1 Twingo 1
    # 2 Agila 2
    # 3 Mustang 1
    
    q = Car.select().join(Person).where(Person.name == 'Alice')
    
    for car in q:
        print(car, car.name, car.person_id.name)
    
    # sortie
    # 1 Twingo Alice
    # 3 Mustang Alice
    
    db.close()
    

    Ceci dit, je ne connaissais pas peewee jusqu'à hier, donc à prendre avec des pincettes.

Suivre le flux des commentaires

Note : les commentaires appartiennent à ceux qui les ont postés. Nous n'en sommes pas responsables.