pursue wind pursue wind
首页
Java
Python
数据库
框架
Linux
中间件
前端
计算机基础
DevOps
项目
面试
书
关于
归档
MacOS🤣 (opens new window)
GitHub (opens new window)
首页
Java
Python
数据库
框架
Linux
中间件
前端
计算机基础
DevOps
项目
面试
书
关于
归档
MacOS🤣 (opens new window)
GitHub (opens new window)
  • 基于Python轻松自建App服务器

    • 0App 与后端服务器通信方法简介
    • 1本小册要完成的通信场景功能
    • 2服务器端组件框架的选择与介绍
    • 3基于腾讯云的服务器端环境搭建
    • 4基于 Tornado 的 HTTP 服务器简介及代码组织框架
    • 5第一次数据请求 1:服务器接收用户注册信息
    • 6第一次数据请求 2:为用户处理模块增加 log 管理
    • 7第一次数据请求 3:将用户信息写入 MySQL 数据库
      • 整个逻辑架构图
      • 配置数据用户名和密码
      • 创建数据库
      • 代码中配置数据库
      • 代码中定义数据库表
      • 代码中初始化数据库
      • 代码将用户信息写入数据库
      • 增加错误码处理
      • 结果检查
        • HTTP 发包模拟器再次请求注册信息
        • 查看控制台
        • 查看数据库
        • 在 HTTP 发包模拟器上再次点击注册
      • 代码下载
      • 小结
    • 8服务器接收客户端图片上传,并保存在硬盘中
    • 9服务器接收客户端请求,并返回 H5 页面
    • 10搭建基于 Nginx 的代理服务器
    • 11基于 HTTPS 的数据加密
    • 12大型 HTTP 服务器架构演进路线及思路
    • 13总结
  • 基于Python实现微信公众号爬虫

  • Xpath
  • python3 翻译
  • python3循环创建数据库表
  • python实用30个小技巧
  • pywin32
  • Python
  • 基于Python轻松自建App服务器
pursuewind
2020-11-23
目录

7第一次数据请求 3:将用户信息写入 MySQL 数据库

# 将用户信息写入 MySQL 数据库

上两小节已完成逻辑代码,这小节将学习使用 ORM 的方式将用户注册信息写入数据库中。

# 整个逻辑架构图

数据库的信息(如地址、端口、用户名和密码等)存放在 base.py 中,model.py 中定义了数据库表并从 base.py 中获取数据库信息。当 main.py 启动时,其将调用 model.py 初始化数据库。而 users_views.py 负责将客户端的请求数据写入数据库中,并返回注册成功信息。

# 配置数据用户名和密码

用户名为 root,密码为 pwd@demo, 在服务器端输入如下命令配置数据库。

mysql -u root
set password for 'root' @localhost = password('pwd@demo');
1
2

# 创建数据库

在服务器端输入如下命令创建数据库。

CREATE DATABASE demo CHARACTER SET 'utf8' COLLATE 'utf8_general_ci';
1

创建完成后,使用 show databases 检查数据库是否创建成功。

# 代码中配置数据库

在配置文件 base.py 中指定数据库,需修改 conf/base.py,增加如下代码:

from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
engine = create_engine('mysql://root:pwd@demo@localhost:3306/demo?charset=utf8', encoding="utf8", echo=False)
BaseDB = declarative_base()
1
2
3
4

# 代码中定义数据库表

在前面的介绍中,我们提到,models.py 这个文件主要包含数据库表的定义及初始化。从第 6 小节中看到,用户注册信息包含手机号、密码和验证码。这里需要记录在数据库中的有手机号(phone)和密码(password),当然还包括创建的时间(createTime)。这些信息作为数据库表项,在 models.py 中定义,在 models.py 文件中输入如下代码:

#! /usr/bin/python3
# -*- coding:utf-8 -*-

from conf.base import BaseDB, engine
import sys
from sqlalchemy import (
Column, 
Integer,
    String, 
    DateTime
)

    
class Users(BaseDB):
    """table for users
    """
    __tablename__ = "users"
    #定义表结构,包括id,phone,password,createTime
    id = Column(Integer, primary_key=True)
    phone = Column(String(50), nullable=False)
    password = Column(String(50), nullable=True)
    createTime = Column(DateTime, nullable=True)
    
    def __init__(self, phone, password, createTime):
        self.phone = phone
        self.password = password
        self.createTime = createTime
    
    
def initdb():
    BaseDB.metadata.create_all(engine)
    
if __name__ == '__main__':
    print ("Initialize database")
    initdb()
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

# 代码中初始化数据库

在 main.py 中,调用 models.py 初始化数据库并启用数据库

具体代码如下:

#! /usr/bin/python3
# -*- coding:utf-8 -*-
# Author: demo
# Email: demo@demo.com
# Version: demo

import tornado.ioloop
import tornado.web
import os
import sys
from tornado.options import define, options
from common.url_router import include, url_wrapper
from tornado.options import define, options
from models import initdb
from sqlalchemy.orm import scoped_session, sessionmaker
from conf.base import BaseDB, engine


class Application(tornado.web.Application):
    def __init__(self):
        initdb()
        handlers = url_wrapper([
        (r"/users/", include('views.users.users_urls'))
        ])
        #定义tornado服务器的配置项,如static/templates目录位置,debug级别等
        settings = dict(
            debug=True,
            static_path=os.path.join(os.path.dirname(__file__), "static"),
            template_path=os.path.join(os.path.dirname(__file__), "templates")
        )
        tornado.web.Application.__init__(self, handlers, **settings)
        self.db = scoped_session(sessionmaker(bind=engine,
                                  autocommit=False, autoflush=True,
                                  expire_on_commit=False))
 
 
if __name__ == '__main__':
    print ("Tornado server is ready for service\r")
    tornado.options.parse_command_line()
    Application().listen(8000, xheaders=True)
    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
32
33
34
35
36
37
38
39
40
41

# 代码将用户信息写入数据库

修改 users_views.py,将用户数据写入数据库中,修改内容包括从 models 中导入 Users 类表,并判断用户是否在数据库中。如果存在,返回注册失败信息;如果不存在,将用户信息写入数据库,并返回注册成功信息。

users_views.py 完整代码如下:

#! /usr/bin/python3
# -*- coding:utf-8 -*-

import tornado.web
import sys
from tornado.escape import json_decode
import logging
from logging.handlers import TimedRotatingFileHandler
from datetime import datetime


#从commons中导入http_response方法
from common.commons import (
    http_response,
)

#从配置文件中导入错误码
from conf.base import (
    ERROR_CODE,
)

from models import (
    Users
)
  
 
########## Configure logging #############
logFilePath = "log/users/users.log"
logger = logging.getLogger("Users")  
logger.setLevel(logging.DEBUG)  
handler = TimedRotatingFileHandler(logFilePath,  
                                   when="D",  
                                   interval=1,  
                                   backupCount=30)  
formatter = logging.Formatter('%(asctime)s \
%(filename)s[line:%(lineno)d] %(levelname)s %(message)s',)  
handler.suffix = "%Y%m%d"
handler.setFormatter(formatter)
logger.addHandler(handler)
 
 
class RegistHandle(tornado.web.RequestHandler):
    """handle /user/regist request
    :param phone: users sign up phone
    :param password: users sign up password
    :param code: users sign up code, must six digital code
    """
    
    @property
    def db(self):
        return self.application.db
        
    def post(self):
        try:
            #获取入参
            args = json_decode(self.request.body)
            phone = args['phone']
            password = args['password']
            verify_code = args['code']
        except:
            #获取入参失败时,抛出错误码及错误信息
            logger.info("RegistHandle: request argument incorrect")
            http_response(self, ERROR_CODE['1001'], 1001)
            return 
            
        ex_user = self.db.query(Users).filter_by(phone=phone).first()
        if ex_user:
            #如果手机号已存在,返回用户已注册信息
            http_response(self, ERROR_CODE['1002'], 1002)
            self.db.close()
            return
        else:
            #用户不存在,数据库表中插入用户信息
            logger.debug("RegistHandle: insert db, user: %s" %phone)
            create_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
            add_user = Users(phone, password, create_time)                         
            self.db.add(add_user)
            self.db.commit()
            self.db.close()
            #处理成功后,返回成功码“0”及成功信息“ok”
            logger.debug("RegistHandle: regist successfully")
            http_response(self, ERROR_CODE['0'], 0)
            
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

# 增加错误码处理

修改 base.py,增加错误码 1002:

"1002": "用户已注册,请直接登录",
1

# 结果检查

上面的几大步骤,从配置数据库,到代码指定数据库,再到将用户信息写入数据库,我们已完成了数据库部分代码的编写,下面执行 main.py 文件,查看是否运行正常。

# HTTP 发包模拟器再次请求注册信息

# 查看控制台

# 查看数据库

# 在 HTTP 发包模拟器上再次点击注册

可以看到,服务器端返回的错误信息提示该用户已注册。

# 代码下载

到目前为止,服务器端代码如下:
demo8 (opens new window)

# 小结

至此,我们已完成了数据库的写入,加上前两节的逻辑处理和 log 处理,客户端与服务器端的第一条消息请求交互已完成。这里只是使用到了 SQLAlchemy 很有限的功能,SQLAlchemy 具有很强大的功能,感兴趣的同学可以访问 SQLAlchemy 官网 (opens new window)学习。

Last Updated: 2023/02/14, 18:02:00
6第一次数据请求 2:为用户处理模块增加 log 管理
8服务器接收客户端图片上传,并保存在硬盘中

← 6第一次数据请求 2:为用户处理模块增加 log 管理 8服务器接收客户端图片上传,并保存在硬盘中→

Theme by Vdoing | Copyright © 2019-2023 pursue-wind | 粤ICP备2022093130号
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式
  • 飙升榜
  • 新歌榜
  • 云音乐民谣榜
  • 美国Billboard榜
  • UK排行榜周榜
  • 网络DJ