tornado web高级开发项目

Posted ExplorerMan

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了tornado web高级开发项目相关的知识,希望对你有一定的参考价值。

本博文将一步步带领你实现抽屉官网的各种功能:包括登陆注册发送邮箱验证码登陆验证码页面登陆验证发布文章上传图片form验证点赞、评论、文章分页处理以及基于tornado的后端和ajax的前端数据处理。

转载请注明出处http://www.cnblogs.com/wanghzh/p/5806514.html

抽屉官网:http://dig.chouti.com/

一、配置(settings)

1
2
3
4
5
6
7
settings = {
    \'template_path\': \'views\',    #模板文件路径
    \'static_path\': \'statics\',        #静态文件路径
    \'static_url_prefix\': \'/statics/\'#静态文件前缀
    \'autoreload\': True,
    \'ui_methods\': mt
}

二、路由配置

1
2
3
4
5
6
7
8
9
10
application = tornado.web.Application([
    (r"/index", home.IndexHandler),    #主页
    (r"/check_code", account.CheckCodeHandler),  #验证码
    (r"/send_msg", account.SendMsgHandler),  #邮箱验证码
    (r"/register", account.RegisterHandler),  #注册
    (r"/login", account.LoginHandler),    #登陆
    (r"/upload_image", home.UploadImageHandler),  #上传图片
    (r"/comment", home.CommentHandler),  #评论
    (r"/favor", home.FavorHandler),   #点赞
], **settings)

三、文件夹分类

下面我们将根据上图文件目录由上到下做一一分析:

四、准备工作

  本项目所有前端反馈均是通过BaseResponse类实现的:

1
2
3
4
5
6
7
8
class BaseResponse:
 
    def __init__(self):
        self.status = False    #状态信息,是否注册成功,是否登陆成功,是否点赞成功、是否评论成功等
        self.code = StatusCodeEnum.Success
        self.data = None        #前端需要展示的数据
        self.summary = None    #错误信息
        self.message = {}    #字典类型的错误信息

本文参考了大量前端和后端基础知识,从入门到精通的链接如下:

前端:

后端:

数据库:

缓存:

五、core:业务处理类handler需要继承的父类

1
2
3
4
5
6
7
8
9
import tornado.web
from backend.session.session import SessionFactory
 
 
class BaseRequestHandler(tornado.web.RequestHandler):
 
    def initialize(self):
 
        self.session = SessionFactory.get_session_obj(self)

六、form:用于form验证的文件,这是一个自定义的tornado form验证模块

  fields:包含字符串、邮箱、数字、checkbox、文件类型验证

  forms:核心验证处理,返回验证是否成功self._valid_status、成功后的数据提self._value_dict、错误信息self._error_dict

class Field:

    def __init__(self):

        self.is_valid = False
        self.name = None
        self.value = None
        self.error = None

    def match(self, name, value):
        self.name = name

        if not self.required:
            self.is_valid = True
            self.value = value
        else:
            if not value:
                if self.custom_error_dict.get(\'required\', None):
                    self.error = self.custom_error_dict[\'required\']
                else:
                    self.error = "%s is required" % name
            else:
                ret = re.match(self.REGULAR, value)
                if ret:
                    self.is_valid = True
                    self.value = value
                else:
                    if self.custom_error_dict.get(\'valid\', None):
                        self.error = self.custom_error_dict[\'valid\']
                    else:
                        self.error = "%s is invalid" % name
初始化
class StringField(Field):

    REGULAR = "^.*$"

    def __init__(self, custom_error_dict=None, required=True):

        self.custom_error_dict = {}  # {\'required\': \'IP不能为空\', \'valid\': \'IP格式错误\'}
        if custom_error_dict:
            self.custom_error_dict.update(custom_error_dict)

        self.required = required

        super(StringField, self).__init__()
字符串匹配
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, custom_error_dict=None, required=True):

        self.custom_error_dict = {}  # {\'required\': \'IP不能为空\', \'valid\': \'IP格式错误\'}
        if custom_error_dict:
            self.custom_error_dict.update(custom_error_dict)

        self.required = required
        super(IPField, self).__init__()
ip匹配
class EmailField(Field):

    REGULAR = "^\\w+([-+.\']\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*$"

    def __init__(self, custom_error_dict=None, required=True):

        self.custom_error_dict = {}  # {\'required\': \'IP不能为空\', \'valid\': \'IP格式错误\'}
        if custom_error_dict:
            self.custom_error_dict.update(custom_error_dict)

        self.required = required
        super(EmailField, self).__init__()
邮箱匹配
class IntegerField(Field):

    REGULAR = "^\\d+$"

    def __init__(self, custom_error_dict=None, required=True):

        self.custom_error_dict = {}  # {\'required\': \'IP不能为空\', \'valid\': \'IP格式错误\'}
        if custom_error_dict:
            self.custom_error_dict.update(custom_error_dict)

        self.required = required
        super(IntegerField, self).__init__()
数字匹配
class CheckBoxField(Field):

    REGULAR = "^\\d+$"

    def __init__(self, custom_error_dict=None, required=True):

        self.custom_error_dict = {}  # {\'required\': \'IP不能为空\', \'valid\': \'IP格式错误\'}
        if custom_error_dict:
            self.custom_error_dict.update(custom_error_dict)

        self.required = required
        super(CheckBoxField, self).__init__()

    def match(self, name, value):
        self.name = name

        if not self.required:
            self.is_valid = True
            self.value = value
        else:
            if not value:
                if self.custom_error_dict.get(\'required\', None):
                    self.error = self.custom_error_dict[\'required\']
                else:
                    self.error = "%s is required" % name
            else:
                if isinstance(name, list):
                    self.is_valid = True
                    self.value = value
                else:
                    if self.custom_error_dict.get(\'valid\', None):
                        self.error = self.custom_error_dict[\'valid\']
                    else:
                        self.error = "%s is invalid" % name
checkbox匹配
class FileField(Field):

    REGULAR = "^(\\w+\\.pdf)|(\\w+\\.mp3)|(\\w+\\.py)$"

    def __init__(self, custom_error_dict=None, required=True):

        self.custom_error_dict = {}  # {\'required\': \'IP不能为空\', \'valid\': \'IP格式错误\'}
        if custom_error_dict:
            self.custom_error_dict.update(custom_error_dict)

        self.required = required

        super(FileField, self).__init__()

    def match(self, name, file_name_list):
        flag = True
        self.name = name

        if not self.required:
            self.is_valid = True
            self.value = file_name_list
        else:
            if not file_name_list:
                if self.custom_error_dict.get(\'required\', None):
                    self.error = self.custom_error_dict[\'required\']
                else:
                    self.error = "%s is required" % name
                flag = False
            else:
                for file_name in file_name_list:
                    if not file_name or not file_name.strip():
                        if self.custom_error_dict.get(\'required\', None):
                            self.error = self.custom_error_dict[\'required\']
                        else:
                            self.error = "%s is required" % name
                        flag = False
                        break
                    else:
                        ret = re.match(self.REGULAR, file_name)
                        if not ret:
                            if self.custom_error_dict.get(\'valid\', None):
                                self.error = self.custom_error_dict[\'valid\']
                            else:
                                self.error = "%s is invalid" % name
                            flag = False
                            break

            self.is_valid = flag

    def save(self, request, upload_to=""):

        file_metas = request.files[self.name]
        for meta in file_metas:
            file_name = meta[\'filename\']
            file_path_name = os.path.join(upload_to, file_name)
            with open(file_path_name, \'wb\') as up:
                up.write(meta[\'body\'])

        upload_file_path_list = map(lambda path: os.path.join(upload_to, path), self.value)
        self.value = list(upload_file_path_list)
文件匹配

核心验证处理:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
from backend.form import fields
 
 
class BaseForm:
 
    def __init__(self):
        self._value_dict = {} #数据字典
        self._error_dict = {} #错误信息字典
        self._valid_status = True #是否验证成功
 
    def valid(self, handler):
 
        for field_name, field_obj in self.__dict__.items():
            if field_name.startswith(\'_\'):  #过滤私有字段
                continue
 
            if type(field_obj) == fields.CheckBoxField:  #checkbox处理
                post_value = handler.get_arguments(field_name, None)
            elif type(field_obj) == fields.FileField:  #文件处理
                post_value = []
                file_list = handler.request.files.get(field_name, [])
                for file_item in file_list:
                    post_value.append(file_item[\'filename\'])
            else:
                post_value = handler.get_argument(field_name, None)
 
            field_obj.match(field_name, post_value)  #匹配
            if field_obj.is_valid:                    #如果验证成功
                self._value_dict[field_name] = field_obj.value  #提取数据
            else:
                self._error_dict[field_name] = field_obj.error  #错误信息
                self._valid_status = False
        return self._valid_status    #返回是否验证成功

七、如何应用上述form验证模块:

以注册为例:

前端:

<div class="header">
                <span>注册</span>
                <div class="dialog-close" onclick="CloseDialog(\'#accountDialog\');">X</div>
            </div>
            <div class="content">
                <div style="padding: 0 70px">
                    <div class="tips">
                        <span>输入注册信息</span>
                    </div>
                    <div id="register_error_summary" class="error-msg">

                    </div>
                    <div class="inp">
                        <input name="username" type="text" placeholder="请输入用户名" />

                    </div>
                    <div class="inp">
                        <input name="email" id="email" type="text" placeholder="请输入邮箱" />
                    </div>
                    <div class="inp">
                        <input name="email_code" class="email-code" type="text" placeholder="请输入邮箱验证码" />
                        <a id="fetch_code" class="fetch-code" href="javascript:void(0);">获取验证码</a>
                    </div>
                    <div class="inp">
                        <input name="password" type="password" placeholder="请输入密码" />
                    </div>
                    <div class="inp">
                        <div class="submit" onclick="SubmitRegister(this);">
                            <span>注册</span>
                            <span class="hide">
                                <img src="/statics/images/loader.gif" style="height: 16px;width: 16px">
                                <span>正在注册</span>
                            </span>
                        </div>
                    </div>
                </div>
            </div>
html
js:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
/*
        点击注册按钮
        */
        function SubmitRegister(ths){
            $(\'#register_error_summary\').empty();
            $(\'#model_register .inp .error\').remove();
 

(c)2006-2019 SYSTEM All Rights Reserved IT常识