Flask數據庫連接

Flask數據庫連接

Python數據庫連接方式

python中的數據庫連接有兩種方式:

  • Python 標準數據庫接口,使用 SQL 語句正常操作數據庫,
    e.g: MySQL 關係型數據庫的 pymsql 模塊
  • 用 ORM 來進行數據庫連接, Python 中使用 sqlalchemy , flask中典型的 flask_sqlalchemy ,
    以面向對象的方式進行數據庫的連接與操作
  • ORM 是什麼?有什麼優勢?
    ORM ,即 Object-Relational Mapping (對象關係映射),它的作用是在關係型數據庫和業務實體對象之間作一個映射,這樣,我們在具體的操作業務對象的時候,就不需要再去和複雜的 SQL 語句打交道,只需簡單的操作對象的屬性和方法。

Flask-SQLAlchemy

Flask-SQLAlchemy 是一個 Flask 擴展,簡化了在 Flask 程序中使用 SQLAlchemy 的操作。
SQLAlchemy 是一個很強大的關係型數據庫框架,支持多種數據庫後臺。 SQLAlchemy 提
供了高層 ORM ,也提供了使用數據庫原生 SQL 的低層功能。

配置數據庫

安裝第三方模塊
pip install flask-sqlalchemy
數據庫配置

在app.py文件中:

from flask_sqlalchemy import SQLAlchemy
# 獲取當前絕對路徑
basedir = os.path.abspath(os.path.dirname(__file__)) app = Flask(__name__)
# SQLALCHEMY_DATABASE_URI: 用於連接數據的數據庫。 
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + os.path.join(basedir, 'data.sqlite')
# sqlchemy將會追蹤對象的修改並且發送信號 
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False 
# 每次請求結束之後都會提交數據庫的變動 
app.config['SQLALCHEMY_COMMIT_ON_TEARDOWN'] = True
# 數據庫與app項目關聯, 返回SQLAlchemy實例對象,
# 後面可以使用對象調用數據 db = SQLAlchemy(app)
流行的數據庫引擎採用的數據庫 URL格式

在這裏插入圖片描述

連接 mysql 數據庫報錯解決

報錯爲:ImportError: No module named ‘MySQLdb’”
MySQLdb只支持Python2,還不支持python3可以用PyMySQL代替。

安裝方法:pip install PyMySQL
然後在需要的項目中,把 init.py中添加兩行:

    import pymysql
    pymysql.install_as_MySQLdb()

就可以用 import MySQLdb了。其他的方法與MySQLdb一樣。

定義模型

模型(Model)這個術語表示程序使用的持久化實體。

class Role(db.Model):
	# __tablename__類變量定義數據庫中表的名稱。不指定默認爲模型名稱。
	# Flask-SQLAlchemy需要給所有的模型定義主鍵列,通常命名爲id。
	id = db.Column(db.Integer, primary_key=True)
	name = db.Column(db.String(64), unique=True)
	# repr()顯示一個可讀字符串,用於調試和測試 
	def __repr__(self): 
		return '<Role %r>' % self.name 
class User(db.Model):
	__tablename__ = 'users' 
	id = db.Column(db.Integer, primary_key=True)
	username = db.Column(db.String(64), unique=True, index=True) 
	def __repr__(self): 
		return '<User %r>' % self.username
模型列類型

在這裏插入圖片描述

模型列屬性

在這裏插入圖片描述

數據查詢

查詢過濾器

在這裏插入圖片描述

查詢執行函數

在這裏插入圖片描述

分頁實現

分頁對象擁有的屬性

在這裏插入圖片描述

分頁對象擁有的方法

在這裏插入圖片描述

數據庫關係

數據庫實體間有三種對應關係:一對一,一對多,多對多。

一對一關係

一個學生對應一個學生檔案材料,或者每個人都有唯一的身份證編號。
在這裏插入圖片描述

模型定義
# one_to_one.py文件 
from app import db import pymysql 
pymysql.install_as_MySQLdb() 
class People(db.Model):
 	__tablename__ = 'peoples' 
 	id = db.Column(db.Integer, primary_key=True, autoincrement=True)
  	name = db.Column(db.String(20), nullable=False) 
  	
	""" 
	 關係使用 relationship() 函數表示;
	 'Card': People類對應的表與Card類對應的表關聯;
	 backref='people': 反向引用, 在Card類中添加新屬性people; 
	 uselist=False: 默認爲True, 如果爲False代表一對一關係;
	 lazy='select': 決定了 SQLAlchemy 什麼時候從數據庫中加載數據; 
	 還可以設 定:'joined', 'subquery' , 'dynamic' 可能報錯: 
	 SAWarning: Multiple rows returned with uselist=False for lazily- loaded
	"""
	 
   	card = db.relationship('Card', backref='people', uselist=False)
   	
   	def __init__(self, name): 
   		self.name = name 
   		
   	def __repr__(self): 
   		return '<People: %s>' % (self.name) 
   		
class Card(db.Model):
	__tablename__ = 'cards' 
	id = db.Column(db.Integer, primary_key=True, autoincrement=True) 
	cardID = db.Column(db.String(30), nullable=False) 
	# 外鍵必須用類 sqlalchemy.schema.ForeignKey 來單獨聲明; 
	people_id = db.Column(db.Integer, db.ForeignKey('peoples.id')) 
	
	def __repr__(self): 
		return "<Card: %s>" % (self.cardID)
基本操作

if __name__ == '__main__':
	db.drop_all() 
	db.create_all() 
	
	# 增元素 
	p1 = People(name="西部開源")
	p2 = People(name="粉條")
	db.session.add_all([p1, p2])
	db.session.commit()
	card1 = Card(cardID='001', people_id=p1.id)
	card2 = Card(cardID='002', people_id=p2.id) 
	db.session.add_all([card1, card2]) 	
	db.session.commit()
	
	# 查找 
	card_people1 = Card.query.filter_by(cardID='001').first().people 
	people_card1 = People.query.filter_by(id=1).first().card 
	print(card_people1) print(people_card1) 
	
	# 刪除
	print("刪除前: ", Card.query.all(), People.query.all()) 
	card = Card.query.filter_by(cardID='001').first() 
	db.session.delete(card) 
	db.session.commit()
	print("刪除後: ", Card.query.all(), People.query.all())

一對多關係

一個學生只屬於一個班,但是一個班級有多名學生。在這裏插入圖片描述
設計數據庫表:只需在 學生表 中多添加一個班級號的ID;
通過添加主外鍵約束,避免刪除數據時造成數據混亂

模型定義
from app import db import pymysql 
pymysql.install_as_MySQLdb()
# 一對多: 外鍵寫在多的一端; Grade:Stdudents== 1:n 

class Student(db.Model): 
	__tablename__ = 'students' 
	id = db.Column(db.Integer, primary_key=True, autoincrement=True) 
	name = db.Column(db.String(20), nullable=False) 
	
	# 外鍵 
	grade_id = db.Column(db.Integer, db.ForeignKey('grades.id')) 
	
	def __repr__(self): 
		return "<Student: %s %s %s>" % (self.id, self.name, self.grade_id) 
		
class Grade(db.Model): 
	__tablename__ = 'grades' 
	id = db.Column(db.Integer, primary_key=True, autoincrement=True) 
	name = db.Column(db.String(20), nullable=False) 
	
	# 反向引用, 讓Student類中添加屬性grade; 
	students = db.relationship('Student', backref='grade') 
	
	def __repr__(self): 
		return "<Grade: %s %s %s>" % (self.id, self.name, self.students)
基本操作
if __name__ == '__main__': 
	db.drop_all() 
	db.create_all() 
	
	# 增元素 
	s1 = Student(name="西部開源") 
	s2 = Student(name="粉條")
	db.session.add_all([s1, s2]) 
	db.session.commit() 
	
	grade1 =Grade(name='Python開發')
	grade1.students.append(s1)
	grade1.students.append(s2)
	db.session.add_all([grade1])
	db.session.commit()
	print("添加成功: ", Student.query.all(), Grade.query.all())
	
	# 查找 
	student_grade1 = Student.query.filter_by(name='粉條').first().grade 
	grade_students = Grade.query.filter_by(name="Python開發").first().students 
	print(student_grade1)
	print(grade_students)
	
	# 刪除
	print("刪除前: ", Student.query.all(), Grade.query.all())
	grade1 = Grade.query.filter_by(name='Python開發').first()
	db.session.delete(grade1) 
	db.session.commit() 
	print("刪除後: ", Student.query.all(), Grade.query.all())

多對多關係

一個學生可以選擇多門課,一門課也有多名學生。在這裏插入圖片描述
對於多對多表,通過關係表就建立起了兩張表的聯繫!多對多表時建立主外鍵後,要先刪除約束表
內容再刪除主表內容。在這裏插入圖片描述

模型定義
from app import db import pymysql 
pymysql.install_as_MySQLdb() 
# 第三方表 
tags=db.Table('tags', 
		db.Column('student_id',db.Integer,db.ForeignKey('math_students.id')), 
		db.Column('course_id',db.Integer,db.ForeignKey('courses.id'))
	) 
	
class MathStudent(db.Model): 
	__tablename__ = 'math_students' 
	id = db.Column(db.Integer, primary_key=True, autoincrement=True) 
	name = db.Column(db.String(20), nullable=False) 
	courses = db.relationship('Course', secondary=tags) 
	
	def __repr__(self): 
		return "<MathStudent: %s >" % (self.name)
		
class Course(db.Model):
	__tablename__ = 'courses' 
	id = db.Column(db.Integer, primary_key=True, autoincrement=True) 
	name = db.Column(db.String(20), nullable=False) 
	students = db.relationship('MathStudent', secondary=tags) 
	
	def __repr__(self): 
		return "<Course: %s >" % (self.name)
基本操作
if __name__ == '__main__': 
	db.drop_all()
	db.create_all() 
	
	# 創建
	s1 = MathStudent(name="拉格朗日")
	s2 = MathStudent(name="麥克勞林") 
	s3 = MathStudent(name="羅爾") 
	
	course1 = Course(name="高等數學")
	course2 = Course(name="線性代數") 
	
	s1.courses.append(course1) 
	s1.courses.append(course2)
	s2.courses.append(course1)
	s3.courses.append(course2) 
	
	db.session.add_all([s1, s2, s3, course1, course2]) 
	db.session.commit() 
	
	# 刪除
	courseObj = Course.query.filter_by(name="線性代數").first() 
	studentObj = MathStudent.query.filter_by(name="羅爾").first() 
	
	print("刪除前選擇線性代數的學生: ", courseObj.students)
	
	courseObj.students.remove(studentObj) 
	
	print("刪除後擇線性代數的學生: ", courseObj.students)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章