SQLAlchemy 中的 Session、sessionmaker、scoped_session

SQLAlchemy 中的 Session、sessionmaker、scoped_session

目錄

  • 一、關于 Session
    • 1. Session是緩存嗎?
    • 2. Session作用:
    • 3. Session生命周期:
    • 4. Session什么時候創建,提交,關閉?
    • 4. 獲取一個Session:
    • 5. 關于SQLAlchemy 的 create_engine:
    • 6. 關于線程安全:
  • 二、單線程下 scoped_session 對創建 Session 的影響
    • 1. 兩個 Session 添加同一個對象
    • 2. 不同的 Session 添加不同的對象
    • 3. 用 scoped_session 創建 Session
  • 三、多線程下 scoped_session 對創建 Session 的影響
    • 1. 當不用 scoped_session 時:
    • 2. 當使用 scoped_session 時:

一、關于 Session

Session 其實 就是一個會話, 可以和數據庫打交道的一個會話

在一般的意義上, 會話建立與數據庫的所有對話,并為你在其生命周期中加載或關聯的所有對象表示一個“等待區”。他提供了一個入口點獲得查詢對象, 向數據庫發送查詢,使用會話對象的當前數據庫連接, 將結果行填充在對象中, 然后存儲在會話中, 在這種結構中稱為身份映射 – 這種數據結構維護了每一個副本的唯一, 這種唯一意味著一個對象只能有一個特殊的唯一主鍵。

會話以基本無狀態的形式開始,一旦發出查詢或其他對象被持久化,它就會從一個引擎申請連接資源,該引擎要么與會話本身相關聯,要么與正在操作的映射對象相關聯。此連接標識正在進行的事務, 在會話提交或回滾其掛起狀態之前,該事務一直有效。

會話中維護的所有變化的對象都會被跟蹤 - 在再次查詢數據庫或提交當前事務之前, 它將刷新對數據庫的所有更改, 這被稱為工作模式單元。

在使用會話時候,最重要的是要注意與它相關聯的對象是會話所持有的事務的代理對象 - 為了保持同步,有各種各樣的事件會導致對象重新訪問數據庫。可能從會話中分離對象并繼續使用他們,盡管這種做法有其局限性。但是通常來說,當你希望再次使用分離的對象時候,你會將他們與另一個會話重新關聯起來, 以便他們能夠恢復表示數據庫狀態的正常任務。


1. Session是緩存嗎?

可能會將這里的session與http中的session搞混,需要注意的是,它有點用作緩存,因為它實現了 身份映射 模式,并存儲了鍵入其主鍵的對象。但是,它不執行任何類型的查詢緩存。
此外,默認情況下,Session使用弱引用存儲對象實例。這也違背了將Session用作緩存的目的。關于session強應用下次再討論。

2. Session作用:

1. session創建和管理數據庫連接的會話
2. model object 通過session對象訪問數據庫,并把訪問到的數據以 Identity Map的方式,映射到Model object中

3. Session生命周期:

1. session在剛被創建的時候,還沒有和任何model object 綁定,可認為是無狀態的
2. session 接受到query查詢語句, 執行的結果或保持或者關聯到session中
3. 任意數量的model object被創建,并綁定到session中,session會管理這些對象
4. 一旦session 里面的objects 有變化,那可是要commit/rollback提交或者放棄changs

4. Session什么時候創建,提交,關閉?

一般來說,session在需要訪問數據庫的時候創建,在session訪問數據庫的時候,準確來說,應該是“add/update/delete”數據庫的時候,會開啟database transaction。假設沒有修改autocommit的默認值(False), 那么,database transaction 一直會保持,只有等到session發生rolled back、committed、或者closed的時候才結束,一般建議,當database transaction結束的時候,同時close session,以保證,每次發起請求,都會創建一個新的session特別是對web應用來說,發起一個請求,若請求使用到Session訪問數據庫,則創建session,處理完這個請求后,關閉session

4. 獲取一個Session:

Session 是一個直接實例化的常規的Python 類。然而, 為了標準會會話的配置和獲取方式, sessionmaker 類通常用于創建頂級會話配置, 然后可以在整個應用程序中使用它, 就不需要重復配置參數。

下面是sessionmaker 的使用方式

from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker# 創建連接數據庫的引擎,session連接數據庫需要
my_engine = create_engine('mysql+pymysql://root:123456@localhost/my_db')# 創建一個配置過的Session類
Session = sessionmaker(bind=my_engine)# 實例化一個session
db_session = Session()# 使用session
myobject = MyObject('foo', 'bar')
db_session.add(myobject)
db_session.commit()

在上面,該sessionmaker()創建了一個工廠類,在創建這個工廠類時我們配置了參數綁定了引擎。將其賦值給Session。每次實例化Session都會創建一個綁定了引擎的Session。這樣這個session在訪問數據庫時都會通過這個綁定好的引擎來獲取連接資源
當你編寫應用程序時, 請將sessionmaker 工廠放在全局級別,視作應用程序配置的一部分。例如:應用程序包中有三個.py文件,您可以將該sessionmaker行放在__init__.py文件中; 在其他模塊“from mypackage import Session”。這樣,所有的Session()的配置都由該配置中心控制。

5. 關于SQLAlchemy 的 create_engine:

直接只用 create_engine 時,就會創建一個帶連接池的引擎:

my_engine = create_engine('mysql+pymysql://root:123456@localhost/my_db')

創建一個session,連接池會分配一個connection。當session在使用后顯示地調用 session.close(),也不能把這個連接關閉,而是由由QueuePool連接池管理并復用連接。

確保 session 在使用完成后用 session.close、session.commit 或 session.rollback 把連接還回 pool,這是一個必須在意的習慣。

關于SQLAlchemy 數據庫連接池:

session 和 connection 不是相同的東西, session 使用連接來操作數據庫,一旦任務完成 session 會將數據庫 connection 交還給 pool。在使用 create_engine 創建引擎時,如果默認不指定連接池設置的話,一般情況下,SQLAlchemy 會使用一個 QueuePool 綁定在新創建的引擎上。并附上合適的連接池參數

create_engine() 函數和連接池相關的參數有:

  • pool_recycle, 默認為 -1, 推薦設置為 7200, 即如果 connection 空閑了 7200 秒,自動重新獲取,以防止 connection 被 db server 關閉。
  • pool_size=5, 連接數大小,默認為 5,正式環境該數值太小,需根據實際情況調大
  • max_overflow=10, 超出 pool_size 后可允許的最大連接數,默認為 10, 這 10 個連接在使用過后,不放在 pool 中,而是被真正關閉的。
  • pool_timeout=30, 獲取連接的超時閾值,默認為 30 秒

SQLAlchemy不使用連接池:
在創建引擎時指定參數 poolclass=NullPool 即禁用了SQLAlchemy提供的數據庫連接池。SQLAlchemy 就會在執行 session.close() 后立刻斷開數據庫連接。當然,如果沒有被調用 session.close(),則數據庫連接不會被斷開,直到程序終止。

my_engine = create_engine('mysql+pymysql://root:123456@localhost/my_db',poolclass=NullPool)

關于 SQLAlchemy 的 engine ,這里有一篇文章寫的很好:http://sunnyingit.github.io/book/section_python/SQLalchemy-engine.html

6. 關于線程安全:

session不是線程安全的,在多線程的環境中,默認情況下,多個線程將會共享同一個session。試想一下,假設A線程正在使用session處理數據庫,B線程已經執行完成,把session給close了,那么此時A在使用session就會報錯,怎么避免這個問題?

1. 可以考慮在這些線程之間共享Session及其對象。但是應用程序需要確保實現正確的鎖定方案,以便多個線程不會同時訪問Session或其狀態。SQLAlchemy 中的 scoped_session 就可以證線程安全,下面會有討論。
2. 為每個并發線程維護一個會話,而不是將對象從一個Session復制到另一個Session,通常使用Session.merge()方法將對象的狀態復制到一個不同Session的新的本地對象中。

二、單線程下 scoped_session 對創建 Session 的影響

上面簡單介紹了sessionmaker的作用,下面開始探討 scoped_session 對創建 Session 的影響。現在先探討單線程情況。


先聲明待會實驗用的模型:

from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String
from sqlalchemy import create_engineBase = declarative_base
engine = create_engine("mysql+pymysql://root:123456@127.0.0.1:3306/my_db?charset=utf8mb4")class Person(Base):__tablename__ = 'Person'id = Column(Integer, primary_key=True, autoincrement=True)name = Column(String(length=64), comment='姓名')mobile = Column(String(length=13), comment='手機號')id_card_number = Column(String(length=64), comment='身份證')def __str__(self):return '%s(name=%r,mobile=%r,id_card_number=%r)' % (self.__class__.__name__,self.name,self.mobile,self.id_card_number)# 在數據庫中創建模型對象的表
Base.metadata.create_all(engine)

1. 兩個 Session 添加同一個對象

1.1 在 commit 之前添加:


from sqlalchemy.orm import sessionmaker, scoped_sessionsession_factory = sessionmaker(bind=engine)
# engine 在上面已經創建好了person = Person(name='frank-' + 'job3', mobile='111111', id_card_number='123456789')Session= session_factory()
s1= session_factory()
# s1 : <sqlalchemy.orm.session.Session object at 0x107ec8c18>s2 = session_factory() 
# s2 : <sqlalchemy.orm.session.Session object at 0x107ee3ac8>print(s1 is s2)
# Falseid(s1),id(s2)
# 4427910168, 4428020424s1.add(person)
s2.add(person)
# 會報錯!
# sqlalchemy.exc.InvalidRequestError: Object '<Person at 0x22beb14bf60>' is already attached to session '2' (this is '3')

結論:

通過 sessionmaker 工廠創建了兩個 Session ,而且可以看到 s1 s2 是兩個不同的 Session 。
在 s1 添加 person 后,繼續使用 s2 添加 person 報錯. 說 person 這個對象 已經和 另一個 Session 關聯一起來了, 所以再次關聯另一個 Session 就會報錯。

1.2 在 commit 之后添加:

即在上面代碼的 s1.add(person) 之后, s1.commit() ,然后再 s2.add(persion)
這里就沒帖代碼了。

結論:

即使在 s1 提交之后,s2 再去添加 person 也會發生錯誤,但 s1 的提交是成功了的,數據 person 已經存放在數據庫了。
當 s1 添加 person 并提交,然后關閉 s1 ,s2再去添加并提交 person 數據庫,這不會報錯,但是數據庫也不會出現兩條 person 數據。

1.3 再 close 之后添加:

p = Person(name='frank', mobile='11111111', id_card_number='123456789')s1.add(p)
s1.commit()s2.add(p)
s2.commit()# 也會報錯!!!
# sqlalchemy.exc.InvalidRequestError: Object '<Person at 0x21207e3e128>' is already attached to session '2' (this is '3')p = Person(name='frankcc', mobile='1111111122', id_card_number='1234567890')s1.add(p)
s1.commit()
s1.close()
s2.add(p)
s2.commit()# 不會報錯

結論:

s1 關閉之后, s2再去添加提交同一個對象,不會報錯,但是數據庫值有一條 person 數據。

2. 不同的 Session 添加不同的對象

person4 = Person(name='frank-' + 'job4', mobile='4444444444', id_card_number='123456789')
person1 = Person(name='frank-' + 'job1', mobile='111111', id_card_number='123456789')s1.add(person1)
s2.add(person4)
s1.commit()  # 提交數據
s2.commit()  # 提交數據, 寫入數據庫

結論:

當然,s1 ,s2 添加提交不同的對象,不會出錯。在數據庫成功新增數據。 

mysql> select * from person;
+----+------------+------------+----------------+
| id | name       | mobile     | id_card_number |
+----+------------+------------+----------------+
|  1 | frank-job1 | 111111     | 123456789      |
|  2 | frank-job4 | 4444444444 | 123456789      |
+----+------------+------------+----------------+
2 rows in set (0.00 sec)

以上說明:

一個對象一旦被一個 Session 添加,除非關閉這個 Session ,不然其他的 Session 無法添加這個對象。
一個 Session 添加并提交一個對象,然后關閉該 Session ,其他的 Session 可以添加并提交這個對象,但是數據庫并不會有這條數據。

3. 用 scoped_session 創建 Session


session_factory = sessionmaker(bind=engine)
Session = scoped_session(session_factory)s1 = Session()
# <sqlalchemy.orm.session.Session object at 0x0000020E58690240>s2 = Session()
# <sqlalchemy.orm.session.Session object at 0x0000020E58690240>print(s1 is s2)
# Truep = Person(name='frankaaabb', mobile='1111111122233', id_card_number='12345678900099')s1.add(p)
s2.add(p)
s2.commit()

結論:

可以看到,通過scoped_session再去創建 Session ,返回的是同一個 Session 。
scoped_session類似單例模式,當我們調用使用的時候,會先在Registry里找找之前是否已經創建Session,未創建則創建 Session ,已創建則直接返回。

三、多線程下 scoped_session 對創建 Session 的影響

這里探討在多線程下使用 scoped_session 與不使用 scoped_session 的情況


1. 當不用 scoped_session 時:

當不使用 scoped_session 時,也分兩種情況,是否創建全局性 Session

1.1 多線程下不設置 Session 為全局變量


session_factory = sessionmaker(bind=engine)
Session = session_factorydef job(name):session = Session()print(f"id session:{id(session)}")person = Person(name='frank-' + name, mobile='111111', id_card_number='123456789')print(f"{name} person is add..")session.add(person)time.sleep(1)if name == 'job3':# 線程3 提交, 其他線程不提交.session.commit()session.close()if __name__ == '__main__':thread_list = []# 創建5個線程for i in range(5):name = 'job' + str(i)t = threading.Thread(target=job, name=name, args=(name,))thread_list.append(t)for t in thread_list:t.start()for t in thread_list:t.join()

結論:

每個線程下的 Session 都是不同的 Session
數據庫成功新增了線程3提交的數據,其他的線程中的數據并沒有提交到數據庫中去。

id session:2557871997392
job0 person is add..
id session:2557871998064
job1 person is add..
id session:2557871998568
job2 person is add..
id session:2557871999072
job3 person is add..
id session:2557871999688
job4 person is add..mysql> select * from person;
+----+------------+--------+----------------+
| id | name       | mobile | id_card_number |
+----+------------+--------+----------------+
| 14 | frank-job3 | 111111 | 123456789      |
+----+------------+--------+----------------+
1 row in set (0.00 sec)

1.2 在多線程下用全局 Session


session_factory = sessionmaker(bind=engine)
Session = session_factory
session = Session()def job(name):global sessionprint(f"id session:{id(session)}")person = Person(name='frank-' + name, mobile='111111', id_card_number='123456789')print(f"{name} person is add..")session.add(person)time.sleep(1)if name == 'job3':# 線程3 提交, 其他線程不提交.session.commit()session.close()if __name__ == '__main__':thread_list = []# 創建5個線程for i in range(5):name = 'job' + str(i)t = threading.Thread(target=job, name=name, args=(name,))thread_list.append(t)for t in thread_list:t.start()for t in thread_list:t.join()

結論:

全部線程下的 Session 都時同一個 Session
每個線程下的數據都被提交到了數據庫

id session:2737857674824
job0 person is add..
id session:2737857674824
job1 person is add..
id session:2737857674824
job2 person is add..
id session:2737857674824
job3 person is add..
id session:2737857674824
job4 person is add..mysql> select * from person;
+----+------------+--------+----------------+
| id | name       | mobile | id_card_number |
+----+------------+--------+----------------+
| 15 | frank-job0 | 111111 | 123456789      |
| 16 | frank-job2 | 111111 | 123456789      |
| 17 | frank-job1 | 111111 | 123456789      |
| 18 | frank-job3 | 111111 | 123456789      |
| 19 | frank-job4 | 111111 | 123456789      |
+----+------------+--------+----------------+
5 rows in set (0.00 sec)

2. 當使用 scoped_session 時:

2.1 多線程下不設置 Session 為全局變量


session_factory = sessionmaker(bind=engine)
Session = scoped_session(session_factory)def job(name):session = Session()print(f"id session:{id(session)}")person = Person(name='frank-' + name, mobile='111111', id_card_number='123456789')print(f"{name} person is add..")session.add(person)time.sleep(1)if name == 'job3':# 線程3 提交, 其他線程不提交.session.commit()session.close()if __name__ == '__main__':thread_list = []# 創建5個線程for i in range(5):name = 'job' + str(i)t = threading.Thread(target=job, name=name, args=(name,))thread_list.append(t)for t in thread_list:t.start()for t in thread_list:t.join()

結論:

每個線程下的 Session 都不相同
只有線程3下的數據被提交到了數據庫

id session:2173841850832
job0 person is add..
id session:2173841851504
job1 person is add..
id session:2173841851896
job2 person is add..
id session:2173841852008
job3 person is add..
id session:2173841853128
job4 person is add..mysql> select * from person;
+----+------------+--------+----------------+
| id | name       | mobile | id_card_number |
+----+------------+--------+----------------+
| 32 | frank-job3 | 111111 | 123456789      |
+----+------------+--------+----------------+
1 row in set (0.00 sec)

2.2 多線程下設置 Session 為全局變量


session_factory = sessionmaker(bind=engine)
Session = scoped_session(session_factory)
session = Session()def job(name):global sessionprint(f"id session:{id(session)}")person = Person(name='frank-' + name, mobile='111111', id_card_number='123456789')print(f"{name} person is add..")session.add(person)time.sleep(1)if name == 'job3':# 線程3 提交, 其他線程不提交.session.commit()session.close()if __name__ == '__main__':thread_list = []# 創建5個線程for i in range(5):name = 'job' + str(i)t = threading.Thread(target=job, name=name, args=(name,))thread_list.append(t)for t in thread_list:t.start()for t in thread_list:t.join()

結論:

每個線程下的 Session 是同一個 Session
每個線程下的數據都沒提交到了數據庫

id session:2810724382032
job0 person is add..
id session:2810724382032
job1 person is add..
id session:2810724382032
job2 person is add..
id session:2810724382032
job3 person is add..
id session:2810724382032
job4 person is add..mysql> select * from person;
+----+------------+--------+----------------+
| id | name       | mobile | id_card_number |
+----+------------+--------+----------------+
| 33 | frank-job0 | 111111 | 123456789      |
| 34 | frank-job2 | 111111 | 123456789      |
| 35 | frank-job1 | 111111 | 123456789      |
| 36 | frank-job3 | 111111 | 123456789      |
| 37 | frank-job4 | 111111 | 123456789      |
+----+------------+--------+----------------+
5 rows in set (0.00 sec)

以上說明:

在同一個線程中,有 scoped_session 的時候,返回的是同一個 Session 對象。
在多線程下,即使通過  scoped_session 創建Session,每個線程下的 Session 都是不一樣的,每個線程都有一個屬于自己的 Session 對象,這個對象只在本線程下共享。 
scoped_session 只有在單線程下才能發揮其作用。在多線程下顯得沒有什么作用。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/456349.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/456349.shtml
英文地址,請注明出處:http://en.pswp.cn/news/456349.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

沒有任何權力的“項目經理”該如何當?

2016.11.25 11:40* 字數 1454 閱讀 108評論 0喜歡 1小王幾月前被任命為項目經理&#xff0c;負責9個人的工作安排。工作上要對上負責&#xff0c;完成項目&#xff0c;可對下小王卻沒有對小組成員的工作考核權&#xff0c;也就是說&#xff0c;不能影響他們的收入。 圖片發自簡…

SparkSQL之Join原理

文章目錄前言&#xff1a;Join背景介紹Join常見分類以及基本實現機制Hash JoinBroadcast Hash JoinShuffle Hash JoinSort-Merge Join總結前言&#xff1a; 寫SQL的時候很多時候都有用到join語句&#xff0c;但是我們真的有仔細想過數據在join的過程到底是怎么樣的嗎&#xff…

SQLAlchemy中filter_by()和filter()的用法不同

filter_by() 和 filter() 的最主要的區別&#xff1a; 模塊語法><&#xff08;大于和小于&#xff09;查詢and_和or_查詢filter_by()直接用屬性名&#xff0c;比較用不支持不支持filter()用類名.屬性名&#xff0c;比較用支持支持 談 filter_by() 的語法之前先看下 filt…

python爬蟲從入門到放棄(六)之 BeautifulSoup庫的使用

上一篇文章的正則&#xff0c;其實對很多人來說用起來是不方便的&#xff0c;加上需要記很多規則&#xff0c;所以用起來不是特別熟練&#xff0c;而這節我們提到的beautifulsoup就是一個非常強大的工具&#xff0c;爬蟲利器。 beautifulSoup “美味的湯&#xff0c;綠色的濃湯…

SparkHiveSQL中Join操作的謂詞下推?

前言&#xff1a; SparkSQL和HiveSQL的Join操作中也有謂詞下推&#xff1f;今天就通過大神的文章來了解下。同樣&#xff0c;如有冒犯&#xff0c;請聯系。 正文 上文簡要介紹了Join在大數據領域中的使用背景以及常用的幾種算法&#xff0d;broadcast hash join 、shuffle h…

【轉載】通過金礦模型介紹動態規劃 (動態規劃入門)

先附上原文地址&#xff1a;http://www.cnblogs.com/sdjl/articles/1274312.html 通過金礦模型介紹動態規劃 對于動態規劃&#xff0c;每個剛接觸的人都需要一段時間來理解&#xff0c;特別是第一次接觸的時候總是想不通為什么這種方法可行&#xff0c;這篇文章就是為了…

flask模型中【外鍵】relationship的使用筆記

模型中relationship的使用筆記 模型.PY class User(db.Model):# __tablename__ user1 #定義表名id db.Column(db.Integer, primary_keyTrue, autoincrementTrue)username db.Column(db.String(10), nullableTrue)password db.Column(db.String(64), nullableTrue)phone …

六種方式實現生產者消費者(未完)

2019獨角獸企業重金招聘Python工程師標準>>> 一、利用Object對象是wait和notify\notifyAll package com.jv.parallel.consumerandproducer.objectwait;public class Car {private volatile int flag 0;public void showConsumer(){System.out.println("I am a…

SQL中基于代價的優化

還記得筆者在上篇文章無意中挖的一個坑么&#xff1f;如若不知&#xff0c;強烈建議看官先行閱讀前面兩文&#xff0d;《SparkSQL Join原理》和《Join中竟然也有謂詞下推?》 第一篇文章主要分析了大數據領域Join的三種基礎算法以及各自的適用場景&#xff0c;第二篇文章在第一…

git如何解決沖突(代碼托管在coding)

分支A提交合并請求到分支B&#xff0c;有沖突git fetch code 拉取遠程倉庫的其他分支代碼&#xff08;我拉代碼是remote add code所以這里是code,可以用git remote查看&#xff09;git checkout 分支A 切換到分支Agit pull code 分支A 拉取分支A代碼git checkout 分支B 切換到分…

cookie和session之會話機制: ? http 協議? ---》 無狀態協議

設置cookie&#xff1a; 通過response對象&#xff1a; response make_response() response.set_cookie(key,value,max_age(單位second),expires(要求是detetime類型)) expires datetime(year2018,month11,day5) #expires是這么設置的 expires datetime.n…

Java Map 怎樣實現Key 的唯一性?

大家都知道。在Map和Set不可存在反復元素&#xff1f; 可是對于內部的細節我們并不了解。今天我們就一塊來 探討一下&#xff01; 1 對于 HashMap HashSet 他們的底層數據結構的實現是&#xff1a;維護了一張 HashTable 。容器中的元素所有存儲在Hashtable 中。他們再加入…

win10下安裝pyspark及碰到的問題

文章目錄前言安裝過程Q1總結&#xff1a;前言 最近由于工作需要&#xff0c;需要了解下pyspark&#xff0c;所以就在win10環境下裝了下&#xff0c;然后在pycharm中使用的時候碰到了一些問題。整個過程可謂是一波三折。下面一一道來。 安裝過程 安裝過程就不詳細說了&#x…

解決AttributeError AttributeError: 'NoneType' object has no attribute 'filename'

原因忘記上傳文件 表單需要加屬性 enctype"multipart/form-data" 否則報錯&#xff01;AttributeError AttributeError: NoneType object has no attribute filename enctype"multipart/form-data是設置表單的MIME編碼。默認情況&#xff0c;這個編碼格式是ap…

SQLAlchemy()分頁器paginate方法

Flask的數據分頁示例 用法&#xff1a; 1&#xff0c;首先寫數據獲取的視圖函數&#xff0c;就像這樣&#xff1a; # 首頁 blog_bp.route(/, endpointindex) def index():#獲取頁數page request.args.get(page,1)paginate Article.query.paginate(pageint(page),per_page3)…

開源中國 2014 年源創會年度計劃

時光總是從敲代碼的指尖不經意地滑過&#xff0c;轉眼2014年已快過去一半&#xff0c;OSC依然心懷著最初的夢想。 源創會&#xff0c;oscer的線下快樂大本營&#xff0c;我們仍在繼續...... 聆聽技術大牛講解最前沿的技術&#xff0c;和同道中人切磋IT秘籍&#xff0c;吃點心侃…

互聯網金融行業申請評分卡(A卡)簡介

文章目錄前言基本概念1、信用違約風險的基本概念什么是信用違約風險&#xff1a;組成部分違約的主體個貸中常用的違約定義M0&#xff0c;M1&#xff0c;M2的定義2、申請評分卡的重要性和特性信貸場景中的評分卡申請評分卡的概念為什么要開發申請評分卡評分卡的特性 &#xff08…

Flask的csrf_token的用法

在flask當中&#xff0c;flask-wtf模塊時攜帶csrf校驗的&#xff0c;只是需要開啟&#xff1b; 如果不開啟校驗就不需要校驗&#xff0c;但是那樣不安全。 Csrf是針對與post請求的跨域限制&#xff0c;get請求沒有作用 csrf_token的開啟 在flask中開啟csrf保護 from flask_…

dotty編譯器語法特性之一交叉類型,聯合類型和文本單例類型

2019獨角獸企業重金招聘Python工程師標準>>> ###翻譯&#xff1a;http://dotty.epfl.ch/docs/reference/intersection-types.html #交叉類型 trait Resettable {def reset(): this.type } trait Growable[T] {def add(x: T): this.type } def f(x: Resettable &…

【轉】Zookeeper 安裝和配置

轉自&#xff1a;http://coolxing.iteye.com/blog/1871009 Zookeeper的安裝和配置十分簡單, 既可以配置成單機模式, 也可以配置成集群模式. 下面將分別進行介紹. 單機模式 1. 配置 點擊這里下載zookeeper的安裝包之后, 解壓到合適目錄. 進入zookeeper目錄下的conf子目錄, 創建z…