# 對程式中可能經常變化的值應該提取到配置檔案中
# 建立檔案夾在檔案夾下建立file,充當配置檔案
from tornado.httpserver import HTTPServer
from tornado.ioloop import IOLoop
from tornado.options import define, parse_config_file, options
from tornado.web import Application, RequestHandler
class IndexHandler(RequestHandler):
def get(self,*args,**kwargs):
html = '<form method=post action=/login enctype=multipart/form-data>' \
'<span style=color:red;>使用者名</span>'\
'<input type=text name=username><br>'\
'<span>密碼</span>'\
'<input type=password name=password><br>'\
'<input type=file name=avatar><br>'\
'<input type=file name=avatar><br>'\
'<input type=submit value=送出>  '\
'<input type=reset value=重置>'\
'</form>'
fail_html = '<form method=post action=/login>' \
'<span style=color:red;>使用者名</span>'\
'<input type=text name=username><br>'\
'<span>密碼</span>'\
'<input type=password name=password><br>'\
'<span>使用者名或密碼錯誤!</span><br>'\
'<input type=submit value=送出>  '\
'<input type=reset value=重置>'\
'</form>'
# 擷取以get方式發起請求時攜帶的參數
msg = self.get_query_argument('msg',None)
print(msg)# fail
msgs = self.get_query_arguments('msg')
print(msgs)# ['fail']
if msg:
# msg存在說明出錯了
self.write(fail_html)
else:
self.write(html)
def post(self,*args,**kwargs):
pass
class LoginHandler(RequestHandler):
def get(self,*args,**kwargs):
pass
def post(self,*args,**kwargs):
# 如果使用者輸入的使用者名是abc,密碼是123
# 資訊輸入正确,否則不正确
username = self.get_body_argument('username',None)
password = self.get_body_argument('password',None)
print(username,password)
usernames = self.get_body_arguments('username')
passwords = self.get_body_arguments('password')
print(usernames,passwords)
if username == 'abc' and password == '123':
# 如果使用者上傳了圖檔,則儲存圖檔
# self.get_body_argument('avatar')
# HTTPServerRequest對象的files屬性
# 以字典的方式組織上傳的檔案
# 如果圖檔未上傳,則files屬性就是一個{}
files = self.request.files
if files:
# 使用者上傳了檔案
# {鍵名:[上傳檔案1,上傳檔案2...],
# 鍵名2:[上傳檔案a,上傳檔案b...]}
# 擷取使用者上傳的圖檔并儲存
avatars = files.get('avatar')
for avatar in avatars:
# 上傳檔案有3個屬性
# type屬性:該檔案的類型
# 例如image/jpeg
# filename屬性:該檔案原始的名字
# body屬性:該檔案的内容(以二進制格式)
body = avatar.get('body')
# 将body寫入一個檔案儲存起來
writer = open('../upload/%s' % avatar.get('filename'),'wb')
writer.write(body)
writer.close()
# 跳轉到全新的界面
self.redirect('/blog?username='+username)
else:
# 回到登入界面重新登入
self.redirect('/?msg=fail')
class BlogHandler(RequestHandler):
def get(self,*args,**kwargs):
username = self.get_query_argument('username',None)
# 擷取自定義請求頭的内容
print(self.request)
# 擷取所有請求頭的相關内容(對象的屬性)
hs = self.request.headers
# 有這個鍵就取相關的值,沒有這個鍵就預設為None
v = hs.get('myhead',None)
print(v)
if username:
self.write('歡迎'+username+'來到BLOG頁面')
else:
# 沒有使用者名登入,直接通路了
self.write('歡迎來到BLOG頁面')
def post(self,*args,**kwargs):
u = self.get_argument('username')
print(u)
us = self.get_arguments('username')
print(us)
define('duankou',type=int,default=9999)
# 目前檔案所在檔案夾的上一個(mytornado)下的config/config
parse_config_file('../config/config')
app = Application([('/',IndexHandler),
('/login',LoginHandler),
('/blog',BlogHandler)])
# 建立真正的伺服器程式
server = HTTPServer(app)
# 讓伺服器監聽某一個端口(端口号是一個int,原則上不小于10000)
server.listen(options.duankou)
# 目前線程中啟動伺服器
IOLoop.current().start()
相關筆記:
1.利用get_body_argument或get_body_arguments可以獲得請求體中的參數.
get_body_argument獲得的是單獨的參數值,
get_body_arguments獲得的是清單形式的參數值.
另外,兩者還有2個明顯的差別:
1.使用get_body_argument時,最好提供預設值,
防止通路時沒有提供伺服器需要的參數導緻的400:bad request.
使用get_body_arguments時,如果用戶端沒有提供伺服器需要的參數,
隻會獲得一個空清單,不會産生錯誤.
2.如果在請求體中存在重名的參數,get_body_argument僅能取到最後一個設定的參數值,
而get_body_arguments可以取到所有的重名的鍵所對應的值.
例如:對username重複輸入zhangsan,lisi,wangwu
get_body_argument取到的值是wangwu
get_body_arguments取到的值是[‘zhangsan’,’lisi’,’wangwu’]
2.界面的跳轉:self.redirect(路徑)
3.利用get_query_argument或get_query_arguments可以獲得以get方式發起請求時攜帶的參數.
get_query_argument獲得的是單獨參數值,
get_query_arguments獲得的是以清單形式組織的參數值.
另外,兩者還有2個明顯差別:
1.利用get_query_argument時,最好提供預設值,
防止用戶端通路時未提供所需參數導緻400:Bad Request錯誤.
使用get_query_arguments時,用戶端未提供所需參數時,隻會獲得一個空清單,但不會産生錯誤.
2.當有多個重名的參數提供時,利用get_query_argument僅能獲得最後一個參數值,
利用get_query_arguments可以獲得所有重名參數的參數值.
4.get_argument擷取請求參數:
就像get_query_argument+get_body_argument,
無論請求參數是出現在請求行中還是請求體中,隻要有該參數名稱就能獲得參數值
get_arguments擷取請求參數:
就像get_query_arguments+get_body_arguments,
無論請求參數出現在請求行還是請求體中,都能以清單的形式将參數值獲得
10.RequestHandler裡面有一個屬性,叫做request,
引用着一個HttpServerRequest類型的對象,該對象中封裝了與請求相關的幾乎一切内容.
HTTPServerRequest(protocol=’http’, host=’localhost:9999’, method=’GET’,
uri=’/blog?username=abc’, version=’HTTP/1.1’, remote_ip=’127.0.0.1’,
headers={‘Accept’: ‘text/html,application/xhtml+xml,application/xml;
q=0.9,/;q=0.8’, ‘Host’: ‘localhost:9999’,
‘Accept-Language’: ‘en-GB,en;q=0.5’,
‘Accept-Encoding’: ‘gzip, deflate’,
‘Referer’: ‘http://localhost:9999/‘,
‘Cookie’: ‘csrftoken=ZEOtPCrQtomQLum02c4uZc1LBGZSC1FdHGq1XzwS6TwlQyuHdpl1NaK62VV9IpiK’, ‘Upgrade-Insecure-Requests’: ‘1’, ‘Connection’: ‘keep-alive’, ‘User-Agent’: ‘Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:61.0) Gecko/20100101 Firefox/61.0’})
我們可以利用self.request.headers擷取所有請求頭.
headers是以字典的方式組織請求頭中的名和值.
可以利用self.request.files擷取上傳的檔案.
files也是以字典的形式組織上傳的檔案.
每一個上傳檔案都有3個屬性:
type屬性,表示檔案的類型(例如image/jpeg),
filename屬性,表示檔案的檔案名稱,
body屬性,二進制格式的檔案内容.通過标準的IO操作,就可以将上傳的檔案儲存到伺服器了.