在web應用里使用原生的SQL語句操作數(shù)據(jù)庫主要存在下面兩類問題:
1.手動編寫SQL語句比較乏味,而且視圖函數(shù)中加入太多的SQL語句會降低代碼的易讀性。另外還容易出現(xiàn)安全問題,比如SQL注入。
2.在部署時切換到不通的DBMS,我們需要使用不同的Python接口庫,這讓DBMS的切換變的不太容易。
下面利用SQLAlchemy對MySQL進行簡單的CRUD操作
# -*- coding: utf-8 -*-
"""利用sqlalchemy對mysql進行簡單的增刪改查"""
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
from sqlalchemy import Column, Integer, String, DateTime, Boolean
engine = create_engine('mysql+pymysql://root:root@localhost:3306/news?charset=utf8') # 連接news數(shù)據(jù)庫(news庫需提前創(chuàng)建好)
Session = sessionmaker(bind=engine)
Base = declarative_base()
class News(Base):
"""
在python終端執(zhí)行以下命令手動創(chuàng)建表
from sqlalchemy_test import News, engine
News.metadata.create_all(engine)
"""
# 表名
__tablename__ = 'news'
id = Column(Integer, primary_key=True, autoincrement=True)
title = Column(String(200), nullable=False)
content = Column(String(2000), nullable=False, default='新聞內(nèi)容')
types = Column(String(20), nullable=False)
image = Column(String(300), default="")
author = Column(String(20), default="")
view_count = Column(Integer, default=0)
created_at = Column(DateTime)
is_valid = Column(Boolean, default=True)
class MysqlOrmTest(object):
def __init__(self):
self.session = Session()
def add_one(self):
# 添加一條數(shù)據(jù)
news_obj = News(
title='標題',
types='體育',
content="新聞內(nèi)容"
)
self.session.add(news_obj)
self.session.commit()
return news_obj
def add_more(self):
"""添加多條數(shù)據(jù)"""
self.session.add_all([
News(title='標題2', types='推薦', content="新聞內(nèi)容"),
News(title='標題3', types='百家', content="新聞內(nèi)容"),
News(title='標題4', types='軍事', content="新聞內(nèi)容"),
News(title='標題5', types='推薦', content="新聞內(nèi)容")
])
self.session.commit()
def get_more(self):
"""獲取多條數(shù)據(jù)"""
return self.session.query(News).filter_by(is_valid=1)
def get_one(self):
"""獲取一條數(shù)據(jù)"""
return self.session.query(News).get(8) # 獲取id為8的數(shù)據(jù)
def update_data(self):
""""數(shù)據(jù)更新 """
obj = self.session.query(News).get(4)
obj.is_valid = 0
self.session.add(obj)
self.session.commit()
return obj.is_valid
def delete_data(self):
"""刪除數(shù)據(jù)"""
# 獲取要刪除的數(shù)據(jù)
data = self.session.query(News).get(8)
self.session.delete(data)
self.session.commit()
def main():
obj = MysqlOrmTest()
# 增加一條數(shù)據(jù)
result = obj.add_one()
# 增加多條數(shù)據(jù)
obj.add_more()
# 獲取一條數(shù)據(jù)
result = obj.get_one()
# 獲取多條數(shù)據(jù)
result = obj.get_more()
for item in result:
print(item.title)
print(obj.update_data())
# 刪除數(shù)據(jù)
obj.delete_data()
if __name__ == "__main__":
main()
Flask-SQLAlchemy是對SQLAlchemy又進行了一層封裝
# -*- coding: utf-8 -*-
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://root:root@localhost:3306/note?charset=utf8'
db = SQLAlchemy(app)
class Note(db.Model):
"""
在python終端執(zhí)行以下命令手動創(chuàng)建表
from flask_sqlalchemy_test import db
db.create_all()
"""
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
body = db.Column(db.Text)
def __repr__(self):
return '<Note %r>' % self.body
Create
note1 = Note(body="這是第1條筆記")
note2 = Note(body="這是第2條筆記")
db.session.add(note1)
db.session.add(note2)
db.session.commit()
除了依次調(diào)用add()方法添加多個記錄,也可以使用add_all()一次添加包含所有記錄對象的列表
Read
一般來說,一個完整的查詢遵循<模型類名>.query.<過濾方法>.<查詢方法>的模式
all(): 返回所有的記錄
Note.query.all()
first(): 返回第一條記錄
note1 = Note.query.first()
print(note1.id)
count(): 返回記錄的數(shù)量
Note.query.count()
get(): 指定主鍵值(id字段)的記錄
note2 = Note.query.get(2) # 讀取表中id為2的數(shù)據(jù)
print(note2.body)
filter(): 它使用指定的規(guī)則來過濾記錄
Note.query.filter(Note.body=='SHAVE').first() #找出body字段值為SHAVE的記錄
LIKE
filter(Note.body.like('%foo%'))
IN
filter(Note.body.in_(['foo','bar','baz']))
NOT IN
filter(~Note.body.in_(['foo','bar','baz']))
AND
1.使用and_()
from sqlalchemy import and_
filter(and_(Note.body == 'foo',Note.title == 'foobar'))
2.或在filter()中加入多個表達式,使用逗號分隔
filter(Note.body == 'foo', Note.title == 'foobar')
3.或疊加調(diào)用多個filter() / filter_by()方法
filter(Note.body == 'foo').filter(Note.title == 'foobar')
OR 使用or_()
from sqlalchemy import or_
filter(or_(Note.body == 'foo', Note.body == 'bar'))
filter_by():在filter_by方法中,你可以使用關鍵字表達式來指定過濾規(guī)則。
Note.query.filter(body=='SHAVE').first()
更多的查詢方法和過濾方法可參考(http://docs.sqlalchemy.org/en/lates/orm/query.html)
Update
更新一條記錄非常簡單,直接賦值給模型類的字段屬性就可以改變字段值,然后調(diào)用commit()方法提交會話即可。
note = Note.query.get(3)
note.body = "hello world"
db.session.commit()
只有要插入新的記錄或將現(xiàn)有的記錄添加到會話中時才需要add()方法,單純要更新現(xiàn)有的記錄時只需要直接為屬性賦值,然后提交會話。
Delete
note = Note.query.get(2)
db.session.delete(note)
db.session.commit()
刪除記錄和添加記錄很相似,最后都需調(diào)用commit()方法提交需改