1.模型建立与数据初始化
1.1分析建立表所需要的字段
本次主要是添加一个帖子展示时,所需要的内容,这里就得创建一个mysql的数据表去存储它的内容。
1.2 使用peewee创建多表关联结构Model
模型建立
# forum/models.py
# 用于创建数据表模型
from peewee import *
from forum import database
from datetime import datetime
# 创建基类:减少重复代码
class BaseModel(Model):
create_time = DateTimeField(default = datetime.now)
# 创建函数,用于返回用户的信息位字典形式
def to_json(self) -> dict:
r = {}
for k in self.__data__.keys():
# 判断数据是否是create_time(时间不是字符串)
if k == 'create_time':
r[k] = str(getattr(self,k))
else:
r[k] = getattr(self,k)
return r
class Meta:
database = database
# 创建帖子表
class TopicModel(BaseModel):
id = CharField(primary_key = True)
title = CharField(verbose_name='标题')
imgs = CharField(verbose_name='图片', max_length=2000)
content = CharField(verbose_name='内容')
chick_num = CharField(verbose_name='点击数')
type_ = CharField(verbose_name='类型')
# 关联主表
user = ForeignKeyField(UserModel, backref='topics')
class Meta:
table_name = 't_topic'
运行此模型添加到数据库中
TopicModel.create_table(True)
1.3 sql插入数据
INSERT INTO `t_topic` (`id`, `create_time`, `title`, `imgs`, `content`, `chick_num`, `type_`, `user_id`) VALUES ('5de0d5bc5dd0a380dbc1aca3', '2050-01-01 00:00:00', 'Adobe发布低门槛AR创作Aero、Dimension 3.0等,带来AR营销机遇!', '/static/img/1575015868036-4610b912c8fcc3ce816273d1ab5b168dd53f2051.jpeg,/static/img/1575015868037-c9fcc3cec3fdfc03362df891ee214791a4c22661.jpeg,/static/img/1575015868038-7a899e510fb30f2401ac73d8f28b1146ac4b03de.jpeg,/static/img/1575015868039-aec379310a55b319cd936cce79b74223cefc17c2.jpeg,/static/img/1575015868040-58ee3d6d55fbb2fb5b4849057554e0a14623dc6d.jpeg,/static/img/1575015868041-10dfa9ec8a1363277290d613ab9160e908fac7b0.jpeg,/static/img/1575015868042-ac345982b2b7d0a2ba08f1a8f1f1b60c4a369ae2.jpeg', 0xE6ADA4E5898DEFBC8CE59CA839E69C883230E697A5E79A84E3808AE59CA8E696B0E5AA92E4BB8BE696B9E99DA2E2809CE4B88AE4B88BE6B182E7B4A2E2809DE79A8441646F6265EFBC8CE69C80E7BB88E98089E68BA9E4BA864152E3808BE4B880E69687E4B8ADEFBC8C565250696E6561E69BBEE68EA2E8AEA8E4BA8641646F6265E59CA8E696B0E5AA92E4BB8BE696B9E99DA2E79A84E6BCABE6BCABE68EA2E7B4A2EFBC8CE5B9B6E69C80E7BB88E98089E68BA9E4BA864152EFBC88E6849FE585B4E8B6A3E79A84E8AFBBE88085E58FAFE782B9E587BBE8939DE5AD97E887AAE8A18CE99885E8AFBBEFBC89E380820A0AE8808CE69CACE69C88EFBC8CE4BA8EE7BE8EE59BBDE5BD93E59CB0E697B6E997B43131E69C8832E697A52D36E697A5E4B8BEE58A9EE79A844D4158E5A4A7E4BC9AE4B88AEFBC8C41646F6265E5B195E7A4BAE4BA86E69797E4B88BE4B880E7B3BBE58897E8AEBEE8AEA1E5B7A5E585B7E79A84E69C80E696B0E58AA8E68081EFBC8CE585B6E4B8ADE58C85E68BACE69C80E696B0E68EA8E587BAE79A844152E8AEBEE8AEA1E5B7A5E585B74165726FE38081E4BBA5E58F8AE694AFE68C814152E79A8444696D656E73696F6E20332E30EFBC8C41646F6265E59CA84152E696B9E99DA2E79A84E5B883E5B180E5BE90E5BE90E5B195E5BC80E38082E7BB86E8B08841646F6265E59CA84152E696B9E99DA2E79A84E5B883E5B1800A0AE59CA8E6988EE7A1AEE4BA864152E79A84E58F91E5B195E696B9E59091E5908EEFBC8C41646F6265E98090E6ADA5E5B195E5BC80E4BA86E59CA8E6ADA4E696B9E99DA2E79A84E8A18CE58AA8E3808241646F6265E58588E698AFE5B195E7A4BAE4BA86E4B8A4E6ACBEE59FBAE4BA8E4152E8AEBEE8AEA1E79A84E697A0E69687E69CAC5549E6A682E5BFB5EFBC8CE99A8FE5908EE58F88E6ADA3E5BC8FE58F91E8A18CE4BA864152E588B6E4BD9CE5B7A5E585B74165726FEFBC8CE5B9B6E59CA84D4158E5A4A7E4BC9AE4B88AE5B195E7A4BAE4BA8644696D656E73696F6E20332E30E694AFE68C814152E79A84E696B0E6B688E681AFE380820A0A41646F6265205844E68F90E587BAE697A0E69687E69CAC5549E8AEBEE8AEA1EFBC9A546578742D46726565205549204B697420666F722041646F62652058440A0AE59CA8E6ADA4E5898DE4BD93E9AA8CE5A49AE4BABAE5BC80E694BEE4B896E7958C5652E6B8B8E6888FE3808AE69585E59C9FE3808BE79A84E697B6E58099EFBC8CE5B08FE7BC96E4B8BAE6B8B8E6888FE6838AE889B3E79A84E794BBE99DA2E5928CE5BC80E694BEE79A84E4B896E7958CE8808CE79D80E8BFB7E38082E4BD86E4B88EE6ADA4E5908CE697B6EFBC8CE5B08FE7BC96E4B99FE58F91E78EB0E3808AE69585E59C9FE3808BE8BF99E6A0B7E79A845652E6B8B8E6888FE5AD98E59CA8E4B880E4B8AAE997AEE9A298EFBC9AE794B1E4BA8EE698AFE99288E5AFB950432F5652E794A8E688B7E5908CE697B6E5BC80E58F91EFBC8CE3808AE69585E59C9FE3808BE79A845549E8AEBEE8AEA1E59FBAE69CACE98089E68BA9E4BA86E4BCA0E7BB9FE7BD91E6B8B8E68980E98787E794A8E79A84E69687E69CACE4B8BAE4B8BBE79A845549E8AEBEE8AEA1E38082E8BF99E4B8805549E59CA8E4BCA0E7BB9FE79A843244E698BEE7A4BAE599A8E4B88AE997AEE9A298E4B88DE5A4A7EFBC8CE4BD86E59CA8E585A8E699AFE79A845652E78EAFE5A283E4B8ADE4BD93E9AA8CE5B9B6E4B88DE7AE97E4BDB3E380820A0AE6ADA4E5A496EFBC8CE8BF87E5A49AE69687E69CACE79A845549E8AEBEE8AEA1E4B99FE8BE83E4B8BAE5BDB1E5938DE99885E8AFBBE59BB0E99ABEE4BABAE7BEA4E4BBA5E58F8AE8A786E99A9CE4BABAE7BEA4E79A84E794A8E688B7E4BD93E9AA8CE38082E79BAEE5898DEFBC8CE4B896E7958CE69687E79BB2E6AF94E4BE8BE4BB8DE9AB98E8BEBE323025EFBC8CE8BF99E4B880E58F97E4BC97E7BEA4E4BD93E5BE88E99ABEE4B88EE5AD98E59CA8E5A4A7E9878FE69687E69CACE79A845549E4BAA4E4BA92E38082E8808CE5AFB9E4BA8EE8A786E99A9CE7BEA4E4BD93E8808CE8A880EFBC8CE59CA8E69687E69CACE4B88DE69893E4BA8EE8AF86E588ABE79A84E68385E586B5E4B88BEFBC8CE69C89E79D80E9AB98E5AFB9E6AF94E5BAA6E5928CE7AE80E58D95E5BDA2E78AB6E79A84E59BBEE6A087E883BDE5A49FE68F90E4BE9BE68385E699AFE4B88AE4B88BE69687E38082E4BD86E685A2E685A2E99A8FE79D80E8AFADE99FB3E7958CE99DA2E4BBA5E58F8A4152E68A80E69CAFE79A84E58F91E5B195EFBC8CE5889BE5BBBA5549E697B6E69687E69CACE5B7B2E98090E6B890E4B88DE5868DE698AFE5BF85E5A487E79A84E7BB84E4BBB6E38082E8AFADE99FB3E7958CE99DA2E58581E8AEB8E794A8E688B7E9809AE8BF87E8AFADE99FB3E591BDE4BBA4E4B88EE5BA94E794A8E8BF9BE8A18CE4BAA4E4BA92EFBC9B4152E4BD93E9AA8CE4B99FE58FAFE4BBA5E59CA8E6B688E999A4E6BD9CE59CA8E8A786E8A789E5B9B2E689B0E79A84E5908CE697B6E6B7BBE58AA0E69C89E794A8E79A84E4BFA1E681AFEFBC9AE9809AE8BF87E59BBEE5838FE5928CE58AA8E794BBE69DA5E68F90E4BE9BE6B885E699B0E79A84E68C87E4BBA4EFBC8CE883BDE5B8AEE58AA9E794A8E688B7E59CA8E4B88DE99C80E8A681E99885E8AFBBE79A84E68385E586B5E4B88BE4B88E5549E4BAA4E6B581E380820A0AE4B8BAE6ADA4EFBC8C2041646F6265E4BA8E3130E69C883331E697A5E68F90E587BAE4BA86E4B880E7A78DE794A8E4BBA5E58F96E4BBA3E69687E69CAC5549E79A84E8AEBEE8AEA1E696B9E6A188EFBC9A546578742D46726565205549204B697420666F722041646F6265205844E38082E8AFA5E696B9E6A188E794B143617261204E65656CE8AEBEE8AEA1EFBC8CE588A9E794A8E4BA86E8AFADE99FB3E38081E59BBEE5838FE5928CE58AA8E794BBE69DA5E4B8BAE794A8E688B7E68F90E4BE9BE6B885E699B0E79A84E68C87E4BBA4E38082546578742D46726565205549204B6974E58C85E590ABE4B8A4E4B8AAE8AEBEE8AEA1E6A682E5BFB5EFBC8CE4B8A4E88085E59D87E98787E794A8E4BA86E8AFADE99FB3E7958CE99DA2E5928C4152E4BD93E9AA8CE38082E9A696E4B8AAE6A682E5BFB5E698AFE4B880E6ACBEE7A7BBE58AA8E5AFBCE888AAE5BA94E794A8E7A88BE5BA8F506F6C61726973EFBC8CE58581E8AEB8E794A8E688B7E9809AE8BF87E8AFADE99FB3E591BDE4BBA4E5928C4152E8B7AFE6A087E5898DE5BE80E79BAEE79A84E59CB0EFBC9BE7ACACE4BA8CE4B8AAE6A682E5BFB5E58899E698AFE4B880E6ACBEE8999AE68B9FE58AA9E6898B4152746965EFBC8CE883BDE5A49FE5B8AEE58AA9E794A8E688B7E8AF86E588ABE4B88DE7869FE68289E79A84E5AFB9E8B1A1E5928CE4BD8DE7BDAEEFBC8CE5B9B6E5B8AEE58AA9E794A8E688B7E8A7A3E586B3E697A5E5B8B8E7949FE6B4BBE4B8ADE58FAFE883BDE98187E588B0E79A84E997AEE9A298E3808243617261204E65656CE8BF98E4B8BAE585B6E4BB964152E8AEBEE8AEA1E88085E68F90E4BE9BE4BA86E4B880E4B8AAE794B1E4B88DE5908CE59BBEE6A087E5928CE7BB84E4BBB6E7BB84E68890E79A84E5BA93EFBC8CE5B8AEE58AA9E8AEBEE8AEA1E88085E5889BE5BBBAE697A0E69687E69CACE79A845549E4BAA4E4BA92E7958CE99DA2E380820A0A41646F6265E68EA8E587BAE697A0E99C80E68E8CE68FA1E7BC96E7A88BE68A80E5B7A7E79A844152E5889BE4BD9CE5B7A5E585B74165726F0A0A3131E69C8835E697A5EFBC8C41646F6265E6ADA3E5BC8FE58F91E8A18CE4BA86E69797E4B88B4152E5889BE4BD9CE5B7A5E585B741646F6265204165726FE38082E8AFA5E5B7A5E585B7E58581E8AEB8E8AEBEE8AEA1E5B888E59CA84152E78EAFE5A283E4B8ADE69E84E5BBBAE5928CE58886E4BAABE6B289E6B5B8E5BC8FE4BD93E9AA8CEFBC8CE5B9B6E697A0E99C80E68E8CE68FA1E4BBBBE4BD95E7BC96E7A88BE68A80E5B7A7E380820A0AE4B88EE585B6E4BB964152E5889BE4BD9CE5B7A5E585B7E79BB8E6AF94EFBC8C41646F6265204165726FE585B7E5A487E5A682E4B88BE79A84E58A9FE883BDE38082E58FAFE8A786E58C96E5889BE4BD9CEFBC9A4165726FE883BDE5A49FE68F90E4BE9BE79BB4E8A782E4B894E4B88DE789BAE789B2E8B4A8E9878FE79A84E5889BE4BD9CE4BD93E9AA8CE38082E794A8E688B7E58FAFE4BBA5E4BDBFE794A8E58FAFE8A786E58C965549E69E84E5BBBA4152E4BD93E9AA8CEFBC8CE8808CE58886E6ADA5E8AFB4E6988EE58899E5B086E5BC95E5AFBCE794A8E688B7E69E84E5BBBAE78BACE789B9E79A844152E59CBAE699AFEFBC9B, 1, 'technology', '5de0d2696e78ad79c2e2c64a');
2.主页显示内容
2.1 查看前端所需的接口
在前端点击到主页时,可以看到所需要的请求访问的接口,这个就是我们所需要在后端从数据库中获取的内容
2.2使用Tornado创建获取数据的接口
接口代码
# forum/handler/TopicHandler.py
from forum.handler.BaseHandler import BaseHandler
from forum import manager
from forum.models import TopicModel
# 获取数据库中的帖子内容
class GetTopicsHandler(BaseHandler):
async def get(self):
# 从数据库中使用peewee_async异步获取数据
topics = await manager.execute(TopicModel.select().order_by(TopicModel.create_time.desc()))
rs_data = {}
data = []
for topic in topics:
# 把文章信息转为json
t = topic.to_json()
# 把用户信息转为json
t['user'] = t.get('user').to_json()
# 分割图片的地址
if t.get('imgs') == None or t.get('imgs') == '':
t['imgs'] = None
else:
# 多个图片存储在imgs中,需要分隔开才行
t['imgs'] = t.get('imgs').split(',')
data.append(t)
rs_data['code'] = 200
rs_data['msg'] = '获取成功'
rs_data['topics'] = data
self.finish(rs_data)
挂载路由
# router.py
from forum.handler import BaseHandler,UserHandler,TopicHandler
handlers = [
('/',BaseHandler.IndexHandler),
('/api/user/add/?', UserHandler.AddUserHandler),
('/api/send_msg/?', UserHandler.SendEmailHandler),
('/api/user/login/?', UserHandler.LoginHandler),
('/api/user/get/?', UserHandler.GetUserHandler),
('/api/user/update/?', UserHandler.UpdateUserHandler),
('/api/topic/all/?', TopicHandler.GetTopicsHandler)
]
3.帖子详情
3.1概述
当我们点击每个帖子的详情时候,我们需要从后端获取数据,展示出帖子的详细内容(每个帖子有对应id)
3.2查看前端所需要的接口和传递的数据
这是每次后端开发新的接口所需要做的事情
3.3使用Tornado创建获取详情页的接口
接口
# forum/handler/TopicHandler.py
from forum.handler.BaseHandler import BaseHandler
from forum import manager
from forum.models import TopicModel
# 从数据库中获取帖子的详情内容
class GetOneTopicHandler(BaseHandler):
async def post(self):
rs_data = {}
# 获取前端获取来的ID
id = self.get_body_argument('id')
# 获取数据
topic = await manager.get(TopicModel, id=id)
# 把文章信息转成json
t = topic.to_json()
# 把用户信息转成json
t['user'] = t.get('user').to_json()
# 分割图片的地址
if t.get('imgs') == None or t.get('imgs') == '':
t['imgs'] = None
else:
t['imgs'] = t.get('imgs').split(',')
# 传递给前端
rs_data['code'] = 200
rs_data['msg'] = '获取成功'
rs_data['topic'] = t
self.finish(rs_data)
挂载路由
# router.py
from forum.handler import BaseHandler,UserHandler,TopicHandler
handlers = [
('/',BaseHandler.IndexHandler),
('/api/user/add/?', UserHandler.AddUserHandler),
('/api/send_msg/?', UserHandler.SendEmailHandler),
('/api/user/login/?', UserHandler.LoginHandler),
('/api/user/get/?', UserHandler.GetUserHandler),
('/api/user/update/?', UserHandler.UpdateUserHandler),
('/api/topic/all/?', TopicHandler.GetTopicsHandler),
('/api/topic/id/?', TopicHandler.GetOneTopicHandler)
]
3.4效果展示
4.分类显示帖子
4.1查看前端所需的接口和传递的数据
4.2使用Tornado创建获取分类页面的过滤数据接口
总体来说和2.的开发接口很类似,需要在获取信息时添加一个过滤即可。
接口代码
# forum/handler/TopicHandler.py
from forum.handler.BaseHandler import BaseHandler
from forum import manager
from forum.models import TopicModel
# 获取数据库中的帖子内容
class GetTopicsHandler(BaseHandler):
async def post(self):
# 从前端获取传递的过滤类型
type_ = self.get_body_argument('type')
# 从数据库中获取数据
topics = await manager.execute(TopicModel.select().where(TopicModel.type_ == type_).order_by(TopicModel.create_time.desc()))
rs_data = {}
data = []
for topic in topics:
# 把文章信息转为json
t = topic.to_json()
# 把用户信息转为json
t['user'] = t.get('user').to_json()
# 分割图片的地址
if t.get('imgs') == None or t.get('imgs') == '':
t['imgs'] = None
else:
# 多个图片存储在imgs中,需要分隔开才行
t['imgs'] = t.get('imgs').split(',')
data.append(t)
rs_data['code'] = 200
rs_data['msg'] = '获取成功'
rs_data['topics'] = data
self.finish(rs_data)
5.发布帖子信息
5.1查看前端所需要的接口和传递的数据方式
5.2创建接口
创建WTForms表单验证
# forum/wtforms.py
# 完整注册(给t_user表)增加数据之前的数据验证
from wtforms_tornado import Form
from wtforms.fields import StringField
from wtforms.fields.simple import HiddenField
from wtforms.validators import DataRequired, Length
# 发布新帖子的数据验证
class AddTopicForm(Form):
type_ = StringField('类型', validators=[DataRequired(message='请选择类型')])
title = StringField('标题', validators=[DataRequired(message='请填写标题')])
content = StringField('内容')
接口
# forum/handler/TopicHandler.py
from uuid import uuid4
from forum.handler.BaseHandler import BaseHandler
from forum import manager
from forum.models import TopicModel, UserModel
from forum.wtforms import AddTopicForm
from forum.decorators import login_required_async
# 发布帖子:增加数据
class AddTopicHandler(BaseHandler):
@login_required_async
async def post(self):
rs_data = {}
# 获取传递的数据,传递到Form
topic_form = AddTopicForm(self.request.arguments)
# 验证
if topic_form.validate():
# 验证成功,增加帖子
# 获取当前用户信息: 通过登录装饰器获取
user = await manager.get(UserModel, id=self._user_id)
# 生成一个唯一的id标识帖子
id = uuid4().hex
# 发布图片:
# 建立一个full_img_path
img_path = []
# 保存前端发布的图片信息
imgs = self.request.files.get('imgs',[])
for i in imgs:
# 获取文件名字
file_name = f'{uuid4().hex}{os.path.splitext(i.get("filename"))[-1]}'
# 获取文件全名:保存的地址
full_path = os.path.join(settings.get('static_path'),'img',file_name)
# 保存图片文件
with open(full_path,'wb') as f:
f.write(i.get('body'))
# 追加图片的路径到img_path
img_path.append(f'/static/img/{file_name}')
# 更新topic对象中
await manager.create(TopicModel, **topic_form.data, user=user, id=id, imgs=','.join(img_path))
rs_data['code'] = 200
rs_data['msg'] = '发帖成功'
else:
# 验证失败,数据不合法
rs_data['code'] = 500
rs_data['msg'] = '发帖失败'
self.finish(rs_data)
5.获取个人帖子
5.1查看前端所需的接口和传递的数据
5.2使用token创建获取信息的接口
# 获取个人发布的帖子信息
class GetMyTopicHandler(BaseHandler):
@login_required_async
async def post(self):
rs_data = {}
# 通过user_id进行筛选获取帖子信息
# 多表查询
topics = await manager.execute(TopicModel.select().join(UserModel).where(UserModel.id == self._user_id).order_by(TopicModel.create_time.desc()))
# 将所有帖子信息转换成json<包含user信息>
data = []
for t in topics:
d = tran_topic(t)
data.append(d)
# 响应前端
rs_data['code'] = 200
rs_data['msg'] = '获取个人帖子信息成功'
rs_data['topics'] = data
self.finish(rs_data)