本博文将一步步带领你实现抽屉官网的各种功能:包括登陆、注册、发送邮箱验证码、登陆验证码、页面登陆验证、发布文章、上传图片、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__()
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
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>
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(); $(ths).children( \':eq(0)\' 以上是关于tornado web高级开发项目的主要内容,如果未能解决你的问题,请参考以下文章
面面观 | 使用python tornado web进行开发 |