当前位置:   article > 正文

9-tornado-Template优化方法、个人信息案例、tornado中ORM的使用(peewee的使用、peewee_async)、WTForms的使用_no module named 'peewee_async

no module named 'peewee_async
在很多情况下,前端模板中在很多页面有都重复的内容可以使用,比如页头、页尾、甚至中间的内容都有可能重复。

这时,为了提高开发效率,我们就可以考虑在共同的部分提取出来,
主要方法有如下:
1. 模板继承
2. UI模板
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

1 模板继承

common/base.html

{% block content %}
{% end %}
  • 1
  • 2

shop2.html

{% extends 'common/base.html'%}

{% block content %}
{% end %}
  • 1
  • 2
  • 3
  • 4

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,
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

3 个人信息案例

环境搭建

在网站中,少了数据CRUD的操作,但在tornado中,我们知道若想操作的话尽量使用异步的操作,这样效率才会高。

那应该如何编写呢,下面我们来一起做下吧。首先我们先一起搭建下环境。

具体的操作如下:

前端

copy 原生素材

html —> templates

css —> static/css

js —> static/js

img —> static/img

到项目中

后端

from tornado import web, ioloop
from tornado.web import StaticFileHandler

class 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()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

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;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

熟悉Mysql操作

之前我们了解过pymysql操作数据库,但那是同步的。

我们需要使用一个异步的框架,在这,我们推荐使用aiomysql,它的底层大量的使用了pymysql,只是它通过asyncio实现的访问数据库

安装方式

pip install aiomysql
  • 1

使用方式

import asyncio
import aiomysql

async 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 == 42
    pool.close()
    await pool.wait_closed()


loop = asyncio.get_event_loop()
loop.run_until_complete(test_example(loop))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

4 tornado中ORM的使用

4.1 peewee的使用

官网链接

Peewee是一个简单而小型的ORM。使其易于学习且使用直观。

  • 一个小的,表达力很强的ORM
  • python 2.7+和3.4+(使用3.11开发)
  • 支持sqlite,mysql,postgresql和cockroachdb
  • 大量的扩展

安装

pip install peewee
  • 1
 tip
需要安装pymysql,不然会报错
  • 1
  • 2

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])
  • 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

增加数据

    c = Commany()
    c.name = '中国人'
    c.full_name = '北京'
    c.year = 2003
    c.save()

    print(c.id)

    m = Music(name='中国', singer='中国1', duration='1:50',
              _type='流行', commany=c.id)
    m.save()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

案例数据

    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))
  • 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
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138

更新数据

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()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

删除数据

def delete_music():
    # 方法1:直接删除对象
    # m = Music.get_by_id(8)
    # m.delete_instance()

    # 方法2:利用类方法
    Music.delete().where(Music.id >5).execute()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

4.2 peewee_async

peewee_async

安装

PostgreSQL

pip install --pre peewee-async
pip install aiopg
  • 1
  • 2

MySQL

pip install --pre peewee-async
pip install aiomysql
  • 1
  • 2

案例

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!
  • 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
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51

5 WTForms的使用

简介

WTForms是用于Python Web开发的灵活的表单验证和呈现库。它可以与您选择的任何Web框架和模板引擎一起使用。
  • 1

WTForms文档
WTForms_Tornado

安装

pip install wtforms-tornado
  • 1

案例

import tornado.ioloop
import tornado.web

from wtforms.fields import IntegerField
from wtforms.validators import Required
from wtforms_tornado import Form

class 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()
  • 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

表单验证

wftform.py

from wtforms.fields import IntegerField,StringField
from wtforms_tornado import Form
from wtforms.validators import DataRequired, Length

class 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('语言')
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

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)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

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 %}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/172802
推荐阅读
相关标签
  

闽ICP备14008679号