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

相关文章
相关标签/搜索