Maison  >  Article  >  développement back-end  >  Un outil magique pour les débutants pour apprendre Python et jouer avec SQL en cinq minutes !

Un outil magique pour les débutants pour apprendre Python et jouer avec SQL en cinq minutes !

WBOY
WBOYavant
2023-04-12 17:28:151720parcourir

Un outil magique pour les débutants pour apprendre Python et jouer avec SQL en cinq minutes !

Contexte

En fait, j'ai utilisé pymysql au début, mais j'ai trouvé que la maintenance était gênante et qu'il y avait un risque d'injection de code, j'ai donc simplement utilisé directement le framework ORM.

ORM est Object Relational Mapper, qui peut être simplement compris comme le mappage entre les tables de base de données et les classes Python. En exploitant des classes Python, vous pouvez indirectement exploiter la base de données.

Les frameworks Python ORM les plus connus sont SQLAlchemy et Peewee. Je ne ferai pas de comparaison ici, mais expliquerai simplement une utilisation personnelle de SQLAlchemy. J'espère que cela pourra être utile à tous mes amis.

  • version sqlalchemy : 1.3.15
  • version pymysql : 0.9.3
  • version mysql : 5.7

Travail d'initialisation

Généralement, lors de l'utilisation d'un framework ORM, il y aura un travail d'initialisation, tel que la connexion à une base de données, définir une cartographie de base, etc.

Prenons MySQL comme exemple. Pour créer une connexion à une base de données, il vous suffit de transmettre la chaîne DSN. Echo indique s'il faut afficher l'instruction SQL correspondante, ce qui est utile pour le débogage.

from sqlalchemy import create_engine
engine = create_engine('mysql+pymysql://$user:$password@$host:$port/$db?charset=utf8mb4', echo=True)

Conception personnelle

Pour moi personnellement, lors de l'introduction du framework ORM, mon projet fera référence au modèle MVC pour la conception suivante. Parmi eux, model stocke certains modèles de base de données, c'est-à-dire les classes Python mappées aux tables de base de données ; model_op stocke les opérations correspondant à chaque modèle, c'est-à-dire l'ajout, la suppression, la vérification et la modification lorsque l'appelant (comme main.py) ; effectue des opérations de base de données, il lui suffit d'appeler la couche model_op, vous n'avez pas besoin de vous soucier de la couche modèle pour réaliser le découplage.

├── main.py
├── model
│ ├── __init__.py
│ ├── base_model.py
│ ├── ddl.sql
│ └── py_orm_model.py
└── model_op
 ├── __init__.py
 └── py_orm_model_op.py

Instruction de mappage (introduction du modèle)

Par exemple, si nous avons une telle table de test

create table py_orm (
 `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '唯一id',
 `name` varchar(255) NOT NULL DEFAULT '' COMMENT '名称',
 `attr` JSON NOT NULL COMMENT '属性',
 `ct` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
 `ut` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON update CURRENT_TIMESTAMP COMMENT '更新时间',
 PRIMARY KEY(`id`)
)ENGINE=InnoDB COMMENT '测试表';

Dans le framework ORM, le résultat du mappage est la classe Python ci-dessous

# py_orm_model.py
from .base_model import Base
from sqlalchemy import Column, Integer, String, TIMESTAMP, text, JSON
class PyOrmModel(Base):
 __tablename__ = 'py_orm'
 id = Column(Integer, autoincrement=True, primary_key=True, comment='唯一id')
 name = Column(String(255), nullable=False, default='', comment='名称')
 attr = Column(JSON, nullable=False, comment='属性')
 ct = Column(TIMESTAMP, nullable=False, server_default=text('CURRENT_TIMESTAMP'), comment='创建时间')
 ut = Column(TIMESTAMP, nullable=False, server_default=text('CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP'), comment='更新时间')

Tout d'abord, nous pouvons voir l'héritage PyOrmModel. La classe de base est une classe de base fournie par sqlalchemy. Elle effectuera quelques vérifications sur la classe Python que nous avons déclarée. Je l'ai mise dans base_model.

# base_model.py
# 一般base_model做的都是一些初始化的工作
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
engine = create_engine("mysql+pymysql://root:123456@127.0.0.1:33306/orm_test?charset=utf8mb4", echo=False)

Deuxièmement, chaque classe Python doit contenir l'attribut __tablename__, sinon la table correspondante est introuvable.

Troisièmement, il existe deux façons de créer une table de données. La première consiste bien sûr à la créer manuellement dans MySQL. Tant qu'il n'y a aucun problème avec la définition de votre classe Python, elle peut fonctionner normalement ; via le framework ORM, comme ci-dessous :

# main.py
# 注意这里的导入路径,Base创建表时会寻找继承它的子类,如果路径不对,则无法创建成功
from sqlachlemy_lab import Base, engine
if __name__ == '__main__':
 Base.metadata.create_all(engine)

Effet de création :

...
2020-04-04 10:12:53,974 INFO sqlalchemy.engine.base.Engine
CREATE TABLE py_orm (
id INTEGER NOT NULL AUTO_INCREMENT,
name VARCHAR(255) NOT NULL DEFAULT '' COMMENT '名称',
attr JSON NOT NULL COMMENT '属性',
ct TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
ut TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
 PRIMARY KEY (id)
)

Quatrièmement, concernant les attributs de champ

  • 1.primary_key et autoincrement sont plus faciles à comprendre, ce sont la clé primaire et les attributs incrémentiels de MySQL.
  • 2. S'il s'agit d'un type int, vous n'avez pas besoin de spécifier la longueur, mais s'il s'agit d'un type varchar, vous devez la spécifier.
  • 3.nullable correspond à NULL et NOT NULL dans MySQL
  • 4 À propos de default et server_default : default représente la valeur par défaut au niveau du framework ORM, c'est-à-dire que si aucune valeur n'est attribuée au champ lors de l'insertion, notre définition le fera. être utilisé La valeur par défaut ; server_default représente la valeur par défaut au niveau de la base de données, c'est-à-dire le mot-clé par défaut dans l'instruction DDL.

Introduction à la session

Il est mentionné dans la documentation SQLAlchemy que les ajouts, suppressions et modifications à la base de données sont effectués via des sessions.

>>> from sqlalchemy.orm import sessionmaker
>>> Session = sessionmaker(bind=engine)
>>> session = Session()
>>> orm = PyOrmModel(id=1, name='test', attr={})
>>> session.add(orm)
>>> session.commit()
>>> session.close()

Comme ci-dessus, nous pouvons voir que pour chaque opération, nous devons acquérir, soumettre et libérer la session. C'est trop redondant et gênant, nous effectuons donc généralement une couche d'encapsulation.

1. Utilisez le gestionnaire de contexte pour gérer l'annulation et la fermeture anormales de la session. Cette partie est presque cohérente avec l'article référencé.

# base_model.py
from contextlib import contextmanager
from sqlalchemy.orm import sessionmaker, scoped_session
def _get_session():
 """获取session"""
 return scoped_session(sessionmaker(bind=engine, expire_on_commit=False))()
# 在这里对session进行统一管理,包括获取,提交,回滚和关闭
@contextmanager
def db_session(commit=True):
 session = _get_session()
 try:
 yield session
 if commit:
 session.commit()
 except Exception as e:
 session.rollback()
 raise e
 finally:
 if session:
 session.close()

2. Ajoutez deux méthodes dans PyOrmModel pour la conversion entre modèle et dict

class PyOrmModel(Base):
 ...
 @staticmethod
 def fields():
 return ['id', 'name', 'attr']
 @staticmethod
 def to_json(model):
 fields = PyOrmModel.fields()
 json_data = {}
 for field in fields:
 json_data[field] = model.__getattribute__(field)
 return json_data
 @staticmethod
 def from_json(data: dict):
 fields = PyOrmModel.fields()
 model = PyOrmModel()
 for field in fields:
 if field in data:
 model.__setattr__(field, data[field])
 return model

3 Encapsulation des opérations de base de données Différent de l'article de référence, j'ai directement appelé la session, afin que l'appelant n'ait pas besoin d'y prêter attention. la couche de modèle et réduire le couplage.

# py_orm_model_op.py
from sqlachlemy_lab.model import db_session
from sqlachlemy_lab.model import PyOrmModel
class PyOrmModelOp:
 def __init__(self):
 pass
 @staticmethod
 def save_data(data: dict):
 with db_session() as session:
 model = PyOrmModel.from_json(data)
 session.add(model)
 # 查询操作,不需要commit
 @staticmethod
 def query_data(pid: int):
 data_list = []
 with db_session(commit=False) as session:
 data = session.query(PyOrmModel).filter(PyOrmModel.id == pid)
 for d in data:
 data_list.append(PyOrmModel.to_json(d))
 return data_list

4. Appelant

# main.py
from sqlachlemy_lab.model_op import PyOrmModelOp
if __name__ == '__main__':
 PyOrmModelOp.save_data({'id': 1, 'name': 'test', 'attr': {}})

Pour le code complet, veuillez consulter :

​https://github.com/yangancode/python_lab/tree/master/sqlachlemy_lab​

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer