python -- Tornado(详解)、sqlalchemy(详解)

安装依赖

pip install tornado==4.5 -i https://pypi.doubanio.com/simple

配跨域

class BaseHandler(tornado.web.RequestHandler):

    # 配置请求头,允许跨域,否者在浏览器调用的时候报错误,同时还得加上允许Authorization字段过来
    def set_default_headers(self):
        self.set_header("Access-Control-Allow-Origin", "*")
        self.set_header("Access-Control-Allow-Headers", "Content-Type,Authorization,x-requested-with")
        self.set_header("Access-Control-Allow-Methods", "POST,GET,OPTIONS,PUT,DELETE")

    # 这个函数是必要的,有些浏览器或者测试工具在访问之前都会预先访问,你不写的话会导致出错的
    # 例如vue一般需要访问options方法
    def options(self):
        self.finish()

[第一个Tornado]输出一份 Hello Word(这是信仰)

from tornado.web import Application
from tornado.ioloop import IOLoop  # 循环模型对象(事件循环)
from tornado.web import RequestHandler  # 和django中的request一样(请求对象)  里面封装了常用的请求方法GET POST PUT DELETE


class IndexHandler(RequestHandler):
    def get(self):    # 从写get方法
        self.write(
            '<h1>Hello Word</h1>'
        )


if __name__ == '__main__':
    app = Application([            # 注册路由(里面是一个列表,列表中是一个元祖('路由', Tornado程序))
        ('/', IndexHandler)
    ])
    app.listen(port=8001)   # 绑定端口
    print('http://127.0.0.1:8001')
    IOLoop.current().start()   # 获取事件循环对象,启动这个服务

	# 现在请求127.0.0.1:8001 会出现hello word










# 优化写法(优化路由写法)

from tornado.web import Application
from tornado.ioloop import IOLoop  # 循环模型对象(事件循环)
from tornado.web import RequestHandler  # 和django中的request一样(请求对象)  里面封装了常用的请求方法GET POST PUT DELETE


class IndexHandler(RequestHandler):
    def get(self, *args, **kwargs):
        self.write('测试')


def make_app():         # 优化写法
    return Application([
        ('/', IndexHandler),    # 绑定路由信息
    ])


if __name__ == '__main__':
    app = make_app()
    app.listen(port=8001)
    print('Starting Web Server: http://127.0.0.1:8001')
    IOLoop.current().start()









#通过命令行参数启动
from tornado.web import Application
from tornado.ioloop import IOLoop  # 循环模型对象(事件循环)
from tornado.web import RequestHandler  # 和django中的request一样(请求对象)  里面封装了常用的请求方法GET POST PUT DELETE
import tornado.options


class IndexHandler(RequestHandler):
    def get(self, *args, **kwargs):
        self.write('测试')


def make_app():
    return Application([
        ('/', IndexHandler),  # 绑定路由信息
    ], default_host=tornado.options.options.host)


if __name__ == '__main__':
    tornado.options.define('port',
                           default=8001,        # 定义命令行参数
                           type=int,
                           help='bind socket port')
    tornado.options.define('host',
                           default='127.0.0.1:8001',
                           type=str,
                           help='设置host name')

    tornado.options.parse_command_line()   # 解析命令行参数

    app = make_app()
    app.listen(tornado.options.options.port)
    print(f'Starting Web Server: http://{tornado.options.options.host}:{tornado.options.options.port}')
    IOLoop.current().start()

获取请求参数

class IndexHandler(RequestHandler):
    def get(self, *args, **kwargs):
        # 1.读取单个参数
        wd = self.get_argument('wd')  # 读取单个参数

        # 2.读取多个(同名)参数,返回列表
        title = self.get_arguments('title')  # 获取多个title参数(参数名相同的时候) --> 返回一个列表
        # print(title)                           # /?wd=查询参数&title=12135131&title=588


        # 3. 同上一样的效果
        wd2 = self.get_query_argument('wd')   # 获取单个
        wd3 = self.get_query_arguments('title') # 获取多个同名参数
    

总结:
	self.get_argument() / get_arguments()  可以获取任何请求方式的请求参数
		带's'的是获取所有同名参数
		
	self.get_query_argument() / get_query_argments()  获得get请求的查询参数
		返回一个列表,获取get请求方式的keyword对应的一组值,如果不存在,则为空列表
		获取get请求方式的keyword对应的值,如果不存在,则为空字符串
		
	self.get_body_argument() / self.get_body_arguments()  获取post表单参数
	
	
	self.request.arguments.get()
		根据key去查找参数,如果不存在返回None(post  get,参数都在里面)
		常用于判断参数是否存在


	获取post /put/   json参数
	 name = self.request.body.decode()
     names = json.loads(name)


	获取headers参数
	s = self.request.headers
    print(s.get('Host'))  # 示例:获取host

返回响应

self.write(html)         	      # 返回响应数据
self.set_status(status_code)      # 状态码
self.set_cookie(name, value)     
self.redirect('/')   		      # 重定向
self.set_header(name, value)      # 设置请求头


-----------------------------------------------------------------------------

class SearchHandler(RequestHandler):

    def get(self):
        self.write(json.dumps({'code': 500}))       # 返回json对象
        self.set_header('Content-Type', 'application/json;charset=utf-8')   # 更改数据类型
        self.set_status(201)               # 设置状态码
        self.set_cookie('key', 'value')    # 设置cookie 



def make_app():
    return Application([
        ('/', IndexHandler), 
        ('/search/', SearchHandler),   # 注意前方需要/ 
    ])

获取其他的参数

self.request.method   # 请求方法
self.request.path     # 请求路径
self.request.host     # ip
... self对象中很多

获取路径参数

class OrderHandler(RequestHandler):
    def get(self, order):     # 必须多一个参数
        self.write(json.dumps({'code': int(order)}))


def make_app():
    return Application([
        ('/', IndexHandler),  # 绑定路由信息
        ('/search/', SearchHandler),
        (r'/order/(\d+)/', OrderHandler),     # 正则匹配
    ])

图片上传与查看

class OrderHandler(RequestHandler):
    def post(self, *args, **kwargs):
        file = self.request.files.get('image')
        filename = str(file[0].get('filename'))
        image_body = file[0]
        size = int(self.request.headers.get('Content-Length'))
        print('图片大小:kb', size / 1000)  # 获取图片大小

        image_type = ''.join(filename.split('.')[1])  # 后缀
        image_name = ''.join(filename.split('.')[0])  # 文件名
        
        with open('ceshi.' + image_type, 'wb') as f:
            f.write(dict(image_body).get('body'))

    def get(self):
        with open('ceshi.jpg', 'rb') as f:
            self.write(f.read())
            self.set_header('Content-Type', 'image/jpeg')

def make_app():
    return Application([
        ('/order/', OrderHandler),
    ])

文件下载

class OrderHandler(RequestHandler):
	def get(self):
        buf_size = 4096
        filename = 'ceshi.jpg' # self.get_argument('filename', None)
        if not filename:
            self.write({"error": "文件名称为空"})
            return
        # 设置传输的文件类型,有很多例如png/pdf等等 取决于不同场景,这边我用octet-stream
        self.set_header('Content-Type', 'application/octet-stream')
        path = './' + filename
        with open(path, 'rb') as f:
            while True:
                data = f.read(buf_size)
                if not data:
                    break
                self.write(data)
        filename = parse.quote(filename)
        self.set_header('Content-Disposition', 'attachment; filename=' + filename)
        self.finish()

中间件AOP【切入点】

from tornado.web import Application
from tornado.ioloop import IOLoop  # 循环模型对象(事件循环)
from tornado.web import RequestHandler  # 和django中的request一样(请求对象)  里面封装了常用的请求方法GET POST PUT DELETE


class IndexHandler(RequestHandler):
    def get(self, *args, **kwargs):
        self.write({'get': 'get'})

    def post(self, *args, **kwargs):
        self.write({'post': 'post'})




    def initialize(self):
        # 所有的请求方法,都会进行初始化操作
        print('-----initialize------')



    def prepare(self):  # 【建议】(验证参数,权限,读缓存)
        # 预处理(初始化之后,调用行为方法之前   注:先初始化(initialize),后预处理(prepare), GET/POST    常用于缓存,权限验证等)
        print('-----prepare-----')



    def on_finish(self):  # 【主要用于文件关闭  数据库关闭】
    # 所有方法执行完后执行的方法(请求处理完成后,释放资源的方法,在行为方法完后调用)
    print('------on_finish-------')




def make_app():
    return Application([
        ('/', IndexHandler),
    ])


if __name__ == '__main__':
    app = make_app()
    app.listen(port=8001)
    print(f'Starting Web Server: http://127.0.0.1:8001')
    IOLoop.current().start()

API接口设计

用户的 crud操作接口

import uuid as uuid
from tornado.web import Application
from tornado.ioloop import IOLoop
from tornado.web import RequestHandler
from tornado.options import options, define, parse_command_line


class LoginHandler(RequestHandler):
    '''登陆'''

    users = [       # 模拟数据库
        {'id': 1,
         'name': 'disen',
         'pwd': '123456',
         'last_login_device': 'Android 5.1 OnePlus5'}
    ]

    def get(self, *args, **kwargs):
        pass

    def post(self, *args, **kwargs):
        content_type = self.request.headers.get('Content-Type')
        if content_type == 'application/json':
            json_str = json.loads(self.request.body)
            if json_str.get('name') == self.users[0].get('name') and json_str.get('pwd') == self.users[0].get('pwd'):
                uid = uuid.uuid4().hex
                response = {'code': 'OK', 'mes': '登陆成功', 'token': uid}
            else:
                response = {'code': 'NO', 'mes': '账号或密码错误'}
        else:
            response = {'code': 'NO', 'mes': '请求头须为json'}
        self.write(response)
        self.set_header('Content-Type', 'application/json')

    def put(self, *args, **kwargs):
        pass

    def delete(self, *args, **kwargs):
        pass


def make_app():
    return Application(
        handlers=[
            ('/login/', LoginHandler),
        ],
        default_host=options.h)


if __name__ == '__main__':
    define('p', default=8001, type=int, help='绑定的port端口')
    define('h', default='localhost', type=str, help='绑定的ip')

    parse_command_line()  # 解析命令行参数
    app = make_app()
    app.listen(options.p)
    print(f'Starting Web Server: http://127.0.0.1:8001')
    IOLoop.current().start()

解决跨域

import tornado.web


class BaseHandler(tornado.web.RequestHandler):

    def __init__(self,*args,**kwargs):
        super().__init__(*args,**kwargs)
        self.host = ""
        self.port = ""

        # 在初始化方法中添加设置跨域的方法
        self.set_default_headers()


    # 处理OPTIONS域检请求
    def post(self):
        self.set_status(204)
        self.finish()

    # 设置跨域的具体方法
    def set_default_headers(self):
        super().set_default_headers()
        # 设置允许的请求头
        self.set_header("Access-Control-Allow-Methods","GET,POST,PUT,DELETE,OPTIONS")
        self.set_header("X-XSS-Protecion","1")
        self.set_header("Content-Security-Policy","default-src 'self'")
        self.set_header("Access-Control-Allow-Credentials","true")
        # 设置一些自己定义的请求头
        self.set_header("Access-Control-Allow-Headers",
                        "Content-Type,Access-Control-Allow-Headers,X-Auth-Token,Y-Auth-Token"
            )
        self.set_header("Content-Type","application/json; charset=UTF-8")
        # 设置允许本地调试的域名通过!
        self.set_header("Access-Control-Allow-Origin",self.request.headers.get("Origin","http://localhost:9090"))
        # 如果后面的域名设置为 * ,表示允许所有的域名通过
        # self.set_header("Access-Control-Allow-Origin","*")
        # self.set_header("Access-Control-Allow-Origin",self.request.headers.get("Origin","*"))








# 如果前端发起请求需要加上  示例: mode:'cors'
let options = {
	method: 'post',
	body: JSON.stringify({
		'name':'disen',
		'pwd':'123456'
		})
	headers: {
	'Content-Type': 'application/json',
	},
	mode: 'cors'
	};

fetch('http://......./login/, options)
	.then(response=>response.json())
	.then(data=>{$('result').innerHTML = data.msg;
	})
}		

注:项目结构设计(不能一个脚本写到最后,不善于维护)

结构大致如下:

file
	---> app
		---> __init__.py    # 在app的init中,创建tronado.web.Application类对象,并且设置初始化的参数
		
		---> views
			---> __init__.py
			
		---> models
			----> __init__.py
			
			
	---> static
	---> templates
	---> utils
	---> manage.py

SQLAlchemy–>ORM使用

Tronado中没提供orm框架,可以使用SQLAlchemy框架

参考文章

https://www.cnblogs.com/lsdb/p/9835894.html

配置sqlalchemy

pip install sqlalchemy -i https://mirrors.aliyun.com      # 装依赖


注: mac/linux配置pip安装源,在~/.pip/pip.conf, 配置内容
[global]
index-url = 'https://mirrors.aliyun.com/pypi/simple

[install]
trusted-host = mirrors.aliyun.com

如果在windows系统,在用户目录的.pip子目录,配置pip.ini,内容如上

序列化查询对象

method1

1.
for r in session.query(User).all():
    row2dict = lambda r: {c.name: str(getattr(r, c.name)) for c in r.__table__.columns}
    print(row2dict(r))
  








2.
def row2dict(row):
    d = {}
    for column in row.__table__.columns:
        d[column.name] = str(getattr(row, column.name))

    return d

for r in session.query(User).all():
    print(row2dict(r))

表转orm模型

pip install sqlacodegen    # 实际是一个exe程序,需要找到他才能进行表转模型且在当前虚拟环境


转全部表
sqlacodegen --outfile=main.py postgresql+psycopg2://dbuser:zhimakaimen@192.168.1.50:5432/game

sqlacodegen --outfile=导出的文件名 数据库类型+连接数据库的引擎://账号:密码@IP:端口/数据库名


转指定表
sqlacodegen --outfile=main.py postgresql+psycopg2://dbuser:zhimakaimen@192.168.1.50:5432/game --tables user
参数同上... --tables 表名

1.0(配置)

from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base

# 创建引擎
engine = create_engine('mysql+mysqldb://账号:密码@ip:端口/数据库?charset=utf8')
# mysqlclient引擎

# engine = create_engine('mysql+pymysql://账号:密码@ip:端口/数据库?charset=utf8')
# pymysql引擎

# engine = create_engine('sqlite:///db.db', echo=False, connect_args={'check_same_thread': False})
# sqlite引擎

# 生成数据库连接的类
DbSession = sessionmaker(bind=engine)

# 创建会话类
session = DbSession()

# 使用线程隔离的session
# engine = create_engine('sqlite:///db.db', echo=False, connect_args={'check_same_thread': False})
# DbSession = sessionmaker(bind=engine)
# session = scoped_session(DbSession)
# Base = declarative_base(bind=engine)
# 生成所有模型类的父类
# Base = declarative_base(bind=engine)

2.0 orm类

from sqlalchemy import Column, Integer, String, Text, ForeignKey, Float
from util.conn import Base


class Article(Base):
    __tablename__ = 'article1'  # 必须声明数据表的名

    id = Column(Integer, primary_key=True, autoincrement=True)
    title = Column(String(50), nullable=False)
    price = Column(Float, nullable=False)

    def __str__(self):
        return "Article(title:{},price:{})".format(self.title, self.price)


# Base.metadata.create_all()  # 创建所有表

# Base.metadata.drop_all()  # 删除所有表

crud操作

# 增加数据  --> 查第一个数据
# article = Article(title='add', price=13)
# session.add(article)
# session.commit()  # 提交事务

# 批量插入 
1.  objects = [
	    User(name="u1"),
	    User(name="u2"),
	    User(name="u3")]
	session.bulk_save_objects(objects)	

2.	objects = [User(name="u1"), User(name="u2"), User(name="u3")]
	session.add_all(objects)
	session.commit()


# 修改
# user = session.query(Article).first()  # 修改第一条数据
# user.title = '第一个标题'
# session.commit()


res = session.query(Article).filter(Article.id==1).first()  # 修改指定数据
res.price = 100
session.commit()	

# 批量修改
session.query(Note).filter(Note.id==1).update({Note.title:"title-edit",
    Note.body:"body-edit"})

session.commit()




#  查全部
# article = session.query(Article).all()
# data = [{'id': i.id, 'title': i.title, 'price': i.price} for i in article]
# print(data)

# 根据主键查
res = session.query(Article).get(2)
	
# 只查某一个字段(优化性能)
# article = session.query(Article, 'title').all()
# for i in article:
#     print(i.title)






# 删除
res = session.query(Article).filter(Article.id==1)
res.delete()

session.commit()





# 聚合函数(统计数量)
# res = session.query(func.count(Article.id)).first()
# print(res)


# 过滤后的数量
# res = session.query(Article).filter(Article.title=='add').count()

# 分页查询(limit, offset, slice)
res = session.query(Arctcle).limit(10).all()      -- > 只查10条数据
res = session.query(Arctcle).limit(10).offset(20).all() --> 只查10 - 20条数据
res = session.query(Arctcle).slice(10, 20).all()  --> 切片查询


# 某个字段的平均值
# res = session.query(func.avg(Article.price)).first()

# 最小值
# res = session.query(func.min(Article.price)).first()

# 最大值
# res = session.query(func.max(Article.price)).first()

# 求和
# res = session.query(func.sum(Article.price)).first()

#日期查询
from datetime import datetime
from sqlalchemy import extract
res = session.query(cls).filter(
               extract('year', cls.create_time) == datetime.today().year,
                extract('month', cls.create_time) == datetime.today().month,
                extract('day', cls.create_time) == datetime.today().day)\
                .filter(cls.user == user_id).filter(cls.match_id == match_id)\
                .filter(cls.is_free == 1).first()

#过滤
# eq
# result = session.query(Article).filter(Article.title =='title0').all()
# not eq mysql <>
# result = session.query(Article).filter(Article.title !='title0').all()

# like 模糊查询
# title 包含 title
# result = session.query(Article).filter(Article.title.like('%title%')).all()

# in 在..里面 Pyhont关键字 _ 私有的(下划线加前面)
# in[1,4] 查询的是id 为1,4  不是范围
# result = session.query(Article).filter(Article.title.in_(['title0','title4'])).all()

# not in 取反
# result = session.query(Article).filter(~Article.title.in_(['title0','title4'])).all()
# result = session.query(Article).filter(Article.title.notin_(['title0','title4'])).all()

# Null(未开辟空间),空(已开辟空间)
# result = session.query(Article).filter(Article.title == None).all()
# result = session.query(Article).filter(Article.title.is_(None)).all()
# result = session.query(Article).filter(Article.title.isnot(None)).all()
# result = session.query(Article).filter(Article.title !=None).all()

# and 和,且 推荐->第一种简单
# result = session.query(Article).filter(Article.title == 'title0', Article.price == 23).all()
# result = session.query(Article).filter(and_(Article.title == 'title0', Article.price == 23)).all()
# result = session.query(Article).filter(Article.title == 'title0').filter(Article.price == 23).all()

# or 或 只满足一个条件就可以
result = session.query(Article).filter(or_(Article.title == 'title0', Article.price == 17, Article.title == 'title2')).all()



# 数据去重  
from sqlalchemy import distinct
session.query(distinct(BudgetOrganizational.center_name)).all()
		或
session.query(BudgetOrganizational.center_name).group_by(BudgetOrganizational.center_name).all()



# 日期查询的三种方式
方法一注意时间格式:xxxx-xx-xx
方法二没有‘day’
方法三的时间格式同方法一

1、result = Jobs.query.filter(Jobs.create_time < '2017-07-10').all()
2、result = Jobs.query.filter(and_(
    extract('year', Jobs.create_time) == 2017,
    extract('month', Jobs.create_time) == 7
                                )).all()
3、result = Jobs.query.filter(Jobs.create_time.between('1990-01-01', '2018-01-01'))


#排序(逆序)
res = session.query(Article).order_by(Article.id.desc()).all()

外键排序
class User_VipTick(Base):
    '''用户背包'''
    from sqlalchemy.orm import backref
    __tablename__ = 'user_viptick'

    id = Column(Integer, primary_key=True, autoincrement=True)
    user = Column(Integer, ForeignKey('user.id'))
    vipticket = Column(Integer, ForeignKey('vipticket.id'))
    create_time = Column(DateTime, default=datetime.now)
    # 加他
    dp = relationship("User", backref=backref('user', order_by=create_time.desc())) 

属性详解

Column常用参数:

	default:默认值。
	nullable:是否可空。
	primary_key:是否为主键。
	unique:是否唯一。
	autoincrement:是否自动增加。
	onupdate:更新的时候执行的函数。
	name:该属性在数据库中的字段映射



sqlalchemy常用的数据类型:
	
	Integer:整形。
	Float:浮点类型。
	Boolean:传递True/False进去。
	DECIMAL:定点类型。
	enum:枚举类型。
	Date:传递datetime.date()进去。
	DateTime:传递datetime.datetime()进去。
	Time:传递
	datetime.time()进去。
	String:字符类型,使用时需要指定长度,区别于Text类型。
	Text:文本类型。
	LONGTEXT:长文本类型。

外键查询

from sqlalchemy import Column, Integer, String, Text, ForeignKey, Float, func
from sqlalchemy.orm import relationship

from util.conn import Base, session


class Student(Base):
    __tablename__ = 'student'
    student_id = Column(Integer, primary_key=True, autoincrement=True)
    name = Column(String(255))
    age = Column(String(255), default='0')
    sex = Column(String(255), default='男')


class Score(Base):
    __tablename__ = 'score'
    score_id = Column(Integer, primary_key=True, autoincrement=True)
    score = Column(String(255), default='0')
    student_id = Column(ForeignKey('student.student_id'))
    dp = relationship("Student", backref='student')  # backref 绑定双向关系 理解为: 一查多的时候   对象.student


# -->join查询
res3 = session.query(Score.score, Score.student_id).join(Student, Score.student_id == Student.student_id).all()
for i in res3:
    print(i)

# -->正向查询
res0 = session.query(Score).filter(Score.score == 100).all()
print([{'name': i.dp.name} for i in res0])

# -->逆向查询
res = session.query(Student).filter_by(name='李白').first()
for i in res.student:
    print(i.score)

简单的实例

import json

from sqlalchemy import Column, Integer, String, Text, ForeignKey, Float, func
from sqlalchemy.orm import relationship
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base

# 创建引擎
engine = create_engine('mysql+mysqldb://root:Admin123.@IP:3306/study?charset=utf8')
# engine = create_engine('mysql+pymysql://root:Admin123.@IP:3306/polls?charset=utf8')


# 生成数据库连接的类
DbSession = sessionmaker(bind=engine)

# 创建会话类
session = DbSession()

# 生成所有模型类的父类
Base = declarative_base(bind=engine)


class Student(Base):
    __tablename__ = 'student'
    student_id = Column(Integer, primary_key=True, autoincrement=True)
    name = Column(String(255))
    age = Column(String(255), default='0')
    sex = Column(String(255), default='男')


class Score(Base):
    __tablename__ = 'score'
    score_id = Column(Integer, primary_key=True, autoincrement=True)
    score = Column(String(255), default='0')
    student_id = Column(ForeignKey('student.student_id'))
    dp = relationship("Student", backref='student')  # backref 绑定双向关系 理解为: 一查多的时候   对象.student


from tornado.web import Application
from tornado.ioloop import IOLoop
from tornado.web import RequestHandler
from tornado.options import options, define, parse_command_line


class Login(RequestHandler):
    '''测试跨域'''

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.set_default_headers()

    def options(self):
        # 处理OPTIONS域检请求
        self.set_status(204)
        self.finish()

    def set_default_headers(self):
        super().set_default_headers()
        self.set_header("Access-Control-Allow-Methods", "GET,POST,PUT,DELETE,OPTIONS")
        self.set_header("X-XSS-Protecion", "1")
        self.set_header("Content-Security-Policy", "default-src 'self'")
        self.set_header("Access-Control-Allow-Credentials", "true")
        self.set_header("Access-Control-Allow-Headers",
                        "Content-Type,Access-Control-Allow-Headers,X-Auth-Token,token",
                        )
        self.set_header("Content-Type", "application/json; charset=UTF-8")
        self.set_header("Access-Control-Allow-Origin", "*")

    def get(self):
        user = session.query(Student).all()
        user = [{'user_id': i.student_id, 'name': i.name, 'age': i.age} for i in user]
        self.write({'code': 200, 'mes': '查询成功', 'results': user})
        self.set_status(200)

    def post(self, *args, **kwargs):
        token = self.request.headers
        username = self.request.body
        username = json.loads(username).get('username')
        res = session.query(Student).filter_by(name=username).first()
        if res:
            response = {'code': 200, 'mes': '登陆成功'}
        else:
            response = {'code': 500, 'mes': '账号或者密码错误'}
        self.write(response)
        self.set_header('ContType', 'application/json;charset=utf-8')
        self.set_status(200)


app = Application([  # 注册路由(里面是一个列表,列表中是一个元祖('路由', Tornado程序))
    ('/', Login)
])
app.listen(port=8001)  # 绑定端口
print('http://127.0.0.1:8001')
IOLoop.current().start()  # 获取事件循环对象,启动这个服务
  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

像风一样的男人@

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值