使用 aiohttp 和 Tortoise ORM 搭建一个带界面的异步 web 网站
使用 aiohttp 和 Tortoise ORM 搭建一个带界面的异步 web 网站。这是一个很好的技术组合,可以充分利用 Python 的异步特性。
安装必要的包
pip install aiohttp aiohttp_jinja2 tortoise-orm
项目结构
创建一个基本的项目结构:
project/
├── main.py # 应用入口
├── models.py # Tortoise ORM 模型
├── routes.py # 路由定义
├── views.py # 视图处理函数
├── static/ # 静态文件 (CSS, JS等)
└── templates/ # Jinja2 模板
定义数据库模型
在 models.py 中使用 Tortoise ORM 定义模型:
from tortoise import fields
from tortoise.models import Model
class User(Model):
id = fields.IntField(pk=True)
username = fields.CharField(max_length=50, unique=True)
nickname = fields.CharField(max_length=50, null=True)
email = fields.CharField(max_length=100)
created_at = fields.DatetimeField(auto_now_add=True)
class Meta:
table = "users"
def __str__(self):
return self.username
创建视图和路由
在 views.py 中定义视图函数:
# views.py 扩展版
import aiohttp_jinja2
from aiohttp import web
from models import User
@aiohttp_jinja2.template('index.html')
async def index(request):
# 获取所有用户
users = await User.all()
title = 'hello word'
return {'users': users,'title':title}
async def add_user(request):
data = await request.post()
# 创建新用户
user = await User.create(username=data['username'], email=data['email'])
return web.HTTPFound('/')
@aiohttp_jinja2.template('user.html')
async def get_user(request):
user_id = request.match_info.get('id')
# 根据ID查找用户
user = await User.get_or_none(id=user_id)
if not user:
raise web.HTTPNotFound(text="用户不存在")
return {'user': user}
async def update_user(request):
user_id = request.match_info.get('id')
data = await request.post()
# 更新用户信息
user = await User.get(id=user_id)
user.username = data['username']
user.email = data['email']
await user.save()
return web.HTTPFound('/')
async def delete_user(request):
user_id = request.match_info.get('id')
# 删除用户
user = await User.get(id=user_id)
await user.delete()
return web.HTTPFound('/')
在 routes.py 中定义路由:
from views import index, add_user, get_user, update_user, delete_user
def setup_routes(app):
app.router.add_get('/', index)
app.router.add_post('/add_user', add_user)
app.router.add_get('/user/{id}', get_user)
app.router.add_post('/user/{id}/update', update_user)
app.router.add_post('/user/{id}/delete', delete_user)
创建模板
在 templates/index.html 中定义一个简单的模板:
<!DOCTYPE html>
<html>
<head>
<title>用户管理</title>
<link rel="stylesheet" href="/static/css/style.css">
<script src="/static/js/script.js"></script>
</head>
<body>
<h1>用户列表</h1>
<ul>
{% for user in users %}
<li>{{ user.username }} ({{ user.email }})</li>
{% endfor %}
</ul>
{{title}}
<h2>添加新用户</h2>
<form action="/add_user" method="post">
<div>
<label for="username">用户名:</label>
<input type="text" id="username" name="username" required>
</div>
<div>
<label for="email">邮箱:</label>
<input type="email" id="email" name="email" required>
</div>
<button type="submit">添加</button>
</form>
<script src="{{ static('js/script.js') }}"></script>
</body>
</html>
主应用入口
在 main.py 中创建主应用:
# main.py 修改版,添加端口配置
import aiohttp_jinja2
import jinja2
import argparse, os
from aiohttp import web
from tortoise.contrib.aiohttp import register_tortoise
from routes import setup_routes
async def init_app():
app = web.Application()
# 获取当前文件的目录路径
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
# 设置Jinja2模板
aiohttp_jinja2.setup(
app,
loader=jinja2.FileSystemLoader(os.path.join(BASE_DIR, 'templates'))
)
# 设置静态文件根URL
app[aiohttp_jinja2.static_root_key] = '/static'
# 设置静态文件
app.router.add_static('/static/',
path=os.path.join(BASE_DIR, 'static'),
name='static')
# 设置路由
setup_routes(app)
# 设置Tortoise ORM
register_tortoise(
app,
db_url="sqlite://db.sqlite3",
modules={"models": ["models"]},
generate_schemas=True
)
return app
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Run the web application")
parser.add_argument('--host', type=str, default='127.0.0.1', help='Host to run the app on')
parser.add_argument('--port', type=int, default=8000, help='Port to run the app on')
args = parser.parse_args()
web.run_app(init_app(), host=args.host, port=args.port)
添加一些基本的样式
在 static/css/style.css 中:
body {
font-family: Arial, sans-serif;
max-width: 800px;
margin: 0 auto;
padding: 20px;
}
form div {
margin-bottom: 10px;
}
input {
padding: 5px;
width: 300px;
}
button {
padding: 8px 16px;
background-color: #4CAF50;
color: white;
border: none;
cursor: pointer;
}
运行应用
python main.py
添加数据库迁移支持
对于更复杂的应用,推荐使用 Tortoise ORM 的迁移工具 aerich:
pip install aerich
然后,创建一个 config.py 文件来存储 Tortoise ORM 配置:
# config.py
TORTOISE_ORM = {
"connections": {
"default": "sqlite://db.sqlite3",
},
"apps": {
"models": {
"models": ["models", "aerich.models"],
"default_connection": "default",
},
},
"use_tz": False,
"timezone": "Asia/Shanghai"
}
接着初始化 aerich 并创建迁移:
# 初始化 aerich
aerich init -t config.TORTOISE_ORM
# 创建第一个迁移
aerich init-db
# 之后当模型变更时创建迁移
aerich migrate --name add_new_field
# 应用迁移
aerich upgrade
基本的应用程序提供了:
异步数据库访问使用 Tortoise ORM 使用 aiohttp 的 web 服务器 带有 Jinja2 模板的前端界面 简单的用户管理功能
你可以从这个基础上继续扩展,添加更多功能,如用户认证、更复杂的表单处理、API端点等。需要注意的是,所有的数据库操作都应该使用 await 关键字,以确保异步操作的正确执行。
文档信息
版权声明:可自由转载(请注明转载出处)-非商用-非衍生
发表时间:2025年3月1日 19:26