Rumah  >  Artikel  >  pembangunan bahagian belakang  >  Artifak Python yang sangat mudah untuk menggunakan SQL!

Artifak Python yang sangat mudah untuk menggunakan SQL!

PHPz
PHPzke hadapan
2023-04-18 16:19:031126semak imbas

Artifak Python yang sangat mudah untuk menggunakan SQL!

Latar Belakang

Malah, saya menggunakan pymysql pada mulanya, tetapi mendapati penyelenggaraan menyusahkan dan terdapat risiko suntikan kod, jadi saya hanya menggunakan ORM rangka kerja secara langsung.

ORM ialah Object Relational Mapper, yang boleh difahami secara ringkas sebagai pemetaan antara jadual pangkalan data dan kelas Python Dengan mengendalikan kelas Python, anda boleh mengendalikan pangkalan data secara tidak langsung.

Rangka kerja ORM Python yang lebih terkenal ialah SQLAlchemy dan Peewee Saya tidak akan membuat perbandingan di sini, tetapi hanya menerangkan beberapa kegunaan peribadi SQLAlchemy saya harap ia dapat membantu semua rakan saya.

  • versi sqlalchemy: 1.3.15
  • versi pymysql: 0.9.3
  • versi mysql: 5.7
permulaan >

Secara amnya, apabila menggunakan rangka kerja ORM, akan terdapat beberapa kerja permulaan, seperti sambungan pangkalan data, menentukan pemetaan asas, dsb.

Ambil MySQL sebagai contoh Untuk membuat sambungan pangkalan data, anda hanya perlu menghantar rentetan DSN. Echo menunjukkan sama ada untuk mengeluarkan pernyataan SQL yang sepadan, yang berguna untuk penyahpepijatan.

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

Bagi saya secara peribadi, apabila memperkenalkan rangka kerja ORM, projek saya akan merujuk kepada corak MVC untuk reka bentuk berikut. Antaranya, model menyimpan beberapa model pangkalan data, iaitu, kelas Python dipetakan ke jadual pangkalan data model_op menyimpan operasi yang sepadan dengan setiap model, iaitu, menambah, memadam, menyemak dan mengubah suai apabila pemanggil (seperti main.py) menjalankan operasi pangkalan data, ia hanya perlu memanggil lapisan model_op, anda tidak perlu mengambil berat tentang lapisan model untuk mencapai penyahgandingan.

Pernyataan pemetaan (Pengenalan model)
├── main.py
├── model
│ ├── __init__.py
│ ├── base_model.py
│ ├── ddl.sql
│ └── py_orm_model.py
└── model_op
├── __init__.py
└── py_orm_model_op.py

Sebagai contoh, jika kita mempunyai jadual ujian sedemikian.

Dalam rangka kerja ORM, hasil pemetaan ialah kelas Python di bawah.
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 '测试表';

Pertama sekali, kita dapat melihat bahawa PyOrmModel mewarisi kelas Base, yang merupakan kelas asas yang disediakan oleh sqlalchemy Ia akan melakukan beberapa semakan pada kelas Python yang kami isytiharkan, dan saya meletakkannya dalam base_model .
# 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='更新时间')

Kedua, setiap kelas Python mesti mengandungi atribut __tablename__, jika tidak jadual yang sepadan tidak boleh ditemui.
# 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)

Ketiga, terdapat dua cara untuk mencipta jadual data Yang pertama sudah tentu untuk menciptanya secara manual dalam MySQL Selagi tiada masalah dengan definisi kelas Python anda, ia boleh beroperasi secara normal adalah menggunakan penciptaan Bingkai ORM, seperti di bawah.

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

Keempat, tentang atribut medan:
...
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)
)

1.primary_key dan autoincrement lebih mudah difahami, ia adalah kunci utama dan incremental atribut MySQL.

2. Jika ia adalah jenis int, anda tidak perlu menentukan panjang, tetapi jika ia adalah jenis varchar, anda mesti menyatakannya.

3.nullable sepadan dengan NULL dan BUKAN NULL dalam MySQL

4. Mengenai lalai dan server_default: lalai mewakili nilai lalai pada peringkat rangka kerja ORM, iaitu, jika medan dimasukkan apabila memasukkan Jika tiada nilai diberikan, nilai lalai yang kami takrifkan akan digunakan server_default mewakili nilai lalai pada peringkat pangkalan data, iaitu kata kunci lalai dalam penyata DDL.

Pengenalan sesi

Ia disebut dalam dokumentasi SQLAlchemy bahawa penambahan, pemadaman dan pengubahsuaian pada pangkalan data dilakukan melalui sesi.

Seperti di atas, kita dapat melihat bahawa untuk setiap operasi, kita perlu memperoleh, menyerahkan dan melepaskan sesi. Ini terlalu berlebihan dan menyusahkan, jadi kami biasanya melakukan lapisan enkapsulasi.
>>> 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()

1 Gunakan pengurus konteks untuk mengendalikan pemulangan semula dan penutupan yang tidak normal Bahagian ini hampir konsisten dengan artikel yang dirujuk.

2. Tambahkan dua kaedah pada PyOrmModel untuk penukaran antara model dan dict.
# 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()

3. Enkapsulasi operasi pangkalan data Berbeza dengan artikel rujukan, saya terus memanggil sesi, supaya pemanggil tidak perlu memberi perhatian kepada lapisan model dan mengurangkan gandingan.
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

4. Pemanggil:
# 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

Atas ialah kandungan terperinci Artifak Python yang sangat mudah untuk menggunakan SQL!. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Artikel ini dikembalikan pada:51cto.com. Jika ada pelanggaran, sila hubungi admin@php.cn Padam