SQLALchemy, ORM框架(詳細點我)html
做用: 幫助咱們使用類和對象快速實現數據庫操做。java
數據庫:
- 原生:
- MySQLdb
-不支持python3
- pymysql
-支持python 3/2
- ORM框架
- SQLAlchemypython
建立表mysql
import datetime from sqlalchemy.ext.declarative import declarative_base from sqlalchemy import Column,UniqueConstraint from sqlalchemy import Integer,String,DateTime,ForeignKey from sqlalchemy.orm import relationship from engine import engine Base = declarative_base() #類名就至關於表名 class Userinfo(Base): __tablename__ = 'userinfo' id = Column(Integer, primary_key=True, autoincrement=True) name = Column(String(32),index=True,nullable=True) pwd = Column(Integer,nullable=True) dept_id = Column(Integer,ForeignKey('dept.id')) c_time = Column(DateTime,default=datetime.datetime.now()) #在表裏面不生成字段,就是方便查詢和添加數據用 dp = relationship('Dept', backref='us') class Dept(Base): __tablename__ = 'dept' id = Column(Integer, primary_key=True, autoincrement=True) name = Column(String(32),index=True,nullable=True) #建立多對多的關係的時候,SQLAlchemy沒有ManytoMany的字段, # 就不能幫咱們自動的生成第三張表,而是要靠咱們本身去建立第三張表,來記錄關係 #學生和課程是多對多關係的 class Student(Base): __tablename__ = 'student' id = Column(Integer, primary_key=True, autoincrement=True) name = Column(String(32), index=True, nullable=True) cdp = relationship('Course',secondary='student2course',backref='sdp') class Course(Base): __tablename__ = 'course' id = Column(Integer, primary_key=True, autoincrement=True) name = Column(String(32), index=True, nullable=True) class Student2Course(Base): __tablename__ = 'student2course' id = Column(Integer, primary_key=True, autoincrement=True) student_id = Column(Integer,ForeignKey('student.id')) course_id = Column(Integer,ForeignKey('course.id')) __table_args__ = ( #聯合惟一 UniqueConstraint('student_id', 'course_id', name='sc_id'), #聯合 # Index('ix_id_name', 'name', 'extra'), ) #根據類建立數據庫,須要數據庫的鏈接 def create_all(): Base.metadata.create_all(engine) def drop_all(): Base.metadata.drop_all(engine) if __name__== '__main__': # drop_all() create_all()
鏈接數據庫sql
from sqlalchemy import create_engine from sqlalchemy.orm import sessionmaker,scoped_session engine = create_engine( 'mysql+pymysql://root:123456789@127.0.0.1:3306/sqlalchemydb?charset=utf8', max_overflow = 0, pool_size = 5, pool_timeout = 10, pool_recycle = -1, ) #也須要要數據的鏈接 SessionFactory = sessionmaker(bind=engine) # scoped_session 是基於 threading.local();從鏈接池中取一個鏈接放入本身的線程的空間裏面 # 因此多個線程,併發的時候,也是爲每一個線程本身的空間內有本身的一條鏈接,這樣就不衝突了。 session = scoped_session(SessionFactory) #按照session = SessionFactory() 這樣的形式的時候,在每一次線程來的時候, # 都須要每次都從鏈接池中獲取鏈接 ''' def task(): session = SessionFactory() session.query(Student).all() session.close() from threading import Thread for i in range(20): t = Thread(target=task) t.start() ''' ''' session = scoped_session(SessionFactory) def task(): session.query(Student).all() session.remove() 把本身線程空間內的鏈接刪除掉。也就是將鏈接返回給鏈接池。 from threading import Thread for i in range(20): t = Thread(target=task) t.start() '''
對錶的操做數據庫
from SQLAlchemy_Demo import Userinfo,Dept,Student,Student2Course,Course from engine import session from sqlalchemy.orm import sessionmaker #操做用sqlalchemy生成的表 # ############# 執行ORM操做 ############# #查詢 #filter()裏面是一個表達式 #filter_by()裏面是關鍵字傳參數了 # ret = session.query(Userinfo).filter(Userinfo.id>2).all() # ret = session.query(Userinfo).filter_by(id=2).first() # print(ret) #增長數據 #一個對象就表明着一行數據 # obj = Userinfo(name='alex',pwd=123,dept_id=1) # session.add(obj) #批量的添加數據 # session.add_all([ # Userinfo(name='db',pwd=123,dept_id=1), # Userinfo(name='xiaodong',pwd=123,dept_id=1), # ]) # session.commit() # session.close() #刪除 .delete() # session.query(Userinfo).filter(Userinfo.id >3).delete() # session.commit() # session.close() #修改 update({}) # session.query(Userinfo).filter(Userinfo.id ==1).update({"name":"阿輝"}) #synchronize_session=False就能夠字符串的拼接了;默認的是數字的拼接。; Userinfo.name能夠用表裏面的數據 # session.query(Userinfo).filter(Userinfo.id ==1).update({Userinfo.name:Userinfo.name+'帥逼'},synchronize_session=False) # session.query(Userinfo).filter(Userinfo.id ==1).update({Userinfo.pwd:Userinfo.pwd+999}) # session.commit() # session.close() #經常使用的操做 # 分組 後面跟條件 having # from sqlalchemy.sql import func # ret = session.query(Userinfo).group_by(Userinfo.extra).all() #上面這查不了,由於分組後每組後多個,不知道給你返回哪個,須要你本身來指定。 # ret = session.query( # func.max(Userinfo.id), # ).group_by(Userinfo.dept_id).having(func.max(Userinfo.id) >2).all() # print(ret) #FK 連表操做 query要查詢哪張表裏面的什麼數據 # on 條件 Userinfo.dept_id == Dept.id #join -- inner join # user_data = session.query(Userinfo.id,Userinfo.name.label('username'),Dept.name).join(Dept,Userinfo.dept_id == Dept.id).all() # isouter=True -- > LEFT OUTER JOIN -- LEFT JOIN # user_data = session.query(Userinfo.id,Userinfo.name.label('username'),Dept.name).join(Dept,Userinfo.dept_id == Dept.id,isouter=True).all() # for item in user_data: # print(item.id,item.username,item.name) # print(session.query(Userinfo.id,Userinfo.name.label('username'),Dept.name).join(Dept,Userinfo.dept_id == Dept.id,isouter=True)) # ret = session.query(Dept).filter(Dept.name == '銷售').first() # print(ret) #FK關係表 #建立一個名稱爲: IT部門,再在該部門中添加一個員工:小光 #第一種方式: # dept_obj = Dept(name='IT部門') # session.add(dept_obj) # session.commit() #只要commit後 dept_obj這個建立的對象就是當前添加到表裏面的對象 # dept_id = dept_obj.id # print(dept_id) # user_obj = Userinfo(name='小光',dept_id=dept_id,pwd=123) # session.add(user_obj) # session.commit() # session.close() #第二種經過relation字段 # user_obj = Userinfo(name='小光',pwd=123,dp=Dept(name='IT部門')) # # session.add_all(user_obj) # session.commit() #建立一個名稱爲: IT部門,再在該部門中添加一個員工:小2,小3,小4 #以上的這種簡單的方法就不可取了。 #user_obj = Userinfo(name='小光',pwd=123,dp=Dept(name='IT部門')) # user_objs = Userinfo(name='小光02',pwd=123,dp=Dept(name='IT部門')) #這樣就生成了兩個IT部門,分別在對應的添加人。 #這樣要經過反向生成了 # obj=Dept(name='IT部門01') # obj.us = [Userinfo(name='小2',pwd=123),Userinfo(name='小3',pwd=123)] # # session.add(obj) # # session.commit() # session.close() #ManytoMany 多對多關係表 #添加上python課程的小輝和小黑,上Linux的小黑,以及上go的小龍到數據庫中 #方式一,本身添加到三張表中 # session.add_all([Student(name='小輝'),Student(name='小黑'),Student(name='小龍')]) # session.add_all([Course(name='Python'),Course(name='Linux'),Course(name='go')]) # session.add_all([Student2Course(student_id=6,course_id=6),Student2Course(student_id=7,course_id=6),Student2Course(student_id=7,course_id=7),Student2Course(student_id=8,course_id=8)]) # session.commit() # session.close() #方式二: # 建立一個新的課程,建立2個學生,而且爲兩個學生選取新建立的課程 # c_obj = Course(name='java') # c_obj.sdp =[Student(name='01'),Student(name='02')] # # session.add(c_obj) #幫咱們在三張表中建立數據 # session.commit() # session.close() #正常查詢的話,須要本身不斷的連表 #查詢上python課程的全部學生的姓名 # p_obj = session.query(Student2Course.student_id,Course.name,Student.name).join(Course,Student2Course.course_id ==Course.id).join(Student,Student2Course.student_id == Student.id).filter(Course.name=='python').all() # print(p_obj) # 上面的查詢須要本身連表,比較麻煩 所以用relationship字段來查詢,跟FK的類似。 c_obj = session.query(Course).filter(Course.name=='python').first() ret = c_obj.sdp for item in ret: print(item.name)
總結:flask
在flask中使用 flask-sqlalchemy的步驟: 1.先在__init__.py文件中導入並實例化SQLAlchemy from flask_sqlalchemy import SQLAlchemy db = SQLAlchemy() 實例化的db裏面 什麼的有(SQLAlchemy相關的操做), 可是就是沒有數據庫的鏈接,所以必需要初始化 注意: -在外面實例化 -- db = SQLAlchemy() -必須在導入藍圖以前 (由於要導入db,從而操做數據庫的) -必須導入models.py(這樣才能自動的幫咱們去找到對應的類,去生成對應的表) 2. 初始化 (對取app裏面的配置文件,讀取數據庫的鏈接) db.init_app(app) 3.在配置文件中寫入數據庫鏈接的配置 SQLALCHEMY_DATABASE_URI = 'mysql+pymysql://root:123456789@127.0.0.1:3306/sqlalchemydb?charset=utf8' SQLALCHEMY_POOL_SIZE = 10 SQLALCHEMY_MAX_OVERFLOW = 2 4.建立models.py中的類(對應數據庫的表) 在與__init__同級目錄下建立models.py 注意:此時的類必需要繼承db.Model class Userinfo(db.Model): __tablename__ = 'userinfo' id = Column(Integer, primary_key=True, autoincrement=True) name = Column(String(32),index=True,nullable=True) pwd = Column(Integer,nullable=True) dept_id = Column(Integer,ForeignKey('dept.id')) c_time = Column(DateTime,default=datetime.datetime.now()) 5.而後再最外面建立一個獨立的腳本,用來生成表。 注意:要使用app上下文,拿到裏面的app #要應用到app上文管理 from crm import db,create_app app = create_app() app_ctx = app.app_context() with app_ctx: # with 對象 的時候就會自動的觸發類的__enter__ 方法,而後執行下面的代碼,最後執行__exit__ #__enter__是將app_ctx經過;LocalStack放入Local中, db.create_all() #會調用LocalStack 從Local中獲取app,而後再從app中獲取配置。 #__exit__ 是將當前的app_ctx對象從Local中移除掉 6.基於ORM對數據庫進行操做。 要導入db db.session 就至關於 之前使用的session了 db.session.add(...) #SQLAlchemy的應用: # from crm import db # from crm import models # userobj = models.Userinfo(name='小輝', pwd=123, dept_id=12) # userobj.dp = models.Dept(name='銷售') # db.session.add(userobj) # db.session.commit() # db.session.remove()