tornado项目注意点

大致框架思想

若是你作的项目是偏向中小型的话,MTV或者MVC已经足够支撑起整个项目,而若是你作的项目比较大大话,或者说可能之后的业务量很大的话,那你就须要用到四层架构的思想了,那么咱们就各自分析下俩框架的结构。html

一、MVC前端

 MVC是众所周知的模式,即:将应用程序分解成三个组成部分:model(模型),view(视图),和 controller(控制 器)。其中:
             M 管理应用程序的状态(一般存储到数据库中),并约束改变状态的行为(或者叫作“业务规则”)。
             C 接受外部用户的操做,根据操做访问模型获取数据,并调用“视图”显示这些数据。控制器是将“模型”和“视图”隔离,并成为两者之间的联系纽带。
             V 负责把数据格式化后呈现给用户。python

二、四层框架web

咱们一般所说的四层框架,其实是DAO层、Service层、Controller层、View层这四层的相互组合造成。ajax

DAO层:DAO层主要是作数据持久层的工做,负责与数据库进行联络的一些任务都封装在此,DAO层的设计首先是设计DAO的接口数据库

Service层:Service层主要负责业务模块的逻辑应用设计。一样是首先设计接口,再设计其实现的类服务器

Controller层:Controller层负责具体的业务模块流程的控制,在此层里面要调用Serice层的接口来控制业务流程cookie

View层 : 此层与控制层结合比较紧密,须要两者结合起来协同工发。View层主要负责前台jsp页面的表示session

UI--->Service---->Model------>Repository架构

 

验证码

验证码原理在于后台自动建立一张带有随机内容的图片,而后将内容经过img标签输出到页面

安装图像处理模块:

pip3 install pillow   
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import tornado.ioloop
import tornado.web
import io
import check_code
li = []
class CheckCodeHandler(tornado.web.RequestHandler):
    def get(self):
        mstream = io.BytesIO()
        img, code = check_code.create_validate_code()
        li.append(code)   #这里能够保存到session中
        img.save(mstream, "GIF")
        self.write(mstream.getvalue())
        print(code)

class LoginHandler(tornado.web.RequestHandler):
    def get(self):
        self.render('login.html',status="")
    def post(self, *args, **kwargs):
        user = self.get_argument("user",None)
        pwd = self.get_argument("pwd",None)
        mima = self.get_argument("mima",None)
        if user == "alex" and pwd == "123" and mima.upper() == li[0].upper():  #不区分大小写
            self.write("登陆成功")
        else:
            # self.redirect("/login")
            self.render("login.html",status = "验证码错误")

settings = {
    'template_path': 'tpl',
    'static_path': 'static',
    'static_url_prefix': '/static/',
    'cookie_secret': 'aiuasdhflashjdfoiuashdfiuh',
}

application = tornado.web.Application([
    (r"/login", LoginHandler),
    (r"/check_code", CheckCodeHandler),
], **settings)


if __name__ == "__main__":
    application.listen(8888)
    tornado.ioloop.IOLoop.instance().start()
start.py
#!/usr/bin/env python
#coding:utf-8
import random
from PIL import Image, ImageDraw, ImageFont, ImageFilter

_letter_cases = "abcdefghjkmnpqrstuvwxy"  # 小写字母,去除可能干扰的i,l,o,z
_upper_cases = _letter_cases.upper()  # 大写字母
_numbers = ''.join(map(str, range(3, 10)))  # 数字
init_chars = ''.join((_letter_cases, _upper_cases, _numbers))

def create_validate_code(size=(120, 30),
                         chars=init_chars,
                         img_type="GIF",
                         mode="RGB",
                         bg_color=(255, 255, 255),
                         fg_color=(0, 0, 255),
                         font_size=18,
                         font_type="Monaco.ttf",
                         length=4,
                         draw_lines=True,
                         n_line=(1, 2),
                         draw_points=True,
                         point_chance = 2):
    '''
    @todo: 生成验证码图片
    @param size: 图片的大小,格式(宽,高),默认为(120, 30)
    @param chars: 容许的字符集合,格式字符串
    @param img_type: 图片保存的格式,默认为GIF,可选的为GIF,JPEG,TIFF,PNG
    @param mode: 图片模式,默认为RGB
    @param bg_color: 背景颜色,默认为白色
    @param fg_color: 前景色,验证码字符颜色,默认为蓝色#0000FF
    @param font_size: 验证码字体大小
    @param font_type: 验证码字体,默认为 ae_AlArabiya.ttf
    @param length: 验证码字符个数
    @param draw_lines: 是否划干扰线
    @param n_lines: 干扰线的条数范围,格式元组,默认为(1, 2),只有draw_lines为True时有效
    @param draw_points: 是否画干扰点
    @param point_chance: 干扰点出现的几率,大小范围[0, 100]
    @return: [0]: PIL Image实例
    @return: [1]: 验证码图片中的字符串
    '''

    width, height = size # 宽, 高
    img = Image.new(mode, size, bg_color) # 建立图形
    draw = ImageDraw.Draw(img) # 建立画笔

    def get_chars():
        '''生成给定长度的字符串,返回列表格式'''
        return random.sample(chars, length)

    def create_lines():
        '''绘制干扰线'''
        line_num = random.randint(*n_line) # 干扰线条数

        for i in range(line_num):
            # 起始点
            begin = (random.randint(0, size[0]), random.randint(0, size[1]))
            #结束点
            end = (random.randint(0, size[0]), random.randint(0, size[1]))
            draw.line([begin, end], fill=(0, 0, 0))

    def create_points():
        '''绘制干扰点'''
        chance = min(100, max(0, int(point_chance))) # 大小限制在[0, 100]

        for w in range(width):
            for h in range(height):
                tmp = random.randint(0, 100)
                if tmp > 100 - chance:
                    draw.point((w, h), fill=(0, 0, 0))

    def create_strs():
        '''绘制验证码字符'''
        c_chars = get_chars()
        strs = ' %s ' % ' '.join(c_chars) # 每一个字符先后以空格隔开

        font = ImageFont.truetype(font_type, font_size)
        font_width, font_height = font.getsize(strs)

        draw.text(((width - font_width) / 3, (height - font_height) / 3),
                    strs, font=font, fill=fg_color)

        return ''.join(c_chars)

    if draw_lines:
        create_lines()
    if draw_points:
        create_points()
    strs = create_strs()

    # 图形扭曲参数
    params = [1 - float(random.randint(1, 2)) / 100,
              0,
              0,
              0,
              1 - float(random.randint(1, 10)) / 100,
              float(random.randint(1, 2)) / 500,
              0.001,
              float(random.randint(1, 2)) / 500
              ]
    img = img.transform(size, Image.PERSPECTIVE, params) # 建立扭曲

    img = img.filter(ImageFilter.EDGE_ENHANCE_MORE) # 滤镜,边界增强(阈值更大)

    return img, strs
check_code.py
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="/login" method="post">
    <p><input name="user" placeholder="用户名" type="text"></p>
    <p><input name="pwd" placeholder="密码" type="text"></p>
    <p>
      <input name="mima" placeholder="验证码" type="text" >
        <img src="/check_code" onclick='ChangeCode();' id='imgCode'>
    </p>
    <input type="submit" value="提交"><span style="color: red">{{status}}</span>
</form>
<script>
    function ChangeCode() {
        var code = document.getElementById('imgCode');
        code.src += '?';
    }
</script>
</body>
</html>
html

Session全套

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from hashlib import sha1
import os
import time

create_session_id = lambda: sha1(bytes('%s%s' % (os.urandom(16), time.time()), encoding='utf-8')).hexdigest()


class SessionFactory:

    @staticmethod
    def get_session_obj(handler):
        obj = CacheSession(handler)
        return obj

class CacheSession:
    session_container = {}
    session_id = "__sessionId__"

    def __init__(self, handler):
        self.handler = handler
        client_random_str = handler.get_cookie(CacheSession.session_id, None)
        if client_random_str and client_random_str in CacheSession.session_container:
            self.random_str = client_random_str
        else:
            self.random_str = create_session_id()
            CacheSession.session_container[self.random_str] = {}

        expires_time = time.time() + 60 * 20
        handler.set_cookie(CacheSession.session_id, self.random_str, expires=expires_time)

    def __getitem__(self, key):
        ret = CacheSession.session_container[self.random_str].get(key, None)
        return ret

    def __setitem__(self, key, value):
        CacheSession.session_container[self.random_str][key] = value

    def __delitem__(self, key):
        if key in CacheSession.session_container[self.random_str]:
            del CacheSession.session_container[self.random_str][key]
Session.py
全部类的继承BaseRequestHandler,继承后就能够用Session

class BaseRequestHandler(tornado.web.RequestHandler):
    def initialize(self):
        self.session = SessionFactory.get_session_obj(self)

经过self.session['xxx'] = xxx能够储存值

经过self.session['xxx']能够取值

Form验证

一、验证规则文件

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

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)
fields.py

二、验证文件(继承fields)

#!/usr/bin/env python
# -*- coding:utf-8 -*-
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:
                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
forms

三、自定义类

注意:self.xxx = yyy(),其中xxx为须要验证的字段,即你再input中定义的name属性的值,右边的为验证的规则,自定义类必须继承验证文件的类

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from backend.form.forms import BaseForm
from backend.form.fields import StringField
from backend.form.fields import IntegerField

class LoginForm(BaseForm):

    def __init__(self):
        self.user = StringField()
        self.password = StringField()
        self.code = StringField()
        super(LoginForm, self).__init__()

form =  LoginForm(自定义类)() 获得一个对象

经过 form.valid(self)能够验证用户提交的内容是否经过验证--------必须把self传进去为了获取值

经过form._value_dict能够获取用户提交的全部内容

经过form._error_dict能够获取错误信息,用于在前端展现

发送数据的几种方式

在一个页面上也许会有增长,修改,和删除等功能,这里可能须要咱们须要到一个模板,并提交数据,因为增长和修改的时候,咱们所须要的数据大体相同,因此咱们能够利用一个模板进行提交数据,并且提交数据的时候咱们也能够用同一个ajax进行提交

ajax提交数据经常使用的几种方式:

  一、Get是向服务器发索取数据的一种请求

  二、Post是向服务器提交数据的一种请求

  三、Put是向服务器提交修改数据的一种请求

  四、Delete是向服务器提交删除数据的一种请求

咱们能够提早申明一个变量 var METHOD

当用户点击添加的时候咱们把变量赋值为METHOD = 'post';

当用户点击修改的时候咱们把变量赋值为METHOD = 'put';

当用户点击删除的时候咱们把变量赋值为METHOD = 'delete';

这样咱们就不用重复的写ajax,提升了代码的重用性

        ret = JSON.stringify(ret)
        $.ajax({
            type:METHOD,
            url: '/commodity',
            data: {'ret':ret},
            success:function (arg) {
                location.reload()
            }
        });

ret = JSON.stringify(ret)在JavaScript中用于将字典转换成字符串的格式

ret =JSON.parse(ret)在JavaScript中用于将字符串转换成字典的格式

相关文章
相关标签/搜索