1. 程式人生 > >sqlalchemy的兩種方法詳解

sqlalchemy的兩種方法詳解

工作需要,用到了sqlalchemy, 經過近一個月的不斷學習和探索實踐,現在整理一下,以免將來沒地方找。

sqlalchemy有兩種方法,一種是session-mapper的方式,稱為orm方式,另一種就是原生的select等sql語句,稱之為core方式。

下面的講解我們統一把資料庫的相關操作封裝在一個類裡面。

先來說第一種:

from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.dialects.mysql import INTEGER, DATETIME, REAL, TEXT, VARCHAR
from sqlalchemy import Table, Column, ForeignKey, MetaData
from sqlalchemy.orm import mapper, sessionmaker
from sqlalchemy import  func
import re
import hashlib
import os, sys
import time, datetime


class SelectData():
    def __init__(self):
        s1     = "mysql+mysqldb://"
        server = "root:
[email protected]
:3306/test" s2 = "?use_unicode=0&charset=utf8" connectserver = s1 + server + s2 self.engine = create_engine(connectserver, encoding = 'utf-8', echo = False) self.Base = MetaData() self.user= Table( 'user', self.Base, Column('id', INTEGER, primary_key = True), Column('name', TEXT) Column('passwd', TEXT) ) self.client = Table( 'client', self.Base, Column('id', INTEGER, primary_key = True), Column('name', TEXT), Column('id_user', INTEGER), Column('reserved_int', INTEGER), Column('reserved_varchar', VARCHAR(200)) ) self.Base.create_all(self.engine)#create_all可以自動檢測表是否已經建立,非常方便 self.Session = sessionmaker() #建立了一個自定義了的 Session類 self.Session.configure(bind = self.engine) #將建立的資料庫連線關聯到這個session

下面的函式是單表的查詢插入更新展示:
def insert_function(self):
    session = self.Session()
    class User(object): pass
    mapper(User, self.user)
    class Client(object): pass
    mapper(Client, self.client)
    
    #select方式:
    ret = session.query(User).filter(User.name == "admin").first()
    if ret is None:
        #新增新的欄位
        user = User()
        user.name = "admin"
        user.passwd = CountMd5("123456")#此處CountMd5()是自己寫的一個計算md5值的函式
        session.add(user)
        session.flush()
        #session.commit()
        #獲取剛剛插入資料的自增主鍵id
        id_usr = user.id
    else:
        id_usr = ret.id
    
    ret2 = session.query(Client).filter_by(id_user = id_usr).first()
    if ret2 is None:
        client = Client()
        client.name = "Chocolate"
        client.id_user = id_usr
        client.session.add(client)
        session.flush()
        session.commit()
    else:
        #使用update:
        session.query(Client).filter_by(id_user = id_usr).update({"name": "Chocolate", "id_user":id_usr})   
        session.flush()
        session.commit()
        session.close()

下面是多表聯合查詢:
#多表聯合查詢
def testfun2(self, partname, pageindex):
    session = self.Session()
    class User(object): pass
    mapper(User, self.user)
    class Client(object): pass
    mapper(Client, self.client)

    pageval = (pageindex - 1) * 10
    #這裡面一個是like的用法,一個是隻顯示某10條
    ret = self.session.query(User)\
            .join(Client, Client.id_user == User.id )\
            .filter(User.name.like('%' + partname + '%'))\
            .offset().limit(10).all()
    if ret is None:
        return None
    else:
        for k in ret:
            print k.name, k.passwd
    session.close()

下面是刪除表的內容的用法:

#刪除表的全部內容,不刪除表
def delete_func(self):
    session = self.Session()
    class User(object): pass
    mapper(User, self.user)
    class Client(object): pass
    mapper(Client, self.client)
    session.query(Client).delete()
    session.query(User).delete()
    session.commit()
    session.close()
上面就是orm的方式了,這個方式要特別注意的地方就是,session的問題,因為session是有個有效期的,如果我們把session在init函式裡面做成全域性變數self.session,那麼就會出現資料庫實時更新插入的值這裡面查詢不到,所以,對於session的態度,我們是用到再新建,用完手動關閉。

然後下面我們來講一下第二種方式,core的方式:

上面建表的部分是一樣的,只不過要把建完表之後session那一塊替換為:

self.Base.create_all(self.engine)
self.conn = self.engine.connect()
定義一個關閉資料庫連線的函式:
def close(self):
        self.conn.close()
下面是簡單的一些基本用法:

包含了查詢,插入和更新。

def resetpwd(self, passwdm):
        sel = select([self.user]).where(self.user.c.name == "admin")
        ret = self.conn.execute(sel).fetchone()
        if ret is None:
            ins = self.user.insert().values(name = "admin", passwd = passwdm)
            self.conn.execute(ins)
        else:
            updpwd = self.user.update().values(name = "admin", passwd = passwdm).where(self.user.c.name == "admin")
            self.conn.execute(updpwd)

execute會自動commit,不用我們去手動做。這種core的方式要注意的地方就是表後面有個.c,如self.user.c.name,我也不知道為什麼有這個c,看官網的用例上都是這樣的,如果不加的話就不正確。所以還是屈從權威吧。問題解決了才最重要。

就是以上這些了。希望大家一起進步!

轉載文章,請註明出處。