Vous avez peut-être entendu parler du mappage objet-relationnel (ORM). Vous en avez peut-être même utilisé un, mais que sont-ils exactement ? Et comment les utilisez-vous en Python ?
Voici tout ce que vous devez savoir sur les ORM et Python.
Le mappage objet-relationnel (ORM) est une technique de programmation utilisée pour accéder à une base de données. Il expose votre base de données dans une série d'objets. Vous n'avez pas besoin d'écrire des commandes SQL pour insérer ou récupérer des données, vous utilisez une série d'attributs et de méthodes attachés aux objets.
Cela peut sembler complexe et inutile, mais ils peuvent vous faire gagner beaucoup de temps et vous aider à contrôler l'accès à votre base de données.
Voici un exemple. Supposons que chaque fois que vous insérez un mot de passe dans votre base de données, vous souhaitez le hacher, comme expliqué dans la section Sécurité des mots de passe du site Web. Ce n'est pas un problème pour les cas d'utilisation simples --- vous faites le calcul avant l'insertion. Mais que se passe-t-il si vous devez insérer un enregistrement à plusieurs endroits dans le code ? Que se passe-t-il si un autre programmeur s'insère dans votre table et que vous ne le savez pas ?
En utilisant un ORM, vous pouvez écrire du code pour vous assurer que chaque fois que vous accédez à une ligne ou à un champ de votre base de données, votre autre code personnalisé est exécuté en premier.
Cela agit également comme une "source unique de vérité". Si vous souhaitez modifier un calcul personnalisé, vous n'avez qu'à le modifier à un seul endroit, pas à plusieurs. Il est possible d'appliquer bon nombre de ces principes avec la programmation orientée objet (POO) en Python, mais les ORM fonctionnent en tandem avec les principes de la POO pour contrôler l'accès à une base de données.
Il y a certaines choses à surveiller lors de l'utilisation d'un ORM, et il y a des circonstances où vous ne voudrez peut-être pas en utiliser un, mais elles sont généralement considérées comme une bonne chose à avoir, surtout dans une grande base de code.
Comme de nombreuses tâches en Python, il est plus rapide et plus facile d'importer un module que d'écrire le vôtre. Bien sûr, il est possible d'écrire votre propre ORM, mais pourquoi réinventer la roue ?
Les exemples suivants utilisent tous SQLAlchemy, un ORM Python populaire, mais de nombreux principes s'appliquent quelle que soit l'implémentation.
Avant de vous lancer, vous devrez configurer votre machine pour le développement Python avec SQLAlchemy.
Vous devrez utiliser Python 3.6 pour suivre ces exemples. Bien que les anciennes versions fonctionnent, le code ci-dessous nécessitera quelques modifications avant de s'exécuter. Vous n'êtes pas sûr des différences? Notre FAQ Python couvre toutes les différences.
Avant de coder, vous devez configurer un environnement Python, ce qui évitera les problèmes avec d'autres packages Python importés.
Assurez-vous d'avoir installé PIP, le gestionnaire de packages Python, qui est fourni avec la plupart des versions modernes de Python.
Une fois que vous êtes prêt à commencer, vous pouvez commencer par préparer SQLAlchemy. Depuis votre environnement Python dans la ligne de commande, installez SQLAlchemy avec le pip install commande :
pip installer SQLAlchemy-1.2.9
La 1.2.9 est le numéro de version. Vous pouvez laisser cette option désactivée pour obtenir le dernier package, mais il est recommandé d'être précis. Vous ne savez pas quand une nouvelle version peut casser votre code actuel.
Vous êtes maintenant prêt à commencer à coder. Vous devrez peut-être préparer votre base de données pour accepter une connexion Python, mais les exemples suivants utilisent tous une base de données SQLite créée en mémoire ci-dessous.
L'un des composants clés d'un ORM est un modèle . Il s'agit d'une classe Python qui décrit à quoi devrait ressembler une table et comment elle devrait fonctionner. C'est la version ORM de CREATE TABLE instruction en SQL. Vous avez besoin d'un modèle pour chaque table de votre base de données.
Ouvrez votre éditeur de texte ou IDE préféré et créez un nouveau fichier appelé test.py . Saisissez ce code de démarrage, enregistrez le fichier et exécutez-le :
à partir de sqlalchemy import create_engine
depuis sqlalchemy.ext.declarative import declarative_base
Base =base_déclarative()
engine =create_engine('sqlite://') # Crée la base de données en mémoire
Base.metadata.create_all(engine) # Crée toutes les tables de la base de données
Ce code fait plusieurs choses. Les importations sont nécessaires pour que Python comprenne où trouver les modules SQLAlchemy dont il a besoin. Vos modèles utiliseront la declarative_base plus tard, et il configure tous les nouveaux modèles pour qu'ils fonctionnent comme prévu.
Le create_engine La méthode crée une nouvelle connexion à votre base de données. Si vous avez déjà une base de données, vous devrez changer sqlite:// à l'URI de votre base de données. En l'état, ce code créera une nouvelle base de données en mémoire uniquement. La base de données est détruite une fois l'exécution de votre code terminée.
Enfin, le create_all La méthode crée toutes les tables définies dans vos modes dans votre base de données. Comme vous n'avez pas encore défini de modèles, rien ne se passera. Allez-y et exécutez ce code pour vous assurer qu'il n'y a pas de problèmes ou de fautes de frappe.
Faisons un modèle. Ajoutez une autre importation en haut de votre fichier :
de sqlalchemy import Column, Integer, String
Cela importe la colonne , Entier , et Chaîne modules de SQLAlchemy. Ils définissent le fonctionnement des tables, des champs, des colonnes et des types de données de la base de données.
Sous la declarative_base , créez votre classe de modèle :
class Cars(Base) :
__tablename__ ='voitures'
id =Column(Integer, primary_key=True)
make =Column(String(50), nullable=False)
couleur =Colonne(Chaîne(50), nullable=Faux)
Cet exemple simple utilise des voitures, mais vos tables peuvent contenir n'importe quelles données.
Chaque classe doit hériter de Base . Le nom de votre table de base de données est défini dans __tablename__ . Cela devrait être le même que le nom de la classe, mais ce n'est qu'une recommandation, et rien ne se cassera s'ils ne correspondent pas.
Enfin, chaque colonne est définie comme une variable python dans la classe. Différents types de données sont utilisés et la primary_key l'attribut indique à SQLAlchemy de créer l'id colonne comme clé primaire.
Allez-y et ajoutez une dernière importation, cette fois pour la ForeignKey module. Ajoutez ceci à côté de votre colonne importer :
de la colonne d'importation sqlalchemy, ForeignKey, Integer, String
Créez maintenant une deuxième classe de modèle. Cette classe s'appelle CarOwners , et stocke les détails du propriétaire de voitures spécifiques stockées dans Cars tableau :
class CarOwners(Base) :
__tablename__ ='carowners'
id =Column(Integer, primary_key=True)
nom =colonne (chaîne (50), nullable =faux)
âge =colonne (entier, nullable =faux)
car_id =Colonne (Entier, ForeignKey ('cars.id'))
voiture =relation(Voitures)
Il y a plusieurs nouveaux attributs introduits ici. Le car_id champ est défini comme une clé étrangère. Il est lié à l'id dans les voitures table. Remarquez comment le nom de table en minuscules est utilisé, à la place du nom de classe en majuscules.
Enfin, un attribut de voiture est défini comme une relation . Cela permet à votre modèle d'accéder aux Voitures tableau via cette variable. Ceci est démontré ci-dessous.
Si vous exécutez ce code maintenant, vous verrez que rien ne se passe. C'est parce que vous ne lui avez pas encore dit de faire quoi que ce soit de notable.
Maintenant que vos modèles sont créés, vous pouvez commencer à accéder aux objets, lire et écrire des données. C'est une bonne idée de placer votre logique dans sa propre classe et son propre fichier, mais pour l'instant, elle peut rester à côté des modèles.
Dans cet exemple, vous devez insérer des données dans la base de données avant de pouvoir les lire. Si vous utilisez une base de données existante, vous disposez peut-être déjà de données. Quoi qu'il en soit, il est toujours très utile de savoir comment insérer des données.
Vous avez peut-être l'habitude d'écrire INSERT instructions en SQL. SQLAlchemy gère cela pour vous. Voici comment insérer une ligne dans les Voitures maquette. Commencez par une nouvelle importation pour sessionmaker :
de sqlalchemy.orm import sessionmaker
Ceci est nécessaire pour créer la session et DBSession objets, qui sont utilisés pour lire et écrire des données :
DBSession =sessionmaker(bind=engine)
session =DBSession()
Maintenant, placez ceci sous votre create_all déclaration :
car1 =Voitures(
make="Ford",
couleur="argent"
)
session.add(car1)
session.commit()
Décomposons ce code. La variable voiture1 est défini comme un objet basé sur les Cars maquette. Sa marque et sa couleur sont définies comme paramètres. C'est comme dire "faites-moi une voiture, mais ne l'écrivez pas encore dans la base de données". Cette voiture existe en mémoire mais attend d'être écrite.
Ajoutez la voiture à la session avec session.add , puis écrivez-le dans la base de données avec session.commit .
Ajoutons maintenant un propriétaire :
owner1 =CarOwners(
nom="Joe",
âge="99",
voiture_id=(voiture1.id)
)
session.add(propriétaire1)
session.commit()
Ce code est presque identique à l'encart précédent pour les Cars maquette. La principale différence ici est que car_id est une clé étrangère et a donc besoin d'un identifiant de ligne qui existe dans l'autre table. Ceci est accessible via le car1.id propriété.
Vous n'avez pas besoin d'interroger la base de données ou de renvoyer des identifiants, car SQLAlchemy s'en charge pour vous (tant que vous validez d'abord les données).
Une fois que vous avez écrit certaines données, vous pouvez commencer à les relire. Voici comment interroger les Cars et Propriétaires de voitures tableaux :
result =session.query(Cars).all()
C'est aussi simple que cela. En utilisant la requête méthode trouvée dans la session , vous spécifiez le modèle, puis utilisez le tout méthode pour récupérer tous les résultats. Si vous savez qu'il n'y aura qu'un seul résultat, vous pouvez utiliser le premier méthode :
result =session.query(Cars).first()
Une fois que vous avez interrogé le modèle et stocké les résultats renvoyés dans une variable, vous pouvez accéder aux données via l'objet :
imprimer(result[0].color)
Cela imprime la couleur "argent", car cet enregistrement est la première ligne. Vous pouvez boucler sur l'objet de résultat si vous le souhaitez.
Comme vous avez défini la relation dans votre modèle, il est possible d'accéder aux données des tables associées sans spécifier de jointure :
résultat =session.query(CarOwners).all()
impression(résultat[0].nom)
imprimer(result[0].car.color)
Cela fonctionne car votre modèle contient des détails sur la structure de votre table et la voiture l'attribut a été défini comme un lien vers les voitures tableau.
Ce didacticiel ne couvrait que les bases, mais une fois que vous les maîtrisez, vous pouvez passer aux sujets avancés. Les ORM présentent certains inconvénients potentiels :
Ces problèmes ne sont pas un gros problème en eux-mêmes, mais ce sont des choses à surveiller. Si vous travaillez avec une base de données existante, vous risquez d'être pris au dépourvu.
Si vous n'êtes pas convaincu qu'un ORM est le bon outil pour vous, assurez-vous de lire les importantes commandes SQL que les programmeurs doivent connaître.