天天看點

tornado完成一個簡單的登入界面/圖檔的上傳

# 對程式中可能經常變化的值應該提取到配置檔案中
# 建立檔案夾在檔案夾下建立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=送出>&nbsp;&nbsp;&nbsp'\
                '<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=送出>&nbsp;&nbsp;&nbsp'\
                '<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操作,就可以将上傳的檔案儲存到伺服器了.

繼續閱讀