tornado 04注册模块的实现 - nuanxin1111/react GitHub Wiki

我们现在来写一个注册模块来看看各个目录模块之间是如何协同工作的。 首先 config/settings

settings = { 
        #"secure cookies":True,
        #用于 secure_cookie
        "cookie_secret":"y6KHYgM1SbCtH8axxEgt1omSARJwmkaMoBlezBg0EEE=",

        #session_secret 用于session
        "session_secret":"6Mv2JMqLQVC/WO6x0pStUKXy6deVg0ULvOSVQzp1A88=",
        "template_path": "templates", 
        "static_path": "static",
        "login_url":"/login",
        "xsrf_cookies":True,
        #redis设置
        "store_options":{
            'redis_host':'localhost',    
            'redis_port':6379,
            'redis_pass':'',
        },  

        #mongodb设置
        "mongo_options":{
            'hostaddress':'localhost',
            'collection':'demo',
        },  

        #mysql设置
       "mysql_options":{
            'hostaddress':'localhost',
            'database':'demo',
            'user':'root',
            'password':'123456',
        },

        #session生存周期 seconds
        "session_timeout":30*60,
        "debug":True
       }

在这个定义配置的文件中,我们设置了cookie和session的配置,配置了redis,mongodb,mysql的服务。我们可以根据需要在这里增加或者修改配置。

config/urls.py

import os
import sys 

from handler import index

urls = [ 

    (r"/register", index.RegisterHandler),

]

在进行一个模块开发的时候,你需要做的首先就是在这注册你的handler,这个很像我们在做django时候的urls,事实上工作起来也类似。我们要做一个注册模块,首先我们在urls中注册了我们自己的handler。 接着我们要写自己的handler

handler/index.py

import tornado.web
import pymongo
import json

class RegisterHandler(tornado.web.RequestHandler):
    def get(self):
        self.render("register.html")

    def post(self):
        """handle the register request
        """
        name = self.get_argument('name')
        sex = self.get_argument('sex')
        age = self.get_argument('age')
        tel = self.get_argument('tel')
        passwd = self.get_argument('passwd')

        db = self.application.myMongodb
        context = {'name':name, 'sex':sex, 'age':age, 'tel':tel, 'passwd':passwd}
        db.users.insert(context)
        self.write('注册成功')

大致就是在get请求访问过来的时候我们去渲染一个注册表单去前台,然后处理表单的post的请求。现在我们去看看自己的表单,在编写顺序的时候不是说就编写完整的handler之后再去写前端页面,事实上我是编写了get请求之后然后去编写的表单,最后再处理post的请求。 前端页面太过于啰嗦,可以去查看源码,就是一些input,然后ajax请求。 因为在settings中开启了安全cookie的选项,我们在做ajax请求的时候必须要取得cookie中的_xsrf数据,然后随着数据一块发送到后台。现在你只需要跟着做就行,后面我会介绍tornado的secure_cookie。 在前端的页面,如果有ajax请求,你需要在body标签里面使用:

{% module xsrf_form_html() %}

我们来看看ajax部分: register.html

<script type="text/javascript">
$(document).ready(function(){
        
    $("#password").focus(function(){
        $("#myinfo-submit").addClass("orange");
        $("#myinfo-submit").attr("disabled", false);  
        });

    $("#myinfo-submit").click(function(){
        var name = $("#name").val();        
        var sex = $("input:radio[name='sex']:checked").val();
        var age = $("#age").val();
        var tel = $("#tel").val();
        var passwd = $("#password").val();
        var _xsrf = getCookie('_xsrf');

        $.ajax({
           type: "POST",
           url: "/register",
           data: {
                name:name, 
                sex:sex,
                age:age,
                tel:tel,
                passwd:passwd,
 success:function(data) {
            alert(data);
            window.location.href='/login';
           },

            error:function() {
            alert('注册失败');
            }
        });
});
});

</script>

{% module xsrf_form_html() %}这个模块会自动在浏览器中去设置key为_csrf的cookie,我们需要用js去提取,然后随着ajax请求发送到后台。 我们上面的代码用到了getCookie这个提取_csrf的函数,下面是实现: js/common.js

function getCookie(name){
       var result = null;
          //对cookie信息进行相应的处理,方便搜索
          var myCookie = ""+document.cookie+";"; 
            var searchName = ""+name+"=";
             var startOfCookie = myCookie.indexOf(searchName);
              var endOfCookie;
              if(startOfCookie != -1){
              startOfCookie += searchName.length;
              endOfCookie = myCookie.indexOf(";",startOfCookie);
              result = (myCookie.substring(startOfCookie,endOfCookie));
            }   
    return result;
} //end function

在ajax请求之后,我们处理请求的代码就是上面handler中处理post请求的代码。 首先用了self.get_argument来接收发送过的数据,然后我们调用mongodb来插入数据。那么,看到这儿,会很疑惑,我们什么时候启动的mongo实例呢。 在我们的server.py中:

import os
import sys

import tornado.ioloop
import tornado.options
import tornado.httpserver

#multi process
import tornado.netutil
import tornado.process
import pymongo

from tornado.options import define, options
from config import urls
from config import settings
from util import session

import torndb
import logging


define("port", default=8888, help="run on the given port", type=int)


class Application(tornado.web.Application):
    def __init__(self):
        handlers = urls.urls
        setting = settings.settings
        #connect mongo
        client = pymongo.MongoClient(setting['mongo_options']['hostaddress'])
        self.myMongodb = client[setting['mongo_options']['collection']]

        tornado.web.Application.__init__(self, handlers, **setting)
        self.session_manager = session.SessionManager(
                setting['session_secret'],
                setting['store_options'],
                setting['session_timeout']
                )

def main():
    tornado.options.parse_command_line()

    #multi process
    sockets = tornado.netutil.bind_sockets(options.port)
    tornado.process.fork_processes(2)

    http_server = tornado.httpserver.HTTPServer(Application())
    http_server.add_sockets(sockets)
    print 'Development server is running at http://127.0.0.1:%s/' % options.port
    tornado.ioloop.IOLoop.instance().start()

if __name__ == '__main__':
    main()

关于在上面导入的其他模块,我们后面都会分析,在Application初始化的时候我们就连接了mongodb,为此我们需要安装pymongo.

pip install pymongo

在此也附注上pip freeze list

MySQL-python==1.2.3
argparse==1.2.1
asyncmongo==1.3
backports-abc==0.4
backports.ssl-match-hostname==3.5.0.1
certifi==2015.11.20.1
constants==0.6.0
meld3==1.0.2
peewee==2.8.0
pymongo==3.2
redis==2.10.5
singledispatch==3.4.0.3
six==1.10.0
supervisor==3.2.0
tornado==4.3
torndb==0.3
ujson==1.35
wsgiref==0.1.2
⚠️ **GitHub.com Fallback** ⚠️