1.使用PyMySQL連接mysql
在成功連接python內嵌的sqlite后,我想嘗試連接這個世界使用人數最多的數據庫-MySQL盯滚。于是我去MySQL官網查找官方提供的python驅動兽埃,只找到python3.4版本的侦鹏,而我自己使用的是python3.5.2铜跑,因此無法安裝湿右,百度后發(fā)現(xiàn)有個替代品,即PyMySQL,我在pip中成功得安裝了它并成功得鏈接到我本地的數據庫芜抒,以下是連接的代碼
#-*- coding=utf-8 -*-
import pymysql
conn=pymysql.connect(host='localhost',port=3306,user='root',password='xxx',db='test',charset='UTF8')
cur=conn.cursor()
cur.execute('insert into user (userid,username) values(1,\'ou\')')
cur.close()
conn.commit()
conn.close()
2.使用SQLAlchemy
在Python中珍策,最有名的ORM框架是SQLAlchemy。我們來看看SQLAlchemy的用法宅倒。
首先通過pip安裝SQLAlchemy:
pip install sqlalchemy
然后攘宙,利用上次我們在MySQL的test數據庫中創(chuàng)建的user表,用SQLAlchemy來試試:
第一步拐迁,導入SQLAlchemy蹭劈,并初始化DBSession:
# 導入:
from sqlalchemy import Column, String, create_enginefrom sqlalchemy.orm
import sessionmakerfrom sqlalchemy.ext.declarative
import declarative_base
# 創(chuàng)建對象的基類:
Base = declarative_base()
# 定義User對象:
class User(Base):
# 表的名字:
__tablename__ = 'user'
# 表的結構:
id = Column(String(20), primary_key=True)
name = Column(String(20))
# 初始化數據庫連接:
engine = create_engine('mysql+mysqlconnector://root:password@localhost:3306/test')
# 創(chuàng)建DBSession類型:
DBSession = sessionmaker(bind=engine)
以上代碼完成SQLAlchemy的初始化和具體每個表的class定義。如果有多個表线召,就繼續(xù)定義其他class铺韧,例如School:
class School(Base):
__tablename__ = 'school'
id = ...
name = ...
create_engine()用來初始化數據庫連接。SQLAlchemy用一個字符串表示連接信息:'數據庫類型+數據庫驅動名稱://用戶名:口令@機器地址:端口號/數據庫名'
你只需要根據需要替換掉用戶名缓淹、口令等信息即可哈打。
下面,我們看看如何向數據庫表中添加一行記錄讯壶。
由于有了ORM料仗,我們向數據庫表中添加一行記錄,可以視為添加一個User
對象:
# 創(chuàng)建session對象:
session = DBSession()
# 創(chuàng)建新User對象:
new_user = User(id='5', name='Bob')
# 添加到session:
session.add(new_user)
# 提交即保存到數據庫:
session.commit()
# 關閉
session:session.close()
可見伏蚊,關鍵是獲取session立轧,然后把對象添加到session,最后提交并關閉躏吊。DBSession對象可視為當前數據庫連接氛改。
3.HTTP協(xié)議
協(xié)議是指計算機通信網絡中兩臺計算機之間進行通信所必須共同遵守的規(guī)定或規(guī)則,超文本傳輸協(xié)議(HTTP)是一種通信協(xié)議比伏,它允許將超文本標記語言(HTML)文檔從Web服務器傳送到客戶端的瀏覽器
目前我們使用的是HTTP/1.1 版本
URL詳解
URL(Uniform Resource Locator) 地址用于描述一個網絡上的資源胜卤, 基本格式如下
schema://host[:port#]/path/.../[;url-params][?query-string][#anchor]
scheme 指定低層使用的協(xié)議(例如:http, https, ftp)
host HTTP服務器的IP地址或者域名
port# HTTP服務器的默認端口是80,這種情況下端口號可以省略凳怨。如果使用了別的端口瑰艘,必須指明,例如 http://www.cnblogs.com:8080/
path 訪問資源的路徑
url-params
query-string 發(fā)送給http服務器的數據
anchor- 錨
HTTP協(xié)議是無狀態(tài)的
http協(xié)議是無狀態(tài)的肤舞,同一個客戶端的這次請求和上次請求是沒有對應關系紫新,對http服務器來說,它并不知道這兩個請求來自同一個客戶端李剖。 為了解決這個問題芒率, Web程序引入了Cookie機制來維護狀態(tài).
HTTP消息的結構
先看Request 消息的結構, Request 消息分為3部分篙顺,第一部分叫請求行偶芍, 第二部分叫http header, 第三部分是body. header和body之間有個空行充择, 結構如下圖
第一行中的Method表示請求方法,比如"POST"匪蟀,"GET"椎麦, Path-to-resoure表示請求的資源, Http/version-number 表示HTTP協(xié)議的版本號
當使用的是"GET" 方法的時候材彪, body是為空的
Get和Post方法的區(qū)別
Http協(xié)議定義了很多與服務器交互的方法观挎,最基本的有4種,分別是GET,POST,PUT,DELETE. 一個URL地址用于描述一個網絡上的資源段化,而HTTP中的GET, POST, PUT, DELETE就對應著對這個資源的查嘁捷,改,增显熏,刪4個操作雄嚣。 我們最常見的就是GET和POST了。GET一般用于獲取/查詢資源信息喘蟆,而POST一般用于更新資源信息.
我們看看GET和POST的區(qū)別
1. GET提交的數據會放在URL之后缓升,以?分割URL和傳輸數據,參數之間以&相連履肃,如EditPosts.aspx?name=test1&id=123456. POST方法是把提交的數據放在HTTP包的Body中.
2. GET提交的數據大小有限制(因為瀏覽器對URL的長度有限制)仔沿,而POST方法提交的數據沒有限制.
3. GET方式需要使用Request.QueryString來取得變量的值坐桩,而POST方式通過Request.Form來獲取變量的值尺棋。
4. GET方式提交數據,會帶來安全問題绵跷,比如一個登錄頁面膘螟,通過GET方式提交數據時,用戶名和密碼將出現(xiàn)在URL上碾局,如果頁面可以被緩存或者其他人可以訪問這臺機器荆残,就可以從歷史記錄獲得該用戶的賬號和密碼.
狀態(tài)碼
Response 消息中的第一行叫做狀態(tài)行,由HTTP協(xié)議版本號净当, 狀態(tài)碼内斯, 狀態(tài)消息 三部分組成。
狀態(tài)碼用來告訴HTTP客戶端像啼,HTTP服務器是否產生了預期的Response.
HTTP/1.1中定義了5類狀態(tài)碼俘闯, 狀態(tài)碼由三位數字組成,第一個數字定義了響應的類別
1XX 提示信息 - 表示請求已被成功接收忽冻,繼續(xù)處理
2XX 成功 - 表示請求已被成功接收真朗,理解,接受
3XX 重定向 - 要完成請求必須進行更進一步的處理
4XX 客戶端錯誤 - 請求有語法錯誤或請求無法實現(xiàn)
5XX 服務器端錯誤 - 服務器未能實現(xiàn)合法的請求
看看一些常見的狀態(tài)碼
200 OK
最常見的就是成功響應狀態(tài)碼200了僧诚, 這表明該請求被成功地完成遮婶,所請求的資源發(fā)送回客戶端
302 Found
重定向蝗碎,新的URL會在response中的Location中返回,瀏覽器將會使用新的URL發(fā)出新的Request旗扑。
304 Not Modified 代表上次的文檔已經被緩存了蹦骑, 還可以繼續(xù)使用
400 Bad Request 客戶端請求與語法錯誤,不能被服務器所理解
403 Forbidden 服務器收到請求臀防,但是拒絕提供服務
404 Not Found 請求資源不存在(輸錯了URL)
500 Internal Server Error 服務器發(fā)生了不可預期的錯誤
503 Server Unavailable 服務器當前不能處理客戶端的請求脊串,一段時間后可能恢復正常
4.WSGI接口
了解了HTTP協(xié)議和HTML文檔,我們其實就明白了一個Web應用的本質就是:
瀏覽器發(fā)送一個HTTP請求清钥;
服務器收到請求琼锋,生成一個HTML文檔;
服務器把HTML文檔作為HTTP響應的Body發(fā)送給瀏覽器祟昭;
瀏覽器收到HTTP響應缕坎,從HTTP Body取出HTML文檔并顯示。
所以篡悟,最簡單的Web應用就是先把HTML用文件保存好谜叹,用一個現(xiàn)成的HTTP服務器軟件,接收用戶請求搬葬,從文件中讀取HTML荷腊,返回。Apache急凰、Nginx女仰、Lighttpd等這些常見的靜態(tài)服務器就是干這件事情的。
如果要動態(tài)生成HTML抡锈,就需要把上述步驟自己來實現(xiàn)疾忍。不過,接受HTTP請求床三、解析HTTP請求一罩、發(fā)送HTTP響應都是苦力活,如果我們自己來寫這些底層代碼撇簿,還沒開始寫動態(tài)HTML呢聂渊,就得花個把月去讀HTTP規(guī)范。
正確的做法是底層代碼由專門的服務器軟件實現(xiàn)四瘫,我們用Python專注于生成HTML文檔汉嗽。因為我們不希望接觸到TCP連接、HTTP原始請求和響應格式莲组,所以诊胞,需要一個統(tǒng)一的接口,讓我們專心用Python編寫Web業(yè)務。
這個接口就是WSGI:Web Server Gateway Interface撵孤。
WSGI接口定義非常簡單迈着,它只要求Web開發(fā)者實現(xiàn)一個函數,就可以響應HTTP請求邪码。我們來看一個最簡單的Web版本的“Hello, web!”:
def application(environ, start_response):
start_response('200 OK', [('Content-Type', 'text/html')])
return [b'<h1>Hello, web!</h1>']
上面的application()函數就是符合WSGI標準的一個HTTP處理函數裕菠,它接收兩個參數:
environ:一個包含所有HTTP請求信息的dict
對象;
start_response:一個發(fā)送HTTP響應的函數闭专。
在application()函數中奴潘,調用:
start_response('200 OK', [('Content-Type', 'text/html')])
就發(fā)送了HTTP響應的Header,注意Header只能發(fā)送一次影钉,也就是只能調用一次start_response()函數画髓。start_response()函數接收兩個參數,一個是HTTP響應碼平委,一個是一組list表示的HTTP Header奈虾,每個Header用一個包含兩個str的tuple表示。通常情況下廉赔,都應該把Content-Type頭發(fā)送給瀏覽器肉微。其他很多常用的HTTP Header也應該發(fā)送。然后蜡塌,函數的返回值
b'<h1>Hello, web!</h1>'
將作為HTTP響應的Body發(fā)送給瀏覽器碉纳。
有了WSGI,我們關心的就是如何從environ這個dict對象拿到HTTP請求信息馏艾,然后構造HTML劳曹,通過start_response()發(fā)送Header,最后返回Body攒至。
整個application()函數本身沒有涉及到任何解析HTTP的部分厚者,也就是說躁劣,底層代碼不需要我們自己編寫迫吐,我們只負責在更高層次上考慮如何響應請求就可以了。
不過账忘,等等志膀,這個application()函數怎么調用?如果我們自己調用鳖擒,兩個參數environ和start_response我們沒法提供溉浙,返回的bytes也沒法發(fā)給瀏覽器。所以application()函數必須由WSGI服務器來調用蒋荚。有很多符合WSGI規(guī)范的服務器戳稽,我們可以挑選一個來用。但是現(xiàn)在,我們只想盡快測試一下我們編寫的application()函數真的可以把HTML輸出到瀏覽器惊奇,所以互躬,要趕緊找一個最簡單的WSGI服務器,把我們的Web應用程序跑起來颂郎。
好消息是Python內置了一個WSGI服務器艰管,這個模塊叫wsgiref疚鲤,它是用純Python編寫的WSGI服務器的參考實現(xiàn)。所謂“參考實現(xiàn)”是指該實現(xiàn)完全符合WSGI標準,但是不考慮任何運行效率歹鱼,僅供開發(fā)和測試使用。
運行WSGI服務我們先編寫hello.py實現(xiàn)Web應用程序的WSGI處理函數:
# hello.py
def application(environ, start_response):
start_response('200 OK', [('Content-Type', 'text/html')])
return [b'<h1>Hello, web!</h1>']
然后赔硫,再編寫一個server.py滨达,負責啟動WSGI服務器,加載application()
函數:
# server.py
# 從wsgiref模塊導入:
from wsgiref.simple_server import make_server
# 導入我們自己編寫的application函數:
from hello import application
# 創(chuàng)建一個服務器陨献,IP地址為空咙俩,端口是8000,處理函數是application:
httpd = make_server('', 8000, application)
print('Serving HTTP on port 8000...')
# 開始監(jiān)聽HTTP請求:
httpd.serve_forever()
確保以上兩個文件在同一個目錄下湿故,然后在命令行輸入python server.py
來啟動WSGI服務器:
注意:如果8000端口已被其他程序占用阿趁,啟動將失敗,請修改成其他端口坛猪。
啟動成功后脖阵,打開瀏覽器,輸入http://localhost:8000/墅茉,就可以看到結果了:
如果你覺得這個Web應用太簡單了命黔,可以稍微改造一下,從environ
里讀取PATH_INFO
就斤,這樣可以顯示更加動態(tài)的內容:
# hello.py
def application(environ, start_response):
start_response('200 OK', [('Content-Type', 'text/html')])
body = '<h1>Hello, %s!</h1>' % (environ['PATH_INFO'][1:] or 'web')
return [body.encode('utf-8')]
你可以在地址欄輸入用戶名作為URL的一部分悍募,將返回Hello, xxx!