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 :

Utilisation de SQLAlchemy ORM


Sujet :

Python

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Octobre 2007
    Messages
    165
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2007
    Messages : 165
    Par défaut Utilisation de SQLAlchemy ORM
    Bonsoir à tous,

    Je me tire les cheveux depuis un petit moment et ... je sèche complètement...
    Je suis entrain de dev un petit soft pour le fun et surtout apprendre SQLAlchemy et je bloque

    J'initialise le tout:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    from sqlalchemy.ext.asyncio import async_sessionmaker, create_async_engine
    from sqlalchemy.orm import declarative_base
     
    DATABASE_URL = "sqlite+aiosqlite:///./db/test.db"
     
    engine = create_async_engine(DATABASE_URL, future=True, echo=True)
    async_session = async_sessionmaker(engine, expire_on_commit=False)
    Base = declarative_base()
    Puis j'ai créé 3 objects tel que:
    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
    class PremierObject(Base):
        __tablename__ = "premieretable"
     
        id: Mapped[int] = mapped_column(primary_key=True)
        name: Mapped[str] = mapped_column(String(30))
     
        deuxiemeobjets: Mapped[list["DeuxiemeObjet"]] = relationship("DeuxiemeObjet", back_populates="premierobjet")
     
     
    class DeuxiemeObjet(Base):
        __tablename__ = "deuxiemetable"
     
        id: Mapped[int] = mapped_column(primary_key=True)
        premierobjet_id: Mapped[int] = mapped_column(ForeignKey("premieretable.id"))
        name: Mapped[str] = mapped_column(String(30))
        description: Mapped[Optional[str]]
        enable: Mapped[bool] = mapped_column(Boolean, default=True)
     
        premierobjet: Mapped["PremierObjet"] = relationship("PremierObject", back_populates="deuxiemeobjets")
        troisiemeobjets: Mapped[list["TroisiemeObjet"]] = relationship("TroisiemeObjet", back_populates="deuxiemeobjet")
     
     
    class TroisiemeObjet(Base):
        __tablename__ = "troisiemetable"
     
        id: Mapped[int] = mapped_column(primary_key=True)
        deuxiemeobjet_id: Mapped[int] = mapped_column(ForeignKey("deuxiemetable.id"), nullable=True)
        description: Mapped[Optional[str]]
     
        deuxiemeobjet: Mapped[list["DeuxiemeObjet"]] = relationship("DeuxiemeObjet", back_populates="troisiemeobjets", secondary='deuxiemeobjet_troisiemeobjets')
     
     
     
    class DeuxiemeObjetTroisiemeObjet(Base):
        __tablename__ = "deuxiemeobjet_troisiemeobjets"
     
        deuxiemeobjet_id: Mapped[int] = mapped_column("deuxiemeobjet_id", Integer, ForeignKey("deuxiemetable.id"), primary_key=True)
        troisiemeobjet_id: Mapped[int] = mapped_column("troisiemeobjet_id", Integer, ForeignKey("troisiemetable.id"), primary_key=True)
     
        deuxiemeobjet: Mapped["DeuxiemeObjet"] = relationship("DeuxiemeObjet", backref="deuxiemeobjet_assoc")
        troisiemeobjet: Mapped[list["TroisiemeObjet"]] = relationship("TroisiemeObjet", backref="troisiemeobjet_assoc")
    J'arrive bien à créer mes objets, tout est inséré correctement en base.
    Par contre, quand je tente de récupérer PremierObjet de la table premieretable, j'ai bien mon objet et je récupère bien les infos de DeuxiemeObjet par contre la liaison DeuxiemeObjet -> TroisiemeObjet semble avoir un soucis parce que je ne peux pas accéder à la liste de TroisiemeObjet

    Le code complet
    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
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    from sqlalchemy import Boolean, ForeignKey, Integer, String
    from sqlalchemy.ext.asyncio import async_sessionmaker, create_async_engine
    from sqlalchemy.future import select
    from sqlalchemy.orm import declarative_base, Mapped, mapped_column, relationship
    from typing import Optional
    import asyncio
     
    DATABASE_URL = "sqlite+aiosqlite:///./test.db"
     
    engine = create_async_engine(DATABASE_URL, future=True, echo=True)
    async_session = async_sessionmaker(engine, expire_on_commit=False)
    Base = declarative_base()
     
    class PremierObject(Base):
        __tablename__ = "premieretable"
     
        id: Mapped[int] = mapped_column(primary_key=True)
        name: Mapped[str] = mapped_column(String(30))
     
        deuxiemeobjets: Mapped[list["DeuxiemeObjet"]] = relationship("DeuxiemeObjet", back_populates="premierobjet")
     
     
    class DeuxiemeObjet(Base):
        __tablename__ = "deuxiemetable"
     
        id: Mapped[int] = mapped_column(primary_key=True)
        premierobjet_id: Mapped[int] = mapped_column(ForeignKey("premieretable.id"))
        name: Mapped[str] = mapped_column(String(30))
        description: Mapped[Optional[str]]
        enable: Mapped[bool] = mapped_column(Boolean, default=True)
     
        premierobjet: Mapped["PremierObjet"] = relationship("PremierObject", back_populates="deuxiemeobjets")
        troisiemeobjets: Mapped[list["TroisiemeObjet"]] = relationship("TroisiemeObjet", back_populates="deuxiemeobjet")
     
     
    class TroisiemeObjet(Base):
        __tablename__ = "troisiemetable"
     
        id: Mapped[int] = mapped_column(primary_key=True)
        deuxiemeobjet_id: Mapped[int] = mapped_column(ForeignKey("deuxiemetable.id"), nullable=True)
        description: Mapped[Optional[str]]
     
        deuxiemeobjet: Mapped[list["DeuxiemeObjet"]] = relationship("DeuxiemeObjet", back_populates="troisiemeobjets", secondary='deuxiemeobjet_troisiemeobjets')
     
     
     
    class DeuxiemeObjetTroisiemeObjet(Base):
        __tablename__ = "deuxiemeobjet_troisiemeobjets"
     
        deuxiemeobjet_id: Mapped[int] = mapped_column("deuxiemeobjet_id", Integer, ForeignKey("deuxiemetable.id"), primary_key=True)
        troisiemeobjet_id: Mapped[int] = mapped_column("troisiemeobjet_id", Integer, ForeignKey("troisiemetable.id"), primary_key=True)
     
        deuxiemeobjet: Mapped["DeuxiemeObjet"] = relationship("DeuxiemeObjet", backref="deuxiemeobjet_assoc")
        troisiemeobjet: Mapped[list["TroisiemeObjet"]] = relationship("TroisiemeObjet", backref="troisiemeobjet_assoc")
     
     
    async def main():
        objet1 = PremierObject(name="Toto")
        objet2 = DeuxiemeObjet(premierobjet=objet1, name="objet2")
        objet3 = TroisiemeObjet(deuxiemeobjet=[objet2])
     
        async with engine.begin() as conn:
            await conn.run_sync(Base.metadata.drop_all)
            await conn.run_sync(Base.metadata.create_all)
     
        async with async_session() as session:
            async with session.begin():
                session.add(objet3)
     
        async with async_session() as session:
            async with session.begin():
                objet1 = (await session.execute(select(PremierObject).where(PremierObject.name == "Toto"))).scalars().first()
                print(objet1.deuxiemeobjets)
     
     
     
    asyncio.run(main())
    L'erreur:
    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
    51
    Traceback (most recent call last):
      File "/Users/Desktop/workspace/Python/perso/crypto/Gestionnaires/Scholars/test/test.py", line 77, in <module>
        asyncio.run(main())
      File "/Users/opt/anaconda3/envs/scholar/lib/python3.10/asyncio/runners.py", line 44, in run
        return loop.run_until_complete(main)
      File "/Users/opt/anaconda3/envs/scholar/lib/python3.10/asyncio/base_events.py", line 649, in run_until_complete
        return future.result()
      File "/Users/Desktop/workspace/Python/perso/crypto/Gestionnaires/Scholars/test/test.py", line 73, in main
        print(objet1.deuxiemeobjets)
      File "/Users/opt/anaconda3/envs/scholar/lib/python3.10/site-packages/sqlalchemy/orm/attributes.py", line 562, in __get__
        return self.impl.get(state, dict_)  # type: ignore[no-any-return]
      File "/Users/opt/anaconda3/envs/scholar/lib/python3.10/site-packages/sqlalchemy/orm/attributes.py", line 1075, in get
        value = self._fire_loader_callables(state, key, passive)
      File "/Users/opt/anaconda3/envs/scholar/lib/python3.10/site-packages/sqlalchemy/orm/attributes.py", line 1110, in _fire_loader_callables
        return self.callable_(state, passive)
      File "/Users/opt/anaconda3/envs/scholar/lib/python3.10/site-packages/sqlalchemy/orm/strategies.py", line 948, in _load_for_state
        return self._emit_lazyload(
      File "/Users/opt/anaconda3/envs/scholar/lib/python3.10/site-packages/sqlalchemy/orm/strategies.py", line 1111, in _emit_lazyload
        result = session.execute(
      File "/Users/opt/anaconda3/envs/scholar/lib/python3.10/site-packages/sqlalchemy/orm/session.py", line 2229, in execute
        return self._execute_internal(
      File "/Users/opt/anaconda3/envs/scholar/lib/python3.10/site-packages/sqlalchemy/orm/session.py", line 2124, in _execute_internal
        result: Result[Any] = compile_state_cls.orm_execute_statement(
      File "/Users/opt/anaconda3/envs/scholar/lib/python3.10/site-packages/sqlalchemy/orm/context.py", line 252, in orm_execute_statement
        result = conn.execute(
      File "/Users/opt/anaconda3/envs/scholar/lib/python3.10/site-packages/sqlalchemy/engine/base.py", line 1414, in execute
        return meth(
      File "/Users/opt/anaconda3/envs/scholar/lib/python3.10/site-packages/sqlalchemy/sql/elements.py", line 489, in _execute_on_connection
        return connection._execute_clauseelement(
      File "/Users/opt/anaconda3/envs/scholar/lib/python3.10/site-packages/sqlalchemy/engine/base.py", line 1638, in _execute_clauseelement
        ret = self._execute_context(
      File "/Users/opt/anaconda3/envs/scholar/lib/python3.10/site-packages/sqlalchemy/engine/base.py", line 1842, in _execute_context
        return self._exec_single_context(
      File "/Users/opt/anaconda3/envs/scholar/lib/python3.10/site-packages/sqlalchemy/engine/base.py", line 1983, in _exec_single_context
        self._handle_dbapi_exception(
      File "/Users/opt/anaconda3/envs/scholar/lib/python3.10/site-packages/sqlalchemy/engine/base.py", line 2328, in _handle_dbapi_exception
        raise exc_info[1].with_traceback(exc_info[2])
      File "/Users/opt/anaconda3/envs/scholar/lib/python3.10/site-packages/sqlalchemy/engine/base.py", line 1964, in _exec_single_context
        self.dialect.do_execute(
      File "/Users/opt/anaconda3/envs/scholar/lib/python3.10/site-packages/sqlalchemy/engine/default.py", line 747, in do_execute
        cursor.execute(statement, parameters)
      File "/Users/opt/anaconda3/envs/scholar/lib/python3.10/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 113, in execute
        self._adapt_connection._handle_exception(error)
      File "/Users/opt/anaconda3/envs/scholar/lib/python3.10/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 254, in _handle_exception
        raise error
      File "/Users/opt/anaconda3/envs/scholar/lib/python3.10/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 90, in execute
        _cursor = self.await_(self._connection.cursor())
      File "/Users/opt/anaconda3/envs/scholar/lib/python3.10/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 93, in await_only
        raise exc.MissingGreenlet(
    sqlalchemy.exc.MissingGreenlet: greenlet_spawn has not been called; can't call await_only() here. Was IO attempted in an unexpected place? (Background on this error at: https://sqlalche.me/e/20/xd2s)
    sys:1: RuntimeWarning: coroutine 'Connection.cursor' was never awaited
    Est-ce qu'une gentille âme serait capable de m'éclairer svp?
    Cordialement,
    Julien

  2. #2
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 753
    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 753
    Par défaut
    Citation Envoyé par m0ul3sh0t Voir le message
    Est-ce qu'une gentille âme serait capable de m'éclairer svp?
    Je ne connais pas votre background mais sqlalchemy est bien assez compliqué pour y mixer en plus de l'asyncio qui s'apprend indépendamment (et qui est de la programmation avancée Python).
    Retailler la hauteur des marches à franchir dans votre apprentissage serait une solution à explorer...

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

  3. #3
    Membre confirmé
    Profil pro
    Inscrit en
    Octobre 2007
    Messages
    165
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2007
    Messages : 165
    Par défaut
    Citation Envoyé par wiztricks Voir le message
    Je ne connais pas votre background mais sqlalchemy est bien assez compliqué pour y mixer en plus de l'asyncio qui s'apprend indépendamment (et qui est de la programmation avancée Python).
    Retailler la hauteur des marches à franchir dans votre apprentissage serait une solution à explorer...

    - W
    Mon background est 15 ans de C/CPP et une bonne année de python
    Si j'ai fait le choix de mixer sqlalchemy avec asyncio c'est en partie parce que je veux faire cohabiter le tout avec du FastAPI et surtout d'autres frameworks qui nécessitent que je travaille en asynchrone

  4. #4
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 753
    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 753
    Par défaut
    Citation Envoyé par m0ul3sh0t Voir le message
    Si j'ai fait le choix de mixer sqlalchemy avec asyncio...
    Disons que cela est la destination affichée de votre voyage... après, je ne vous suggère que quelques étapes. Et si elles ne vous semblent pas pertinentes ben tant pis (c'est vous qui ramez).

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

  5. #5
    Membre confirmé
    Profil pro
    Inscrit en
    Octobre 2007
    Messages
    165
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2007
    Messages : 165
    Par défaut
    Citation Envoyé par wiztricks Voir le message
    Disons que cela est la destination affichée de votre voyage... après, je ne vous suggère que quelques étapes. Et si elles ne vous semblent pas pertinentes ben tant pis (c'est vous qui ramez).

    - W
    Je ne suis pas venu ici pour des cours de philosophie cela dit mais je vous remercie

  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
    Bonjour

    Je rebondi vos échanges pour une question concernant la méthode de conception des tables , on voit les deux codifications cohabiter sur les extraits de code python sur le Net .

    Votre méthode basée sur sqlalchemy.orm utilise visiblement une codification de paramétrage

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    ...
    from sqlalchemy.orm import declarative_base, Mapped, mapped_column, relationship
    ...
     
    class PremierObject(Base):
        __tablename__ = "premieretable"
     
        id: Mapped[int] = mapped_column(primary_key=True)<a href="https://docs.sqlalchemy.org/en/20/orm/quickstart.html" target="_blank">https://docs.sqlalchemy.org/en/20/orm/quickstart.html</a>
        name: Mapped[str] = mapped_column(String(30))
     
        deuxiemeobjets: Mapped[list["DeuxiemeObjet"]] = relationship("DeuxiemeObjet", back_populates="premierobjet")
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    from sqlalchemy import Column, Integer, Text ,  String,  ForeignKey , BLOB , Float ,   BigInteger , Boolean, null
     
    # J'utilise pour ma part méthode basée sur sqlalchemy  une autre solution .
     
     
    class PremierObject(Base):
        __tablename__ = "premieretable"
     
        id  = Column(Integer, primary_key=True,  autoincrement=True)
        name = Column(String(30))
     
        #deuxiemeobjets: Mapped[list["DeuxiemeObjet"]] = relationship("DeuxiemeObjet", back_populates="premierobjet")
    Quelle est la différence entre les deux ?

    La méthode basée sur sqlalchemy.orm semblerait correspondre a sqlalchemy 2.0 + mais je parcours leur documentation sans trouver d'explication précises , auriez vous un point d’entrée plus explicite dans leur doc que la lien de base?


    une question sans rapport avec votre cas?

    Cython et SQLALCHEMY : dans la page d'intro sqlalchemy https://docs.sqlalchemy.org/en/20/intro.html il semble possible d'utiliser des extensions Cython inclut dans SQLAlchemy (Modifié dans la version 2.0 ) mais je recherche comment ajouter celle-ci sans grand succes. Donc si vous avez une idée je suis preneur.



    Démarrage rapide ORM https://docs.sqlalchemy.org/en/20/orm/quickstart.html

Discussions similaires

  1. Réponses: 2
    Dernier message: 23/01/2020, 09h50
  2. [Fabrique Abstraite] L'utilisation d'une ORM rend il la fabrique abstraite inutile?
    Par 3logy dans le forum Design Patterns
    Réponses: 3
    Dernier message: 21/05/2014, 11h08
  3. utilisation des fichiers **.orm.yml
    Par MarronSuisse dans le forum Doctrine2
    Réponses: 0
    Dernier message: 25/02/2012, 02h21
  4. Quel ORM utiliser?
    Par Thomas.NET dans le forum Accès aux données
    Réponses: 22
    Dernier message: 13/04/2010, 16h46
  5. Comment s'utilise l'ORM avec ce framework ?
    Par sir_gcc dans le forum Zend_Db
    Réponses: 13
    Dernier message: 20/01/2008, 13h03

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