python web框架——擴展Django&tornado

一 Django自定義分頁

   目的:自定義分頁功能,並把它寫成模塊(注意其中涉及到的python基礎知識)javascript

    models.py文件css

# Create your models here.
class UserList(models.Model): username = models.CharField(max_length=32) age = models.IntegerField()

    分頁模塊page.py文件html

#!/usr/bin/env python #-*- coding:utf-8 -*-
__author__ = 'mcp'

# 導入後臺標記字符串安全的模塊
from django.utils.safestring import mark_safe # 自定義的分頁類
class Pager(object): def __init__(self, current_page): self.current_page = int(current_page) # 讓方法假裝成屬性,加裝飾器
 @property def start(self): return (self.current_page-1)*10 @property def end(self): return self.current_page*10

    def page_str(self,all_item,base_url): all_page,div = divmod(all_item,10) if div>0: all_page += 1 pager_list = [] if all_page <= 11: start = 1 end = all_page else: if self.current_page < 6: start = 1 end =11 + 1
              else: start = self.current_page - 5 end = self.current_page + 6
                  if self.current_page + 6 > all_page: start = all_page - 11 end = all_page + 1

        for i in range(start,end): # 注意單雙引號的使用,/user_list/?page=
            if i == self.current_page: tmp = '<a style="color:red;font-size:20px;"href="%s%d">%d</a>' %(base_url,i,i,) else: tmp = '<a href="%s%d">%d</a>' %(base_url,i,i,) pager_list.append(tmp) # 上一頁
        if self.current_page > 1: pre_page = '<a href="%s%d">上一頁</a>' %(base_url,self.current_page - 1) else: pre_page = '<a href="javascript:void(0);">上一頁</a>'
         # 下一頁
        if self.current_page < all_page: next_page = '<a href="%s%d">下一頁</a>' %(base_url,self.current_page + 1) else: next_page = '<a href="javascript:void(0);">下一頁</a>'
        
         #在最前面插入上一頁按鈕
 pager_list.insert(0,pre_page) #在最後面插入下一頁按鈕
 pager_list.append(next_page) # return ''.join(pager_list)
         # 直接在後臺標記字符串是安全的
        return  mark_safe(''.join(pager_list))

    views.py文件前端

#!/usr/bin/env python #-*- coding:utf-8 -*-

from django.shortcuts import render from django.shortcuts import HttpResponse from app01 import models
# 導入自定義分頁模塊
from app01 import page # Create your views here. def user_list(request): # 先建立100條表數據 # for item in range(101,500): # dic = {'username':'name%d' %item, 'age':item} # models.UserList.objects.create(**dic) # 再打印數據庫中有多少條數據 # print models.UserList.objects.all().count() # 獲取第0-9條數據,分片 # print type(models.UserList.objects.all()) #<class 'django.db.models.query.QuerySet'> # result = models.UserList.objects.all()[0:10] current_page = request.GET.get('page',1) # 注意current_page爲字符串類型,要轉換成整型 # current_page = int(current_page) # start = (current_page-1)*10 # end = current_page*10 # result = models.UserList.objects.all()[start:end] pager_obj = page.Pager(current_page) # result = models.UserList.objects.all()[pager_obj.start():pager_obj.end()] # 下面這句是從Django ORM中取數據,至關於在數據庫中執行以下sql語句 # SELECT "app01_userlist"."id", "app01_userlist"."username", "app01_userlist"."age"
# FROM "app01_userlist" LIMIT 10 OFFSET 490
result = models.UserList.objects.all()[pager_obj.start:pager_obj.end] # 打印Django ORM中在底層實際執行的sql語句 print result.query # 每頁顯示10條數據 # 共100條 all_item = models.UserList.objects.all().count() # 把下面的代碼封裝到函數中了 pager_str = pager_obj.page_str(all_item,"/user_list/?page=") # all_page,div = divmod(all_item,10) # if div>0: # all_page += 1 # # pager_str = "" # for i in range(1,all_page+1): # # 注意單雙引號的使用 # tmp = '<a href="/user_list/?page=%d">%d</a>' %(i,i,) # pager_str += tmp return render(request,'user_list.html',{'result':result,'pager_str':pager_str})

    user_list.html文件java

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>

    <style> a{ padding: 5px;
        }
    </style>
</head>
<body>
    <h1>測試</h1>
    <table>
        <tbody> {% for line in result %} <tr>
              <td>{{ line.username }}</td>
              <td>{{ line.age }}</td>
           </tr> {% endfor %} </tbody>
    </table> {# <div>#} {# <a href="/user_list/?page=1">1</a>#} {# <a href="/user_list/?page=2">2</a>#} {# <a href="/user_list/?page=3">3</a>#} {# <a href="/user_list/?page=4">4</a>#} {# <a>5</a>#} {# <a>6</a>#} {# <a>7</a>#} {# <a>8</a>#} {# <a>9</a>#} {# <a>10</a>#} {# </div>#} <div> {#在前端標記後臺傳的字符串是安全的#} {#{{ pager_str | safe }}#} {{ pager_str }} </div>
</body>
</html>

    自定義分頁模塊涉及到的知識以及注意點:node

    (1)Django ORMpython

    (2)python中類、屬性、div方法以及封裝特性mysql

    (3)XSS攻擊(在前端或後端標記字符串是安全的)web

    (4)python相關基礎知識以及裝飾器正則表達式

二 自定義Tornado的Session框架

   1 知識回顧

   Tornado中沒有Session部分,這須要開發者去本身擴展Tornado的Session框架。在自定義Session框架以前,先來回顧下Django中Session和Cookie的知識:

    用戶登陸過程當中的Session和Cookie:
        一、在服務端隨機生成一串字符;
        二、將該字符串寫到瀏覽器端,同時將該字符串存儲在服務端,存儲形式爲字典,其中該字符串爲key(服務端Session爲字典形式);
        三、在服務端Session中設置相應值,好比是否已經登陸。

操做Session:
    獲取Session:request.session[key]
    設置Session:reqeust.session[key] = value
    刪除Session:del request[key]
    
request.session.set_expiry(value)
* 若是value爲整數,則Session會在value秒後失效;
* 若是value爲datatime或timedelta,則Session會在這個時間後失效;
* 若是value爲0,則用戶關閉瀏覽器後Session就會失效;
* 若是value爲None,則Session會依賴全局Session失效策略。

    2 自定義Session

     (1)知識儲備

#!/usr/bin/env python # -*- coding:utf-8 -*- class Foo(object): def __getitem__(self, key): print '__getitem__',key def __setitem__(self, key, value): print '__setitem__',key,value def __delitem__(self, key): print '__delitem__',key # 建立obj對象 obj = Foo() # 獲取key爲'k1'的元素,這時會調用__getitem__方法 result = obj['k1'] # 給key爲'k2'的元素賦值,這時會調用__setitem__方法 #obj['k2'] = 'wupeiqi' # 刪除key爲'k3'的元素,這時會調用__delitem__方法 #del obj['k3'] 

    (2)Session框架代碼

#!/usr/bin/env python # -*- coding:utf-8 -*-

import tornado.ioloop import tornado.web from hashlib import sha1 import os, time session_container = {} create_session_id = lambda: sha1('%s%s' % (os.urandom(16), time.time())).hexdigest() class Session(object): session_id = "__sessionId__"

    def __init__(self, request): #當請求過來時,先利用get_cookie方法獲取cookie值,目的是爲了肯定是否存在Cookie,若是有則不生成,不然生成。
        session_value = request.get_cookie(Session.session_id) #若是Cookie不存在,則生成Cookie(建立隨機字符串)
        if not session_value: self._id = create_session_id() else: #若是Cookie存在,則直接將獲取的Cookie值賦值給_id字段
            self._id = session_value #設置Session值
 request.set_cookie(Session.session_id, self._id) #特殊方法:獲取值時調用的方法 
    def __getitem__(self, key): ret = None try: #獲取Session值方法
            ret = session_container[self._id][key] except Exception,e: pass
        return ret #特殊方法:設置值時調用的方法 
    def __setitem__(self, key, value): #判斷是否存在Cookie值,若是存在設置相應的值
        if session_container.has_key(self._id): session_container[self._id][key] = value #若是不存在,則生成相應的字典數據,相似:{'Cookie值':{'IS_LOGIN':'True'}}
        else: session_container[self._id] = {key: value} #特殊方法:刪除值時調用的方法 
    def __delitem__(self, key): del session_container[self._id][key] class BaseHandler(tornado.web.RequestHandler): #擴展了Tornado的initialize方法,這個方法默認爲空方法
    def initialize(self): ''' 這裏initialize的self指向誰? obj = LoginHandler() obj.initialize() ==>LoginHandler類中沒有initialize這個方法,該方法繼承自它的父類 因此initialize的self就是LoginHandler對象 '''
        
        #執行Session類的構造方法,同時把LoginHandler對象傳參給Session類的構造方法
        self.my_session = Session(self) class MainHandler(BaseHandler): def get(self): ret = self.my_session['is_login'] if ret: self.write('index') else: self.redirect("/login") class LoginHandler(BaseHandler): def get(self): ''' 當用戶瀏覽器訪問服務端時,就應該給瀏覽器寫入cookie了,可是這裏沒有寫? 那在哪裏寫入cookie呢?上面定義的相關Handler類都是繼承自RequestHandler,此次繼承的是自定義的BaseHandler類, 繼承自定義的類,而後在類中擴展了initialize方法,獲取用戶cookie或者寫cookie均可以在此方法中操做 '''
        # self.set_cookie()
        # self.get_cookie()
 self.render('login.html', **{'status': ''}) def post(self, *args, **kwargs): #獲取用戶提交的用戶名和密碼
        username = self.get_argument('username') password = self.get_argument('pwd') if username == 'wupeiqi' and password == '123': #若是認證經過,就能夠訪問這個self.my_session對象,而後就能夠把Cookie寫入字典中。
            self.my_session['is_login'] = 'true' self.redirect('/index') else: self.render('login.html', **{'status': '用戶名或密碼錯誤'}) settings = { 'template_path': 'template', 'static_path': 'static', 'static_url_prefix': '/static/', 'cookie_secret': 'abcdefgh', 'login_url': '/login' } application = tornado.web.Application([ #建立兩個URL 分別對應MainHandler和LoginHandler
    (r"/index", MainHandler), (r"/login", LoginHandler), ], **settings) if __name__ == "__main__": application.listen(8888) tornado.ioloop.IOLoop.instance().start()

    (3)分佈式Session框架

     上面使用Tornado預留擴展方法initialize和Class類實現了自定義的Session框架,下面探討如何實現分佈式Session框架。上面自定義的Session框架中,Session默認保存在session_container字典中。實際生產環境中,Session也能夠存儲在Redis,memcache,mysql中,若是把session存儲在單臺服務器上,那麼存在着數據不安全或數據量大時知足不了性能要求。這時能夠考慮分佈式(假設有3臺服務器存儲Session),那麼能夠分別存儲在A、B、C上:

    當用戶第1次訪問時,經過權重和hash計算把session加入到hash環中,實現分佈式存儲;當用戶第2次攜帶Cookie訪問時,經過計算找到相應的Session值並進行認證。

  一致性哈希

#!/usr/bin/env python #coding:utf-8

import sys import math from bisect import bisect if sys.version_info >= (2, 5): import hashlib md5_constructor = hashlib.md5 else: import md5 md5_constructor = md5.new class HashRing(object): #一致性哈希 
    def __init__(self,nodes): ''' 初始化: 包含存儲節點以及節點對應的權重 默認每1個節點有32個虛擬節點 對於權重,經過多建立虛擬節點來實現 如:nodes = [ {'host':'127.0.0.1:8000','weight':1}, {'host':'127.0.0.1:8001','weight':2}, {'host':'127.0.0.1:8002','weight':1}, ] ''' self.ring = dict() self._sorted_keys = [] self.total_weight = 0 self.__generate_circle(nodes) def __generate_circle(self,nodes): for node_info in nodes: self.total_weight += node_info.get('weight',1) for node_info in nodes: weight = node_info.get('weight',1) node = node_info.get('host',None) virtual_node_count = math.floor((32*len(nodes)*weight) / self.total_weight) for i in xrange(0,int(virtual_node_count)): key = self.gen_key_thirty_two( '%s-%s' % (node, i) ) if self._sorted_keys.__contains__(key): raise Exception('該節點已經存在.') self.ring[key] = node self._sorted_keys.append(key) def add_node(self,node): ''' 新建節點node: 新添加節點格式爲:{'host':'127.0.0.1:8002','weight':1},其中第1個元素表示節點,
第2個元素表示該節點的權重。
''' node = node.get('host',None) if not node: raise Exception('節點的地址不能爲空.') weight = node.get('weight',1) self.total_weight += weight nodes_count = len(self._sorted_keys) + 1 virtual_node_count = math.floor((32 * nodes_count * weight) / self.total_weight) for i in xrange(0,int(virtual_node_count)): key = self.gen_key_thirty_two( '%s-%s' % (node, i) ) if self._sorted_keys.__contains__(key): raise Exception('該節點已經存在.') self.ring[key] = node self._sorted_keys.append(key) def remove_node(self,node): ''' 移除節點node: 要移除的節點'127.0.0.1:8000' ''' for key,value in self.ring.items(): if value == node: del self.ring[key] self._sorted_keys.remove(key) def get_node(self,string_key): ''' 獲取string_key所在的節點 ''' pos = self.get_node_pos(string_key) if pos is None: return None return self.ring[ self._sorted_keys[pos]].split(':') def get_node_pos(self,string_key): ''' 獲取string_key所在的節點的索引 ''' if not self.ring: return None key = self.gen_key_thirty_two(string_key) nodes = self._sorted_keys pos = bisect(nodes, key) return pos def gen_key_thirty_two(self, key): m = md5_constructor() m.update(key) return long(m.hexdigest(), 16) def gen_key_sixteen(self,key): b_key = self.__hash_digest(key) return self.__hash_val(b_key, lambda x: x) def __hash_val(self, b_key, entry_fn): return (( b_key[entry_fn(3)] << 24)|(b_key[entry_fn(2)] << 16)|(b_key[entry_fn(1)] << 8)| b_key[entry_fn(0)] ) def __hash_digest(self, key): m = md5_constructor() m.update(key) return map(ord, m.digest()) """ nodes = [ {'host':'127.0.0.1:8000','weight':1}, {'host':'127.0.0.1:8001','weight':2}, {'host':'127.0.0.1:8002','weight':1}, ] ring = HashRing(nodes) result = ring.get_node('98708798709870987098709879087') print result """

    分佈式Session框架代碼:

from hashlib import sha1 import os, time create_session_id = lambda: sha1('%s%s' % (os.urandom(16), time.time())).hexdigest() class Session(object): session_id = "__sessionId__"

    def __init__(self, request): session_value = request.get_cookie(Session.session_id) if not session_value: self._id = create_session_id() else: self._id = session_value request.set_cookie(Session.session_id, self._id) def __getitem__(self, key): # 根據 self._id ,在一致性哈西中找到其對應的服務器IP
        # 找到相對應的redis服務器,如: r = redis.StrictRedis(host='localhost', port=6379, db=0)
        # 使用python redis api 連接
        # 獲取數據,即:
        # return self._redis.hget(self._id, name)

    def __setitem__(self, key, value): # 根據 self._id ,在一致性哈西中找到其對應的服務器IP
        # 使用python redis api 連接
        # 設置session
        # self._redis.hset(self._id, name, value)

    def __delitem__(self, key): # 根據 self._id 找到相對應的redis服務器
        # 使用python redis api 連接
        # 刪除,即:
        return self._redis.hdel(self._id, name)

自定義Tornado的Form框架

   python web框架中,只有Django提供了form框架。在Tornado等其餘python web框架中,須要自定義form框架。Django中的form驗證流程:
       用戶輸入 ==》request.post ==> obj = Form(request.POST) ==> obj.is_valid()
   存在問題:request在獲取用戶輸入時並不知道用戶輸入的個數,Form表單內可能有1個也有可能有多個輸入,這是Django中Form框架存在的問題。

   Form(模型綁定)有兩個主要功能:
    (1)自動生成html表單
    (2)用戶輸入驗證 

   1 簡單的form框架

   index.html文件

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
    <link href="{{static_url("commons.css")}}" rel="stylesheet" />
</head>
<body>
    <h1>hello</h1>
    <form action="/index" method="post">

        <p>hostname: <input type="text" name="host" /> </p>
        <p>ip: <input type="text" name="ip" /> </p>
        <p>port: <input type="text" name="port" /> </p>
        <p>phone: <input type="text" name="phone" /> </p>
        <input type="submit" />
    </form>
</body>
</html>

   index.py文件

#!/usr/bin/env python # -*- coding:utf-8 -*-

import tornado.ioloop import tornado.web from hashlib import sha1 import os, time import re #建立form類
class MainForm(object): #初始化
    def __init__(self): self.host = "(.*)" self.ip = "^(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}$" self.port = '(\d+)' self.phone = '^1[3|4|5|8][0-9]\d{8}$'
    #驗證
    def check_valid(self, request): #循環當前類中的成員,注意此種方法
        for key, regular in self.__dict__.items(): ''' 經過request.get_argument()來獲取用戶前端輸入的值 在循環時,不須要關心前端輸入值的個數,這裏以自定義方法爲主 ''' post_value = request.get_argument(key) #前端提交的數據與自定義的正則表達式進行匹配驗證
            ret = re.match(regular, post_value) print key, ret, post_value class MainHandler(tornado.web.RequestHandler): def get(self): self.render('index.html') def post(self, *args, **kwargs): obj = MainForm() result = obj.check_valid(self) self.write('ok') settings = { 'template_path': 'template', 'static_path': 'static', 'static_url_prefix': '/static/', 'cookie_secret': 'aiuasdhflashjdfoiuashdfiuh', 'login_url': '/login' } application = tornado.web.Application([ (r"/index", MainHandler), ], **settings) if __name__ == "__main__": application.listen(8888) tornado.ioloop.IOLoop.instance().start()

   2  自定義form框架優化版

     (1)驗證字段寫成相應的類;

     (2)類的繼承

     (3)ListForm

  自定義Form完整代碼

#!/usr/bin/env python # -*- coding:utf-8 -*-

import tornado.ioloop import tornado.web import re class Field(object): def __init__(self, error_msg_dict, required): self.id_valid = False self.value = None self.error = None self.name = None self.error_msg = error_msg_dict self.required = required def match(self, name, value): self.name = name if not self.required: self.id_valid = True self.value = value else: if not value: if self.error_msg.get('required', None): self.error = self.error_msg['required'] else: self.error = "%s is required" % name else: ret = re.match(self.REGULAR, value) if ret: self.id_valid = True self.value = ret.group() else: if self.error_msg.get('valid', None): self.error = self.error_msg['valid'] else: self.error = "%s is invalid" % name class IPField(Field): REGULAR = "^(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}$"

    def __init__(self, error_msg_dict=None, required=True): error_msg = {}  # {'required': 'IP不能爲空', 'valid': 'IP格式錯誤'}
        if error_msg_dict: error_msg.update(error_msg_dict) super(IPField, self).__init__(error_msg_dict=error_msg, required=required) class IntegerField(Field): REGULAR = "^\d+$"

    def __init__(self, error_msg_dict=None, required=True): error_msg = {'required': '數字不能爲空', 'valid': '數字格式錯誤'} if error_msg_dict: error_msg.update(error_msg_dict) super(IntegerField, self).__init__(error_msg_dict=error_msg, required=required) class CheckBoxField(Field): def __init__(self, error_msg_dict=None, required=True): error_msg = {}  # {'required': 'IP不能爲空', 'valid': 'IP格式錯誤'}
        if error_msg_dict: error_msg.update(error_msg_dict) super(CheckBoxField, self).__init__(error_msg_dict=error_msg, required=required) def match(self, name, value): self.name = name if not self.required: self.id_valid = True self.value = value else: if not value: if self.error_msg.get('required', None): self.error = self.error_msg['required'] else: self.error = "%s is required" % name else: if isinstance(name, list): self.id_valid = True self.value = value else: if self.error_msg.get('valid', None): self.error = self.error_msg['valid'] else: self.error = "%s is invalid" % name class FileField(Field): REGULAR = "^(\w+\.pdf)|(\w+\.mp3)|(\w+\.py)$"

    def __init__(self, error_msg_dict=None, required=True): error_msg = {}  # {'required': '數字不能爲空', 'valid': '數字格式錯誤'}
        if error_msg_dict: error_msg.update(error_msg_dict) super(FileField, self).__init__(error_msg_dict=error_msg, required=required) def match(self, name, value): self.name = name self.value = [] if not self.required: self.id_valid = True self.value = value else: if not value: if self.error_msg.get('required', None): self.error = self.error_msg['required'] else: self.error = "%s is required" % name else: m = re.compile(self.REGULAR) if isinstance(value, list): for file_name in value: r = m.match(file_name) if r: self.value.append(r.group()) self.id_valid = True else: self.id_valid = False if self.error_msg.get('valid', None): self.error = self.error_msg['valid'] else: self.error = "%s is invalid" % name break
                else: if self.error_msg.get('valid', None): self.error = self.error_msg['valid'] else: self.error = "%s is invalid" % name def save(self, request, upload_path=""): file_metas = request.files[self.name] for meta in file_metas: file_name = meta['filename'] with open(file_name,'wb') as up: up.write(meta['body']) class Form(object): def __init__(self): self.value_dict = {} self.error_dict = {} self.valid_status = True def validate(self, request, depth=10, pre_key=""): self.initialize() self.__valid(self, request, depth, pre_key) def initialize(self): pass

    def __valid(self, form_obj, request, depth, pre_key): """ 驗證用戶表單請求的數據 :param form_obj: Form對象(Form派生類的對象) :param request: Http請求上下文(用於從請求中獲取用戶提交的值) :param depth: 對Form內容的深度的支持 :param pre_key: Html中name屬性值的前綴(多層Form時,內部遞歸時設置,無需理會) :return: 是否驗證經過,True:驗證成功;False:驗證失敗 """ depth -= 1
        if depth < 0: return None form_field_dict = form_obj.__dict__
        for key, field_obj in form_field_dict.items(): print key,field_obj if isinstance(field_obj, Form) or isinstance(field_obj, Field): if isinstance(field_obj, Form): # 獲取以key開頭的全部的值,以參數的形式傳至
                    self.__valid(field_obj, request, depth, key) continue
                if pre_key: key = "%s.%s" % (pre_key, key) if isinstance(field_obj, CheckBoxField): post_value = request.get_arguments(key, None) elif isinstance(field_obj, FileField): post_value = [] file_list = request.request.files.get(key, None) for file_item in file_list: post_value.append(file_item['filename']) else: post_value = request.get_argument(key, None) print post_value # 讓提交的數據 和 定義的正則表達式進行匹配
 field_obj.match(key, post_value) if field_obj.id_valid: self.value_dict[key] = field_obj.value else: self.error_dict[key] = field_obj.error self.valid_status = False class ListForm(object): def __init__(self, form_type): self.form_type = form_type self.valid_status = True self.value_dict = {} self.error_dict = {} def validate(self, request): name_list = request.request.arguments.keys() + request.request.files.keys() index = 0 flag = False while True: pre_key = "[%d]" % index for name in name_list: if name.startswith(pre_key): flag = True break
            if flag: form_obj = self.form_type() form_obj.validate(request, depth=10, pre_key="[%d]" % index) if form_obj.valid_status: self.value_dict[index] = form_obj.value_dict else: self.error_dict[index] = form_obj.error_dict self.valid_status = False else: break index += 1 flag = False class MainForm(Form): def __init__(self): # self.ip = IPField(required=True)
        # self.port = IntegerField(required=True)
        # self.new_ip = IPField(required=True)
        # self.second = SecondForm()
        self.fff = FileField(required=True) super(MainForm, self).__init__() # # class SecondForm(Form): # # def __init__(self): # self.ip = IPField(required=True) # self.new_ip = IPField(required=True) # # super(SecondForm, self).__init__()

class MainHandler(tornado.web.RequestHandler): def get(self): self.render('index.html') def post(self, *args, **kwargs): # for i in dir(self.request):
        # print i
        # print self.request.arguments
        # print self.request.files
        # print self.request.query
        # name_list = self.request.arguments.keys() + self.request.files.keys()
        # print name_list

        # list_form = ListForm(MainForm)
        # list_form.validate(self)
        #         # print list_form.valid_status
        # print list_form.value_dict
        # print list_form.error_dict

        # obj = MainForm()
        # obj.validate(self)
        #         # print "驗證結果:", obj.valid_status
        # print "符合驗證結果:", obj.value_dict
        # print "錯誤信息:"
        # for key, item in obj.error_dict.items():
        # print key,item
        # print self.get_arguments('favor'),type(self.get_arguments('favor'))
        # print self.get_argument('favor'),type(self.get_argument('favor'))
        # print type(self.get_argument('fff')),self.get_argument('fff')
        # print self.request.files
        # obj = MainForm()
        # obj.validate(self)
        # print obj.valid_status
        # print obj.value_dict
        # print obj.error_dict
        # print self.request,type(self.request)
        # obj.fff.save(self.request)
        # from tornado.httputil import HTTPServerRequest
        # name_list = self.request.arguments.keys() + self.request.files.keys()
        # print name_list
        # print self.request.files,type(self.request.files)
        # print len(self.request.files.get('fff'))

        # obj = MainForm()
        # obj.validate(self)
        # print obj.valid_status
        # print obj.value_dict
        # print obj.error_dict
        # obj.fff.save(self.request)
        self.write('ok') settings = { 'template_path': 'template', 'static_path': 'static', 'static_url_prefix': '/static/', 'cookie_secret': 'aiuasdhflashjdfoiuashdfiuh', 'login_url': '/login' } application = tornado.web.Application([ (r"/index", MainHandler), ], **settings) if __name__ == "__main__": application.listen(8888) tornado.ioloop.IOLoop.instance().start()

 

 

參考資料:

       http://www.cnblogs.com/wupeiqi/articles/5341480.html

     http://www.cnblogs.com/luotianshuai/p/5482612.html

相關文章
相關標籤/搜索