大体框架思想

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

1、MVC

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

2、四层框架

我们通常所说的四层框架,实际上是DAO层、Service层、Controller层、View层这四层的相互组合形成。

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

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

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

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

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验证

1、验证规则文件

#!/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

2、验证文件(继承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

3、自定义类

注意: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提交数据常用的几种方式:

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

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

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

  4、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中用于将字符串转换成字典的格式

 

posted on 2017-06-23 17:01  23云恋49枫  阅读(975)  评论(0编辑  收藏  举报