使用Tornado REST框架来构建用于访问用户的简单模型支持的API的快速示例
设置一个新项目:
.
├── handlers
│ └── user.py
├── models
│ └── user.py
├── routers
│ └── user.py
├── serializers
│ └── user.py
├── app.py
├── settings.py
使用Tornado REST框架时,必须告诉它所使用的设置。通过使用环境变量:TORNADO_SETTINGS_MODULE来执行此操作
TORNADO_SETTINGS_MODULE的值应采用Python路径语法,例如foo.settings。请注意,设置模块应位于Python导入搜索路径上。
$ export TORNADO_SETTINGS_MODULE=settings
将以下内容添加到您的settings.py中:
# settings.py
import os
BASE_DIR = os.path.dirname(__file__)
debug = True
secret_key = "******"
routers_path = os.path.join(BASE_DIR, "routers")
api_prefix = "/api"
trailing_slash = False
mysql_host = "127.0.0.1"
mysql_port = 3306
mysql_username = "root"
mysql_password = "******"
mysql_dbname = ""
创建一个可以使用的模型:
# models/user.py
from tornado_restful import models
class User(models.Model):
name = models.CharField(max_length=20, unique=True)
email = models.CharField(max_length=30, unique=True)
创建一个序列化器:
# serializers/user.py
from tornado_restful.models import db
from tornado_restful.serializers import Serializer, fields, validate
from models.user import User
class UserSerializer(Serializer):
id = fields.Int(dump_only=True)
name = fields.Str(
required=True,
validate=[
validate.Length(min=2, max=20),
validate.Regexp("^[a-zA-Z][a-zA-Z0-9_-]*$")
],
)
email = fields.Email(required=True, validate=validate.Length(max=30))
async def create(self, validated_data):
return await db.create(User, **validated_data)
async def update(self, instance, validated_data):
instance.email = validated_data.get("email", instance.email)
await db.update(instance)
return instance
class:
# handlers/user.py
from tornado_restful import status
from tornado_restful.exceptions import NotFoundError
from tornado_restful.handlers import APIHandler
from models.user import User
from serializers.user import UserSerializer
class UserHandler(APIHandler):
async def list(self):
limit, offset = self.paginate()
async with self.application.db.atomic():
users = await self.application.db.execute(
User.select().limit(limit).offset(offset)
)
total = await self.application.db.count(User.select())
serializer = UserSerializer(users, many=True)
self.set_status(status.HTTP_200_OK)
return self.finish({"total": total, "results": serializer.data})
async def retrieve(self, pk):
user = await self.get_object(pk)
serializer = UserSerializer(user)
self.set_status(status.HTTP_200_OK)
return self.finish(serializer.data)
async def create(self):
serializer = UserSerializer(data=self.request.data)
serializer.is_valid(raise_exception=True)
await serializer.save()
self.set_status(status.HTTP_201_CREATED)
return self.finish(serializer.data)
async def partial_update(self, pk):
user = await self.get_object(pk)
serializer = UserSerializer(user, self.request.data, partial=True)
serializer.is_valid(raise_exception=True)
await serializer.save()
self.set_status(status.HTTP_200_OK)
return self.finish(serializer.data)
async def destroy(self, pk):
user = await self.get_object(pk)
await self.application.db.delete(user)
self.set_status(status.HTTP_204_NO_CONTENT)
return self.finish()
async def get_object(self, pk):
try:
user = await self.application.db.get(User, name=pk)
except User.DoesNotExist:
raise NotFoundError
return user
Url:
# routers/user.py
from tornado_restful.routers import NestedRouter
from handlers.user import UserHandler
router = NestedRouter()
router.register(r"users", UserHandler)
为项目提供一个入口:
# app.py
import tornado.ioloop
import tornado.web
from tornado_restful.conf import settings
from tornado_restful.handlers import NotFoundHandler
from tornado_restful.models import db
from tornado_restful.shortcuts import get_routes
def runserver():
app = tornado.web.Application(
handlers=get_routes(),
debug=settings.debug,
default_handler_class=NotFoundHandler,
)
app.db = db
app.listen(8888)
tornado.ioloop.IOLoop.current().start()
if __name__ == "__main__":
runserver()
Serve:
python app.py