IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Python Discussion :

SQL ALCHEMY retroEngenierie


Sujet :

Python

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé Avatar de dedalios
    Homme Profil pro
    concepteur d'application
    Inscrit en
    Février 2008
    Messages
    495
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Indre et Loire (Centre)

    Informations professionnelles :
    Activité : concepteur d'application
    Secteur : Santé

    Informations forums :
    Inscription : Février 2008
    Messages : 495
    Par défaut SQL ALCHEMY retroEngenierie
    bonjour

    Je cherche a construire la structure des tables d'une base de données sous la forme de code Python.
    J'ai découvert sqlacodegen pour outil de 2020.

    L'installation sous Pip pip install sqlacodegen est simple et la commande en ligne sqlacodegen sqlite:///Base.DB --outfile base.py permet de recrééer la structure de cette base SQLlite.


    Il s'agit d'un outil qui lit la structure d'une base de données existante et génère les Code du modèle SQLAlchemy, en utilisant le style déclaratif si possible.

    Cet outil a été écrit pour remplacer sqlautocode , qui souffrait de plusieurs problèmes (y compris, mais sans s'y limiter, l'incompatibilité avec Python 3 et la dernière version de SQLAlchemy).


    Mais voila tous n'est pas aussi simple.

    voici ma petite base créer en SQL 2 tables et une vue


    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    CREATE TABLE "Marque" (
    	IdMarque INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
    	nom TEXT,
    	descrition TEXT
    );
     
     
     
    CREATE TABLE "Appareil_photo" (
    	IdAppareil INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
    	nom TEXT,
    	IdMarque INTEGER  NOT NULL CONSTRAINT FK_IdMarque
    	  REFERENCES "Marque" (IdMarque), 
    	date_ac DATETIME
    );
     
     
     
     
    create view canon as 
    select ap.* , m.nom  
    from "Appareil_photo" ap  inner join "Marque" m
    on ap.IdMarque  = m.IdMarque 
    and   m.IdMarque ='Canon';

    Nom : CaptureBase.PNG
Affichages : 618
Taille : 13,2 Ko

    l'utilisation de la commande d'extraction donne ce code

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    # coding: utf-8
    from sqlalchemy import Column, DateTime, ForeignKey, Integer, Table, Text
    from sqlalchemy.sql.sqltypes import NullType
    from sqlalchemy.orm import relationship
    from sqlalchemy.ext.declarative import declarative_base 
    from sqlalchemy import create_engine
     
     
     
    Base = declarative_base()
    metadata = Base.metadata
     
     
    class Marque(Base):
        __tablename__ = 'Marque'
     
        IdMarque = Column(Integer, primary_key=True)
        nom = Column(Text)
        descrition = Column(Text)
     
     
    t_canon = Table(
        'canon', metadata,
        Column('IdAppareil', Integer),
        Column('nom', Text),
        Column('IdMarque', Integer),
        Column('date_ac', DateTime),
        Column('nom:1', Text)
    )
     
     
    t_sqlite_sequence = Table(
        'sqlite_sequence', metadata,
        Column('name', NullType),
        Column('seq', NullType)
    )
     
     
    class AppareilPhoto(Base):
        __tablename__ = 'Appareil_photo'
     
        IdAppareil = Column(Integer, primary_key=True)
        nom = Column(Text)
        IdMarque = Column(ForeignKey('Marque.IdMarque'), nullable=False)
        date_ac = Column(DateTime)
     
        Marque = relationship('Marque')
    on retrouve donc nos 2 classes liées aux 2 tables mais aucune trace de la vue.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    class Marque(Base):
        __tablename__ = 'Marque'
     
        IdMarque = Column(Integer, primary_key=True)
        nom = Column(Text)
        descrition = Column(Text)
     
     
    class AppareilPhoto(Base):
        __tablename__ = 'Appareil_photo'
     
        IdAppareil = Column(Integer, primary_key=True)
        nom = Column(Text)
        IdMarque = Column(ForeignKey('Marque.IdMarque'), nullable=False)
        date_ac = Column(DateTime)
     
        Marque = relationship('Marque')
    Si l'on cherche à utiliser le code en l'état en ajoutant le moteurs de création de la base
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    engine = create_engine('sqlite:///basephoto.db')
     
    Base.metadata.create_all(engine)    # Only for the first time
    L'exécution renvoi une erreur pour chaque table
    raise exception
    sqlalchemy.exc.CompileError: (in table 'sqlite_sequence', column 'name'): Can't generate DDL for NullType(); did you forget to specify a type on this Column?
    Mais la base est créer mais n'est pas identique au modèle d'Origine.

    Nom : CaptureBase2.PNG
Affichages : 592
Taille : 4,3 Ko

    et le code SQL produit est très différent la vue a disparue et la dépendance entre le 2 table aussi

    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    -- canon definition
     
    CREATE TABLE canon (
    	"IdAppareil" INTEGER, 
    	nom TEXT, 
    	"IdMarque" INTEGER, 
    	date_ac DATETIME, 
    	"nom:1" TEXT
    );
     
     
    -- Marque definition
     
    CREATE TABLE "Marque" (
    	"IdMarque" INTEGER NOT NULL, 
    	nom TEXT, 
    	descrition TEXT, 
    	PRIMARY KEY ("IdMarque")
    );


    • L'autoincrementation a disparue
    • La relation entre les deux tables a disparue


    Dommage .....

    Question existe-t-il des outils similaires et p pour permettre de recréer le code python à partir d'un base de données ?

    Et est-il possible de créer une vue avec sqlalchemy?

  2. #2
    Membre éclairé Avatar de dedalios
    Homme Profil pro
    concepteur d'application
    Inscrit en
    Février 2008
    Messages
    495
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Indre et Loire (Centre)

    Informations professionnelles :
    Activité : concepteur d'application
    Secteur : Santé

    Informations forums :
    Inscription : Février 2008
    Messages : 495
    Par défaut Je continue
    Je reprends le code autogéré et je le modifie pour ajouter la couche des relations entre les 2 tables

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    # coding: utf-8
    from sqlalchemy import Column, DateTime, ForeignKey, Integer, Table, Text
    from sqlalchemy.sql.sqltypes import NullType
    from sqlalchemy.orm import relationship
    from sqlalchemy.ext.declarative import declarative_base 
    from sqlalchemy import create_engine
     
    Base = declarative_base()
    metadata = Base.metadata
     
     
    class Marque(Base):
        __tablename__ = 'Marque'
     
        IdMarque = Column(Integer, primary_key=True, autoincrement =True)
        nom = Column(Text)
        descrition = Column(Text)
     
        Marque = relationship('Marque',  back_populates="AppareilPhoto")
     
     
     
    class AppareilPhoto(Base):
        __tablename__ = 'Appareil_photo'
     
        IdAppareil = Column(Integer, primary_key=True)
        nom = Column(Text)
        IdMarque = Column(Integer, ForeignKey('Marque.IdMarque'), nullable=False)
        date_ac = Column(DateTime)
     
        Appareil = relationship('Appareil',  back_populates="Marque")
     
     
    engine = create_engine('sqlite:///basephoto2.db')
     
    Base.metadata.create_all(engine)    # Only for the first time
    cette fois le résultat est mieux


    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    -- Marque definition
     
    CREATE TABLE "Marque" (
    	"IdMarque" INTEGER NOT NULL, 
    	nom TEXT, 
    	descrition TEXT, 
    	PRIMARY KEY ("IdMarque")
    );
     
     
    -- Appareil_photo definition
     
    CREATE TABLE "Appareil_photo" (
    	"IdAppareil" INTEGER NOT NULL, 
    	nom TEXT, 
    	"IdMarque" INTEGER NOT NULL, 
    	date_ac DATETIME, 
    	PRIMARY KEY ("IdAppareil"), 
    	FOREIGN KEY("IdMarque") REFERENCES "Marque" ("IdMarque")
    );

    on a bien la relation

    Nom : CaptureBase3.PNG
Affichages : 581
Taille : 4,5 Ko


    reste la question de la vue....

    Je fait simple je vais ajouter ma vue via la commande SQL d'exécution

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    # coding: utf-8
    from sqlalchemy import Column, DateTime, ForeignKey, Integer, Table, Text
    from sqlalchemy.sql.sqltypes import NullType
    from sqlalchemy.orm import relationship
    from sqlalchemy.ext.declarative import declarative_base 
    from sqlalchemy import create_engine , text
    from sqlalchemy.orm import scoped_session, sessionmaker, relationship
     
    Base = declarative_base()
    metadata = Base.metadata
     
     
    class Marque(Base):
        __tablename__ = 'Marque'
     
        IdMarque = Column(Integer, primary_key=True, autoincrement =True)
        nom = Column(Text)
        descrition = Column(Text)
     
        Marque = relationship('Marque',  back_populates="AppareilPhoto")
     
     
     
    class AppareilPhoto(Base):
        __tablename__ = 'Appareil_photo'
     
        IdAppareil = Column(Integer, primary_key=True)
        nom = Column(Text)
        IdMarque = Column(Integer, ForeignKey('Marque.IdMarque'), nullable=False)
        date_ac = Column(DateTime)
     
        Appareil = relationship('Appareil',  back_populates="Marque")
     
     
    engine = create_engine('sqlite:///basephoto3.db')
     
    Base.metadata.create_all(engine)    # Only for the first time
     
     
    sql_vue ="""create view canon as 
    select ap.* , m.nom  
    from "Appareil_photo" ap  inner join "Marque" m
    on ap.IdMarque  = m.IdMarque 
    and   m.IdMarque ='Canon'"""
     
     
    Session = sessionmaker(bind=engine) # session dédie au evis
    Session_sur_la_base = Session()
    Session_sur_la_base.execute(sql_vue)
    Session_sur_la_base.commit()
    Ma vue est présente mais je n'utilise pas de solution spécifique à sqlachemy j'exécute le code SQL....

    j'aimerais trouver la solution, je parcours la doc de sqlachemy mais ne trouve aucune solution fonctionnant avec la version actuelle 1.4xxx

    Alors des idées ?

  3. #3
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 754
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 754
    Par défaut
    Salut,

    Dans la mini-documentation de sqlacodegen il est mentionné:
    Getting help

    If you have problems or other questions, you can either:

    Ask on the SQLAlchemy Google group, or
    Ask on the #sqlalchemy channel on Freenode IRC
    note: Si on doit écrire une application sur des tables déjà existantes (parce qu'utilisées par d'autres applications par exemple), il peut y avoir un intérêt à ne pas écrire les "class" correspondantes (sqlalchemy est déjà capable de "mapper" des tables existantes pourvu qu'on connaisse leur nom) mais le reste de l'application devra bien accéder aux attributs et sauf cas très particulier, connaître leur nom...
    Là où ça peut devenir cocasse, c'est lorsque les tables sont mises à jour: s'il n'y a rien pour le détecter, l'application risque de mettre à mal l'intégrité des données de la base.
    Tout ça pour dire que l'intérêt de ce genre d'outils est assez réduit qu'ils sont a utiliser avec précaution.

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  4. #4
    Membre éclairé Avatar de dedalios
    Homme Profil pro
    concepteur d'application
    Inscrit en
    Février 2008
    Messages
    495
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Indre et Loire (Centre)

    Informations professionnelles :
    Activité : concepteur d'application
    Secteur : Santé

    Informations forums :
    Inscription : Février 2008
    Messages : 495
    Par défaut
    Effectivement plus je cherche a appréhender l'ORM d'SQLALCHEMY et les ADD-on que l'on trouve , plus je me demande s'il plus pertinente que risqué de l'utiliser avec des bases de donnée existante....

  5. #5
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 754
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 754
    Par défaut
    Citation Envoyé par dedalios Voir le message
    plus je me demande s'il plus pertinente que risqué de l'utiliser avec des bases de donnée existante....
    On peut le faire ...
    La question que vous vous posez est autre: faut-il écrire ses "class" à la main ou peut-on utiliser des sqlacodegen pour l'automatiser. Voire le support par sqlacodegen des "view".
    Ce que j'essaie de dire, c'est qu'automatiser la fabrication des "class" aidera mais un tout petit peu.

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  6. #6
    Membre éclairé Avatar de dedalios
    Homme Profil pro
    concepteur d'application
    Inscrit en
    Février 2008
    Messages
    495
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Indre et Loire (Centre)

    Informations professionnelles :
    Activité : concepteur d'application
    Secteur : Santé

    Informations forums :
    Inscription : Février 2008
    Messages : 495
    Par défaut
    Citation Envoyé par wiztricks Voir le message
    On peut le faire ...
    La question que vous vous posez est autre: faut-il écrire ses "class" à la main ou peut-on utiliser des sqlacodegen pour l'automatiser. Voire le support par sqlacodegen des "view".
    Ce que j'essaie de dire, c'est qu'automatiser la fabrication des "class" aidera mais un tout petit peu.

    - W
    l'outil sqlacodegen est un outil qui apporte de l'aide mais .

    Mais ce n'est pas tous sqlalchemy.

    sqlacodegen ne vois pas les vue, soit mais les outils intégrés dans SQLALCHEMY ne sont pas simple a appréhender

    INspect ....

  7. #7
    Membre éclairé Avatar de dedalios
    Homme Profil pro
    concepteur d'application
    Inscrit en
    Février 2008
    Messages
    495
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Indre et Loire (Centre)

    Informations professionnelles :
    Activité : concepteur d'application
    Secteur : Santé

    Informations forums :
    Inscription : Février 2008
    Messages : 495
    Par défaut Constat sur SQLALCHEMY
    bonjour

    J'ai cherche a réaliser des tests comparatif entre 2 requêtes :
    l'une utilise les solutions de reflexion d'SQLALCHEMY l'autre une requête simple toutes 2 sur une base Oracle.
    La requête est une simple extraction d'un enregistrement réalisé sur une table .
    La requête porte sur un index de la table.

    Le commande reflect() n'embarque que la seule est unique table du Test.

    Le délai de du traitement avec la solution SQLALCHEMY est 10 fois plus longue que la solution utilisant une requête SQL.

    L'ORM n'est très performant dans ce cas

Discussions similaires

  1. [Python 3.X] chercher des données entre python, SQL Alchemy et flask
    Par sulti dans le forum Interfaçage autre langage
    Réponses: 4
    Dernier message: 21/03/2021, 15h08
  2. [2012] Problème de connexion ODBC avec SQL Alchemy
    Par Nico820 dans le forum Administration
    Réponses: 2
    Dernier message: 09/12/2016, 14h20
  3. [Python 2.X] SQL Alchemy, jointure d'une table avec une liste
    Par bstevy dans le forum Général Python
    Réponses: 3
    Dernier message: 19/02/2016, 01h12
  4. Cours, tutoriels, logiciels, F.A.Q,... pour le langage SQL
    Par Marc Lussac dans le forum Langage SQL
    Réponses: 0
    Dernier message: 04/04/2002, 10h21

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo