V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
prasanta
V2EX  ›  Python

基于配置的 API 接口写法设计讨论

  •  
  •   prasanta · 2017-06-19 15:13:08 +08:00 · 2551 次点击
    这是一个创建于 2493 天前的主题,其中的信息可能已经有所发展或是发生改变。

    现在市面上的开源框架, 不管是 tornado, django 或者 flask. 写起 API 总感觉没有 Nodejs 中的 hapijs 框架爽, 根据 hapijs 的设计原理, 我设想了下面的写法. 大家一起来讨论. 基于配置的方法去写接口感觉真的很舒适. 部分代码如下. (框架还没有, 只是设想. )

    app.js

    from api import *
    from .apis.post import post
    from .apis.user import user
    from .plugins.my_plugin import MyPlugin
    
    app = App()
    
    app.plugin(MyPlugin)
    app.plugin(AuthorizationPlugin('jwt'))
    
    app.publish(user)
    app.publish(post)
    
    app.start(port=3000)
    

    user.js

    from api import *
    from .services.user import UserService
    
    user = BluePrint()
    user.role('admin')
    
    
    @user.cache({
        'expires_in': 30 * 1000,
        'privacy': 'private'
    })
    @user.query({
        'name': Field().string()
    })
    @user.role('all')
    @user.get('/')
    def list(self, request):
        users = UserService.list(**request.query)
        return Response(users)
    
    
    @user.cache({
        'expires_in': 30 * 1000,
        'privacy': 'private'
    })
    @user.params({
        'id': Field().string()
    })
    @user.role('login_user')
    @user.get('/{id}')
    def retrieve(self, request):
        user = UserService.retrieve(id=request.params[id])
        return Response(user)
    
    
    @user.payload({
        'name': Field().string()
    })
    @user.role('admin')
    @user.post('/')
    def create(self, request):
        user = UserService.create(request.payload)
        return Response(user)
    
    
    @user.payload({
        'name': Field().string()
    })
    @user.params({
        'id': Field().string()
    })
    @user.role('admin')
    @user.patch('/{id}')
    def update(self, request):
        user = UserService.update(id=request.params[id], payload=request.payload)
        return Response(user)
    
    
    @user.payload({
        'name': Field().string()
    })
    @user.params({
        'id': Field().string()
    })
    @user.role('admin')
    @user.put('/{id}/name')
    def replace_name(self, request):
        user = UserService.update(id=request.params[id], payload=request.payload)
        return Response(user)
    
    
    8 条回复    2017-06-30 21:35:43 +08:00
    guyskk
        1
    guyskk  
       2017-06-19 20:13:46 +08:00 via Android
    Flask 稍微封装一下也可以写出这种效果,待我回去截个图
    zjq426
        2
    zjq426  
       2017-06-20 09:31:25 +08:00
    araraloren
        3
    araraloren  
       2017-06-20 09:32:26 +08:00
    ~~ 看不懂,也没个注释 讲解,进来一脸懵逼
    guyskk
        4
    guyskk  
       2017-06-20 11:13:29 +08:00
    API 写法

    Flask 封装




    这样写还是比较方便的,不过不建议造新框架,生态很重要
    guyskk
        5
    guyskk  
       2017-06-20 11:22:03 +08:00
    doc_view 里面我用模板生成了 .apib (API Blueprint https://apiblueprint.org/) 格式的文档。
    这些代码没从项目里抽取出来,要做成通用的框架或插件要考虑很多使用场景的问题。我这里约定 全部 POST,全部 JSON,所以省了很多事。
    guyskk
        6
    guyskk  
       2017-06-20 11:29:00 +08:00
    文档效果
    RaymondLiu
        7
    RaymondLiu  
       2017-06-30 21:19:46 +08:00 via iPhone
    @guyskk flask-restful 自带函数验证
    guyskk
        8
    guyskk  
       2017-06-30 21:35:43 +08:00 via Android
    @RaymondLiu 你指的是 RequestParser 吗,感觉有点繁琐,另外它不方便生成文档
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   2697 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 45ms · UTC 15:49 · PVG 23:49 · LAX 08:49 · JFK 11:49
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.