9-tornado-Template优化方法、个人信息案例、tornado中ORM的使用(peewee的使用、peewee_async)、WTForms的使用
在很多情况下,前端模板中在很多页面有都重复的内容可以使用,比如页头、页尾、甚至中间的内容都有可能重复。这时,为了提高开发效率,我们就可以考虑在共同的部分提取出来,
主要方法有如下:
1. 模板继承
2. UI模板
1 模板继承
common/base.html
{% block content %}
{% end %}
shop2.html
{% extends 'common/base.html'%}{% block content %}
{% end %}
2 UI模板
Tornado中支持累死Vue中的组件功能,就是也公共的内容提取出来当成组件。
具体的使用方式是用tornado.web.UIModule
class Entry(tornado.web.UIModule):def render(self, entry, show_comments=False):return self.render_string("module-entry.html", entry=entry, show_comments=show_comments)settings = {"Entry": Entry,
}
3 个人信息案例
环境搭建
在网站中,少了数据CRUD的操作,但在tornado中,我们知道若想操作的话尽量使用异步的操作,这样效率才会高。
那应该如何编写呢,下面我们来一起做下吧。首先我们先一起搭建下环境。
具体的操作如下:
前端
copy 原生素材
html —> templates
css —> static/css
js —> static/js
img —> static/img
到项目中
后端
from tornado import web, ioloop
from tornado.web import StaticFileHandlerclass IndexHandler(web.RequestHandler):def get(self):self.render('personal.html')import os
base_url = os.path.dirname(os.path.abspath(__file__))
settings={'static_path':os.path.join(base_url,'static'),'static_url_prefix':'/static/','template_path':os.path.join(base_url,'templates')
}
if __name__ == "__main__":app = web.Application([web.URLSpec('/',IndexHandler,name='index'),],debug=True,**settings)app.listen(8000)ioloop.IOLoop.current().start()
MySQL
CREATE TABLE `tornado_demo1`.`t_user` (`id` int(10) NOT NULL,`username` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,`nick_name` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,`email` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,`passsword` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,`phone` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,`language` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
熟悉Mysql操作
之前我们了解过pymysql操作数据库,但那是同步的。
我们需要使用一个异步的框架,在这,我们推荐使用aiomysql,它的底层大量的使用了pymysql,只是它通过asyncio实现的访问数据库
安装方式
pip install aiomysql
使用方式
import asyncio
import aiomysqlasync def test_example(loop):pool = await aiomysql.create_pool(host='127.0.0.1', port=3306,user='root', password='root',db='mysql', loop=loop)async with pool.acquire() as conn:async with conn.cursor() as cur:await cur.execute("SELECT 42;")print(cur.description)(r,) = await cur.fetchone()assert r == 42pool.close()await pool.wait_closed()loop = asyncio.get_event_loop()
loop.run_until_complete(test_example(loop))
4 tornado中ORM的使用
4.1 peewee的使用
官网链接
Peewee是一个简单而小型的ORM。使其易于学习且使用直观。
- 一个小的,表达力很强的ORM
- python 2.7+和3.4+(使用3.11开发)
- 支持sqlite,mysql,postgresql和cockroachdb
- 大量的扩展
安装
pip install peewee
tip 需要安装pymysql,不然会报错
peewee.ImproperlyConfigured: MySQL driver not installed!
### 使用方式 #### 创建表from peewee import *db = MySQLDatabase('message', host="127.0.0.1", port=3306, user="root", password="root")class BaseModel(Model):create_time = DateTimeField(default=datetime.now, verbose_name="添加时间")class Music(BaseModel):name = CharField(index=True)singer = CharField(max_length=11, verbose_name="演唱者")duration = CharField(max_length=11, verbose_name="时长")_type = CharField(max_length =11,verbose_name="音乐类型")commany = ForeignKeyField(Commany,verbose_name="版权",backref = "musics")class Meta:database = db table_name = 't_music'class Commany(BaseModel):name = CharField()address = CharField()year - CharField()
db.create_tables([Cmmany,Music])
增加数据
c = Commany()c.name = '中国人'c.full_name = '北京'c.year = 2003c.save()print(c.id)m = Music(name='中国', singer='中国1', duration='1:50',_type='流行', commany=c.id)m.save()
案例数据
commanys = [{'name': '滚石唱片','full_name': '滚石国际音乐股份有限公司','year': 1980},{'name': '华谊兄弟','full_name': '华谊兄弟传媒股份有限公司','year': 1994},{'name': '海蝶音乐','full_name': '北京太合音乐文化发展有限公司','year': 1986},]musics = [{"name": "你是我左边的风景","singer": "林志炫","duration": "2:20","_type": "摇滚","commany": 1},{"name": "把你揉碎捏成苹果","singer": "薛之谦","duration": "2:10","_type": "摇滚","commany": 3},{"name": "游戏人间","singer": "童安格","duration": "1:20","_type": "流行","commany": 2},{"name": "故乡的云","singer": "费翔","duration": "2:40","_type": "摇滚","commany": 1},{"name": "诺言Jason","singer": "青城山下白素贞","duration": "1:10","_type": "古典","commany": 3},{"name": "勇敢的幸福","singer": "Sweety","duration": "1:23","_type": "古典","commany": 2},{"name": "爱丫爱丫","singer": "By2","duration": "2:22","_type": "流行","commany": 1},{"name": "我也曾像你一样","singer": "马天宇","duration": "2:28","_type": "流行","commany": 1}]#### 查询数据The following types of comparisons are supported by peewee:| Comparison | Meaning || ---------- | --------------------------------------- || `==` | x equals y || `<` | x is less than y || `<=` | x is less than or equal to y || `>` | x is greater than y || `>=` | x is greater than or equal to y || `!=` | x is not equal to y || `<<` | x IN y, where y is a list or query || `>>` | x IS y, where y is None/NULL || `%` | x LIKE y where y may contain wildcards || `**` | x ILIKE y where y may contain wildcards || `^` | x XOR y || `~` | Unary negation (e.g., NOT x) |Because I ran out of operators to override, there are some additional query operations available as methods:| Method | Meaning || --------------------- | ----------------------------------------------- || `.in_(value)` | IN lookup (identical to `<<`). || `.not_in(value)` | NOT IN lookup. || `.is_null(is_null)` | IS NULL or IS NOT NULL. Accepts boolean param. || `.contains(substr)` | Wild-card search for substring. || `.startswith(prefix)` | Search for values beginning with `prefix`. || `.endswith(suffix)` | Search for values ending with `suffix`. || `.between(low, high)` | Search for values between `low` and `high`. || `.regexp(exp)` | Regular expression match (case-sensitive). || `.iregexp(exp)` | Regular expression match (case-insensitive). || `.bin_and(value)` | Binary AND. || `.bin_or(value)` | Binary OR. || `.concat(other)` | Concatenate two strings or objects using `||`. || `.distinct()` | Mark column for DISTINCT selection. || `.collate(collation)` | Specify column with the given collation. || `.cast(type)` | Cast the value of the column to the given type. |To combine clauses using logical operators, use:| Operator | Meaning | Example || ---------- | -------------------- | ---------------------------------------------------- || `&` | AND | `(User.is_active == True) & (User.is_admin == True)` || `\|` (pipe) | OR | `(User.is_admin) \| (User.is_superuser)` || `~` | NOT (unary negation) | `~(User.username.contains('admin'))` |Here is how you might use some of these query operators:# Find the user whose username is "charlie".
User.select().where(User.username == 'charlie')# Find the users whose username is in [charlie, huey, mickey]
User.select().where(User.username.in_(['charlie', 'huey', 'mickey']))Employee.select().where(Employee.salary.between(50000, 60000))Employee.select().where(Employee.name.startswith('C'))Blog.select().where(Blog.title.contains(search_string))
更新数据
def update_music():# 方法1:获取数据,在对象上直接修改# m = Music.get_by_id(1)# m.singer='林志炫666'# m.save()# 方法2:利用类方法# update table set ??? where ???Music.update(singer='林志炫').where(Music.id == 1).execute()
删除数据
def delete_music():# 方法1:直接删除对象# m = Music.get_by_id(8)# m.delete_instance()# 方法2:利用类方法Music.delete().where(Music.id >5).execute()
4.2 peewee_async
peewee_async
安装
PostgreSQL
pip install --pre peewee-async
pip install aiopg
MySQL
pip install --pre peewee-async
pip install aiomysql
案例
import asyncio
import peewee
import peewee_async# Nothing special, just define model and database:database = peewee_async.PostgresqlDatabase(database='db_name',user='user',host='127.0.0.1',port='5432',password='password'
)class TestModel(peewee.Model):text = peewee.CharField()class Meta:database = database# Look, sync code is working!TestModel.create_table(True)
TestModel.create(text="Yo, I can do it sync!")
database.close()# Create async models manager:objects = peewee_async.Manager(database)# No need for sync anymore!database.set_allow_sync(False)async def handler():await objects.create(TestModel, text="Not bad. Watch this, I'm async!")all_objects = await objects.execute(TestModel.select())for obj in all_objects:print(obj.text)loop = asyncio.get_event_loop()
loop.run_until_complete(handler())
loop.close()# Clean up, can do it sync again:
with objects.allow_sync():TestModel.drop_table(True)# Expected output:
# Yo, I can do it sync!
# Not bad. Watch this, I'm async!
5 WTForms的使用
简介
WTForms是用于Python Web开发的灵活的表单验证和呈现库。它可以与您选择的任何Web框架和模板引擎一起使用。
WTForms文档
WTForms_Tornado
安装
pip install wtforms-tornado
案例
import tornado.ioloop
import tornado.webfrom wtforms.fields import IntegerField
from wtforms.validators import Required
from wtforms_tornado import Formclass SumForm(Form):a = IntegerField(validators=[Required()])b = IntegerField(validators=[Required()])class SumHandler(tornado.web.RequestHandler):def get(self):self.write("Hello, world")def post(self):form = SumForm(self.request.arguments)if form.validate():self.write(str(form.data['a'] + form.data['b']))else:self.set_status(400)self.write("" % form.errors)application = tornado.web.Application([(r"/", SumHandler),
])if __name__ == "__main__":application.listen(8888)tornado.ioloop.IOLoop.instance().start()
表单验证
wftform.py
from wtforms.fields import IntegerField,StringField
from wtforms_tornado import Form
from wtforms.validators import DataRequired, Lengthclass UserForm(Form):id = IntegerField('ID')username = StringField('用户名',validators=[DataRequired(message='请输入用户名'),Length(min=3,max=8,message='请输入3-8长度的用户名')])nick_name = StringField('昵称')email = StringField('Email')password = StringField('密码')phone = StringField('手机号')language = StringField('语言')
handler.py
forms = UserForm(self.request.arguments)
if forms.validate():del forms.data['id']await objs.create(User,**forms.data)self.render('personal26.html',user_form = forms)
else:self.render('personal26.html',user_form = forms)
HTML生成
{% autoescape None %}{% for field in user_form %}{% if field.label.text == "ID"%}<div class="form-group">{{ field(class_="au-input au-input--full",placeholder=field.label.text)}}</div>{% else %}<div class="form-group">{{ field.label }}{{ field(class_="au-input au-input--full",placeholder=field.label.text)}}{% if field.errors %}{{field.errors}}{% end %}</div>{% end %}
{% end %}
相关文章:
9-tornado-Template优化方法、个人信息案例、tornado中ORM的使用(peewee的使用、peewee_async)、WTForms的使用
在很多情况下,前端模板中在很多页面有都重复的内容可以使用,比如页头、页尾、甚至中间的内容都有可能重复。这时,为了提高开发效率,我们就可以考虑在共同的部分提取出来, 主要方法有如下: 1. 模板继承 2. U…...
IDEA中.java .class .jar的含义与联系
当使用IntelliJ IDEA这样的集成开发环境进行Java编程时,通常涉及.java源代码文件、.class编译后的字节码文件以及.jar可执行的Java存档文件。 1. .java 文件: 1.这些文件包含了Java源代码,以文本形式编写。它们通常位于项目中的源代码目录中…...
北斗三号短报文森林消防应急通信及天通野外图传综合方案
森林火灾突发性强、破坏性大、危险性高,是全球发生最频繁、处置最困难、危害最严重的自然灾害之一,是生态文明建设成果和森林资源安全的最大威胁,甚至可能引发生态灾难和社会危机。我国总体上是一个缺林少绿、生态脆弱的国家,是一…...
js Array.every()的使用
2023.12.13今天我学习了如何使用Array.every()的使用,这个方法是用于检测数组中所有存在的元素。 比如我们需要判断这个数组里面的全部元素是否都包含张三,可以这样写: let demo [{id: 1, name: 张三}, {id: 2, name: 张三五}, {id: 3, name…...
前端编码中快速填充内容--乱数假文
写前端页面的时候,如果要快速插入图片,可以使用 https://picsum.photos/ 详见笔者这篇博文: 工具网站:随机生成图片的网站-CSDN博客 可是,如果要快速填充文字内容该怎么做呢? 以前,我们都是…...
数据结构二维数组计算题,以行为主?以列为主?
1.假设以行序为主序存储二维数组Aarray[1..100,1..100],设每个数据元素占2个存储单元,基地址为10,则LOC[5,5]( )。 A.808 B.818 C.1010 D&…...
springboot(ssm电影院订票信息管理系统 影院购票系统Java系统
springboot(ssm电影院订票信息管理系统 影院购票系统Java系统 开发语言:Java 框架:ssm/springboot vue JDK版本:JDK1.8(或11) 服务器:tomcat 数据库:mysql 5.7(或8.0࿰…...
AI 问答-供应链管理-相关概念:SCM、SRM、MDM、DMS、ERP、OBS、CRM、WMS...
一、供应链管理是什么 供应链管理:理解供应链管理_snowli的博客-CSDN博客 二、SCM 供应链管理 SCM全称为“Supply Chain Management”,即供应链管理。 SCM是企业管理范畴中一个非常重要的概念,指的是企业与供应商、生产商、分销商等各方之…...
初学vue3与ts:vue3选项式api获取当前路由地址
vue2的获取方法 this.$route.pathvue3选项式api获取方法 import { useRouter } from vue-router; const router useRouter(); console.log(router) console.log(router.currentRoute.value.path)...
2023最新大模型实验室解决方案
人工智能是引领未来的新兴战略性技术,是驱动新一轮科技革命和产业变革的重要力量。近年来,人工智能相关技术持续演进,产业化和商业化进程不断提速,正在加快与千行百业深度融合。 大模型实验室架构图 大模型实验室建设内容 一、课…...
leetcode707.设计链表
题目描述 你可以选择使用单链表或者双链表,设计并实现自己的链表。 单链表中的节点应该具备两个属性:val 和 next 。val 是当前节点的值,next 是指向下一个节点的指针/引用。 如果是双向链表,则还需要属性 prev 以指示链表中的…...
【K8s】Kubernetes CRD 介绍(控制器)
文章目录 CRD 概述1. 操作CRD1.1 创建 CRD1.2 操作 CRD 2. 其他笔记2.1 Kubectl 发现机制2.2 校验 CR2.3 简称和属性 3. 架构设计3.1 控制器概览 参考 CRD 概述 CR(Custom Resource)其实就是在 Kubernetes 中定义一个自己的资源类型,是一个具…...
Python 小程序之PDF文档加解密
PDF文档的加密和解密 文章目录 PDF文档的加密和解密前言一、总体构思二、使用到的库三、PDF文档的加密1.用户输入模块2.打开并读取文档数据3.遍历保存数据到新文档4.新文档进行加密5.新文档命名生成路径6.保存新加密的文档 四、PDF文档的解密1.用户输入模块2.前提准备2.文件解密…...
使用python脚本一个简单的搭建ansible集群
1.环境说明: 角色主机名ip地址控制主机server192.168.174.150受控主机/被管节点client1192.168.174.151受控主机/被管节点client2192.168.174.152 2.安装python和pip包 yum install -y epel-release yum install -y python python-pip 3.pip安装依赖库 pip in…...
【价值几十万的仿抖音直播电商系统源码共享】
当下,传统的图文电商模式已经走向没落,以抖音为首的直播电商模式备受用户追捧,它具有实时直播和强互动的特点,是传统电商所不具备的优势。而且,当前正是直播电商的红利期,很多主播和品牌商都通过直播电商业…...
对于vue3项目中使用shareReward还是shareReward.value的问题
问: // 设置当前有没有分享过 默认是false const shareReward ref(false) // 是否是第一次分享 来判断是否发放抽奖次数 function haveShare() { console.log(进入haveshare) if (userInfo.uid && shareReward.value) { rewardTimes(2).then((res) &…...
利用websockify将websocket通信转换成tcp
文章目录 前言websockifywebsockify 介绍websockify 使用 探索的过程提供基础TCP服务测试可用 实现Websocket客户端开始测试websockify功能再次启动websockify单独实现一个js版本websocket客户端 什么是VNC总结 前言 目前遇到一个问题,原本的服务都是利用tcp通信的…...
【LeetCode刷题】-- 163.缺失的区间
163.缺失的区间 class Solution {public List<List<Integer>> findMissingRanges(int[] nums, int lower, int upper) {List<List<Integer>> res new ArrayList<>();for(int num : nums){if(lower < num){res.add(Arrays.asList(lower,num -…...
ClickHouse为何如此之快
针对ClickHouse为什么很快的问题,基于对ClickHouse的基础概念之上,一般会回答是因为是列式存储数据库,同时也会说是使用了向量化引擎,所以快。上面两方面的解释也都能够站得住脚,但是依然不能够解释真正核心的原因。因…...
Avalonia中如何将View事件映射到ViewModel层
前言 前面的文章里面我们有介绍在Wpf中如何在View层将事件映射到ViewModel层的文章,传送门,既然WPF和Avalonia是两套不同的前端框架,那么WPF里面实现模式肯定在这边就用不了,本篇我们将分享一下如何在Avalonia前端框架下面将事件映射到ViewModel层。本章内容还是在上一节的…...
亚马逊/Shopee关键词排名高就一定好?你可能陷入了“数据幻觉”
关键词排名高只说明“看得见”,不代表“卖得动”,更不等于“值得投”。理论锚点信息经济学信号噪音理论:排名只是表层信号,可能混杂品牌词截流等无关信息。SEO 搜索意图分类:信息型搜索不等于交易型搜索。一、误区揭露…...
别再傻傻分不清了!手把手教你选对安规电容(X1/X2/Y1/Y2等级详解)
电子工程师必读:安规电容X/Y等级实战选型指南 当你在设计一款家用空气净化器的开关电源时,突然发现EMC测试总是不达标;当你维修一台工业变频器时,发现安规电容爆裂导致设备瘫痪——这些场景背后,往往隐藏着对X1/X2/Y1/…...
忍者像素绘卷效果展示:云端画布背景+金橙配色+浮雕UI真实渲染效果
忍者像素绘卷效果展示:云端画布背景金橙配色浮雕UI真实渲染效果 1. 视觉风格惊艳呈现 忍者像素绘卷带来了全新的视觉体验,将传统像素艺术与现代设计理念完美融合。这款基于Z-Image-Turbo深度优化的图像生成工具,创造了一个明亮通透的创作环…...
LangChain串联DeepSeek时,如何用自定义OutputParser解决‘思考污染’问题?
LangChain串联DeepSeek时如何用自定义OutputParser解决"思考污染"问题 当我们在LangChain框架中串联使用具备"思考过程"输出的推理模型(如DeepSeek)时,经常会遇到一个棘手的问题:前序节点的思考标签会污染后续…...
Qwen2_5_VLForConditionalGeneration实战:如何用forward方法处理多模态输入(附避坑指南)
Qwen2.5_VL多模态实战:工业级forward方法优化与避坑指南 当文本遇到图像和视频,AI模型的认知能力便迈入了全新维度。Qwen2.5_VLForConditionalGeneration作为当前最先进的多模态生成模型之一,其forward方法的设计直接决定了模型处理图文视频混…...
网站关键词排名变化规律是什么_网站关键词排名优化对SEO的重要性是什么
网站关键词排名变化规律是什么_网站关键词排名优化对SEO的重要性是什么 在当今数字化时代,网站的SEO优化是一个至关重要的领域。其中,关键词排名的变化规律和关键词排名优化对SEO的重要性尤为关键。本文将详细探讨这两方面的内容,帮助你更好…...
Phi-3-mini-4k-instruct-gguf完整指南:模型原理、部署、调参、运维一体化
Phi-3-mini-4k-instruct-gguf完整指南:模型原理、部署、调参、运维一体化 1. 模型概述 Phi-3-mini-4k-instruct-gguf是微软Phi-3系列中的轻量级文本生成模型GGUF版本。这个模型特别适合处理问答、文本改写、摘要整理和简短创作等任务。相比完整版模型,…...
Qwen3-Embedding-4B GPU算力优化:CUDA Stream并发执行向量化与相似度计算,吞吐提升1.8倍
Qwen3-Embedding-4B GPU算力优化:CUDA Stream并发执行向量化与相似度计算,吞吐提升1.8倍 1. 引言:当语义搜索遇上性能瓶颈 想象一下,你正在使用一个智能语义搜索工具,输入“我想吃点东西”,它立刻为你找到…...
Escornabot-lib:面向教育机器人的Arduino语义化控制库
1. Escornabot-lib 库概述Escornabot-lib 是一个专为 Escornabot 教育机器人设计的 Arduino C 类库,由 ROBOteach 团队维护,采用 GNU GPL v3.0 开源协议。该库并非仅提供抽象接口,而是完整封装了 Escornabot 硬件平台的全部底层驱动、状态管理…...
热门AI命理工具盘点:星座、运势、排盘工具一次看
很多朋友对传统命理文化感兴趣,却怕找不对专业靠谱的工具,今天我们就整理了10款不同方向的AI命理相关工具,涵盖星座、面相、运势测算、专业排盘等不同需求,大家可以按需选择。 一、专业命理首选:天府 Agent 链接&#…...
