【问题标题】:Recommendations of Python REST (web services) framework? [closed]Python REST(Web 服务)框架的推荐? [关闭]
【发布时间】:2010-10-17 08:43:48
【问题描述】:

是否有不同的基于 Python 的 REST 框架的建议列表,可用于在服务器端编写您自己的 RESTful API?最好各有优劣。

请随时在此处添加建议。 :)

【问题讨论】:

标签: python web-services rest frameworks


【解决方案1】:

我不是python世界的专家,但我一直在使用django,这是一个优秀的Web框架,可以用来创建一个restful框架。

【讨论】:

    【解决方案2】:

    参见Python Web Frameworks wiki。

    您可能不需要全栈框架,但剩下的列表仍然很长。

    【讨论】:

      【解决方案3】:

      我们将 Django 用于 RESTful Web 服务。

      请注意——开箱即用——Django 没有足够细粒度的身份验证来满足我们的需求。我们使用了Django-REST interface,这很有帮助。 [我们后来推出了自己的产品,因为我们做了很多扩展,以至于它已经成为维护的噩梦。]

      我们有两种 URL:“html” URL 实现面向人的 HTML 页面,“json” URL 实现面向 Web 服务的处理。我们的视图函数通常是这样的。

      def someUsefulThing( request, object_id ):
          # do some processing
          return { a dictionary with results }
      
      def htmlView( request, object_id ):
          d = someUsefulThing( request, object_id )
          render_to_response( 'template.html', d, ... )
      
      def jsonView( request, object_id ):
          d = someUsefulThing( request, object_id )
          data = serializers.serialize( 'json', d['object'], fields=EXPOSED_FIELDS )
          response = HttpResponse( data, status=200, content_type='application/json' )
          response['Location']= reverse( 'some.path.to.this.view', kwargs={...} )
          return response
      

      关键是有用的功能是从两个演示文稿中提取出来的。 JSON 表示通常只是请求的一个对象。 HTML 演示文稿通常包含各种导航帮助和其他有助于人们提高工作效率的上下文线索。

      jsonView 函数都非常相似,这可能有点烦人。但它是 Python,所以让它们成为可调用类的一部分或编写装饰器(如果有帮助)。

      【讨论】:

      • d = someUsefulThing 的可怕重复......即使是 Django 家伙也建议 DRY。
      • @temoto:如果y = someUsefulThing(...) 是“糟糕的重复”,那么对所有函数和方法的所有引用都是“糟糕的”。我不明白如何避免多次引用一个函数。
      • @temoto:“当您需要更改传递给 someUsefulThing 的参数时,有可能在所有调用中都忘记这样做”?什么?这有多“可怕”?这是多次引用函数的微不足道的结果。我无法理解你在说什么以及函数引用是如何“糟糕”的,因为它是不可避免的。
      • 查看接受的答案。结果表达式 {'message': 'Hello, ' + name + '!'} 为所有演示文稿编写一次。
      • 您的 htmlView 和 jsonView 函数为相同的数据提供不同的表示,对吧?所以someUsefulThing(request, object_id)是一个数据检索表达式。现在,您在程序的不同点有两个相同表达式的副本。在接受的答案中,数据表达式被写入一次。用长字符串替换您的 someUsefulThing 调用,例如 paginate(request, Post.objects.filter(deleted=False, owner=request.user).order_by('comment_count')) 并查看代码。我希望它能说明我的观点。
      【解决方案4】:

      我真的很喜欢CherryPy。下面是一个 RESTful Web 服务的示例:

      import cherrypy
      from cherrypy import expose
      
      class Converter:
          @expose
          def index(self):
              return "Hello World!"
      
          @expose
          def fahr_to_celc(self, degrees):
              temp = (float(degrees) - 32) * 5 / 9
              return "%.01f" % temp
      
          @expose
          def celc_to_fahr(self, degrees):
              temp = float(degrees) * 9 / 5 + 32
              return "%.01f" % temp
      
      cherrypy.quickstart(Converter())
      

      这强调了我真正喜欢 CherryPy 的地方;这是一个完全可行的示例,即使对于不了解该框架的人来说也很容易理解。如果您运行此代码,那么您可以立即在 Web 浏览器中看到结果;例如访问http://localhost:8080/celc_to_fahr?degrees=50 将在您的网络浏览器中显示122.0

      【讨论】:

      • 这是一个很好的例子,但它没有 RESTful 风格。
      • @Wahnfrieden:您能否通过澄清为什么您认为上述内容不是 RESTful 来帮助我们其他人?从我的角度来看,它看起来像是 REST 的经典示例,并且似乎没有违反 RESTful 系统的任何规则或约束。
      • 简单来说,上面的 CherryPy 示例所做的是将方法公开为“HTTP 可调用”远程过程。那是RPC。它完全是面向“动词”的。 RESTful 架构专注于由服务器管理的资源,然后对这些资源提供一组非常有限的操作:具体来说,POST(创建)、GET(读取)、PUT (更新)和 DELETE(删除)。对这些资源的操作,特别是通过 PUT 改变它们的状态,是“事情发生”的关键途径。
      • 您可以使用 CherryPy docs.cherrypy.org/stable/progguide/REST.html 编写更多 RESTfull API
      【解决方案5】:

      在设计 RESTful API 时需要注意的是 GET 和 POST 的混淆,就好像它们是同一个东西一样。使用Djangofunction-based viewsCherryPy 的默认调度程序很容易犯这个错误,尽管这两个框架现在都提供了解决这个问题的方法(分别为class-based viewsMethodDispatcher)。

      HTTP-verbs are very important 在 REST 中,除非您对此非常小心,否则您最终会陷入REST anti-pattern

      一些正确的框架是web.pyFlaskBottle。当与mimerender 库结合使用时(完全公开:我写的),它们允许您编写漂亮的 RESTful Web 服务:

      import web
      import json
      from mimerender import mimerender
      
      render_xml = lambda message: '<message>%s</message>'%message
      render_json = lambda **args: json.dumps(args)
      render_html = lambda message: '<html><body>%s</body></html>'%message
      render_txt = lambda message: message
      
      urls = (
          '/(.*)', 'greet'
      )
      app = web.application(urls, globals())
      
      class greet:
          @mimerender(
              default = 'html',
              html = render_html,
              xml  = render_xml,
              json = render_json,
              txt  = render_txt
          )
          def GET(self, name):
              if not name: 
                  name = 'world'
              return {'message': 'Hello, ' + name + '!'}
      
      if __name__ == "__main__":
          app.run()
      

      服务的逻辑只实现一次,正确的表示选择(Accept header)+派发到正确的渲染函数(或模板)以整洁、透明的方式完成。

      $ curl localhost:8080/x
      <html><body>Hello, x!</body></html>
      
      $ curl -H "Accept: application/html" localhost:8080/x
      <html><body>Hello, x!</body></html>
      
      $ curl -H "Accept: application/xml" localhost:8080/x
      <message>Hello, x!</message>
      
      $ curl -H "Accept: application/json" localhost:8080/x
      {'message':'Hello, x!'}
      
      $ curl -H "Accept: text/plain" localhost:8080/x
      Hello, x!
      

      更新(2012 年 4 月):添加了有关 Django 的基于类的视图、CherryPy 的 MethodDispatcher 以及 Flask 和 Bottle 框架的信息。提出问题时两者都不存在。

      【讨论】:

      • 这是不正确的,Django 完全支持识别 POST 与 GET 并将视图仅限于某些方法。
      • 我的意思是,默认情况下,Django 将 POST 和 GET 视为同一件事,这在您执行 RESTful 服务时非常不方便,因为它会强制您这样做:如果 request.method = = 'GET': do_something() elif request.method == 'POST': do_something_else() web.py 没有这个问题
      • @Wahnfrieden:如果 Django 中有原生支持分别处理不同的 HTTP 动词(“原生”我的意思是不需要“如果 request.method==X”),请指点我一些文件?
      • POST 和 GET 的合并不适用于 Django 的基于类的视图(在 1.3 中添加),但我相信对早期版本有效。
      • 关于 CherryPy 的答案不正确。来自 Docs:“REST(代表性状态转移)是一种非常适合在 CherryPy 中实现的架构风格。” - docs.cherrypy.org/dev/progguide/REST.html
      【解决方案6】:

      【讨论】:

        【解决方案7】:

        我强烈推荐 TurboGears 或 Bottle:

        涡轮齿轮:

        • 比 django 简洁
        • 更灵活,更少面向 HTML
        • 但是:不太出名

        瓶子:

        • 非常快
        • 非常容易学习
        • 但是:简约而不成熟

        【讨论】:

          【解决方案8】:

          这是 CherryPy 文档中关于 REST 的讨论:http://docs.cherrypy.org/dev/progguide/REST.html

          它特别提到了一个内置的 CherryPy 调度程序,称为 MethodDispatcher,它根据 HTTP 动词标识符(GET、POST 等)调用方法。

          【讨论】:

            【解决方案9】:

            Piston 是一个非常灵活的框架,用于为 Django 应用程序编写 RESTful API。

            【讨论】:

              【解决方案10】:

              很惊讶没有人提到flask

              from flask import Flask
              app = Flask(__name__)
              
              @app.route("/")
              def hello():
                  return "Hello World!"
              
              if __name__ == "__main__":
                  app.run()
              

              【讨论】:

              • 问这个问题时,Flask 不在...
              • Flask 不适用于 Python 3.x
              • Flask.dev 现在支持 Python 3
              • Flask supports Python 3.3 或更高版本。
              • 这里的菜鸟,这怎么是 RESTful?
              【解决方案11】:

              web2py 包括对轻松构建 RESTful API 的支持,描述了 herehere(视频)。特别是parse_as_rest,它允许您定义将请求参数映射到数据库查询的 URL 模式;和smart_query,它使您能够在 URL 中传递任意自然语言查询。

              【讨论】:

              • 上述链接已失效
              • 链接已更新 - 请重试。
              【解决方案12】:

              2010 年,Pylons 和 repoze.bfg 社区“联手”创建了Pyramid,这是一个主要基于 repoze.bfg 的 Web 框架。它保留了其父框架的理念,可用于RESTful services。值得一看。

              【讨论】:

              • 借助 Pyramid,您可以使用 Cornice,它为构建和记录 REST Web 服务提供了有用的帮助。
              【解决方案13】:

              我认为没有任何理由使用 Django 来公开一个 REST api,有更轻量级和更灵活的解决方案。 Django 提供了很多其他的东西,这些东西并不总是需要。如果您只想将某些代码公开为 REST 服务,则肯定不需要。

              我个人的经验是,一旦你有了一个万能的框架,你就会开始使用它的 ORM、它的插件等,因为它很简单,而且你很快就会结束有一个很难摆脱的依赖。

              选择 Web 框架是一个艰难的决定,我会避免仅仅为了公开 REST API 而选择全栈解决方案。

              现在,如果您真的需要/想要使用 Django,那么 Piston 是一个适用于 django 应用程序的不错的 REST 框架。

              话虽如此,CherryPy 看起来也很不错,但似乎比 REST 更像 RPC。

              查看示例(我从未使用过),如果您只需要 REST,web.py 可能是最好和最干净的。

              【讨论】:

                【解决方案14】:

                我们正在开发一个严格的 REST 服务框架,请查看 http://prestans.googlecode.com

                目前处于早期 Alpha 阶段,我们正在针对 mod_wsgi 和 Google 的 AppEngine 进行测试。

                寻找测试人员和反馈。谢谢。

                【讨论】:

                  【解决方案15】:

                  如果您使用的是 Django,那么您可以考虑将django-tastypie 作为django-piston 的替代品。它比活塞更容易调到非 ORM 数据源,并且有很好的documentation

                  【讨论】:

                    【解决方案16】:

                    现在看来各种python web框架都可以实现RESTful接口了。

                    对于 Django,除了美味的派和活塞,django-rest-framework 是一个值得一提的有前途的。我已经顺利迁移了我的一个项目。

                    Django REST framework 是 Django 的轻量级 REST 框架,它 旨在使构建连接良好、自我描述的 RESTful 变得容易 网络 API。

                    快速示例:

                    from django.conf.urls.defaults import patterns, url
                    from djangorestframework.resources import ModelResource
                    from djangorestframework.views import ListOrCreateModelView, InstanceModelView
                    from myapp.models import MyModel
                    
                    class MyResource(ModelResource):
                        model = MyModel
                    
                    urlpatterns = patterns('',
                        url(r'^$', ListOrCreateModelView.as_view(resource=MyResource)),
                        url(r'^(?P<pk>[^/]+)/$', InstanceModelView.as_view(resource=MyResource)),
                    )
                    

                    以官方网站为例,以上所有代码都提供了api,自我解释文档(如基于soap的webservice)甚至沙箱来测试一下。非常方便。

                    链接: http://django-rest-framework.org/

                    【讨论】:

                    • 特别是可浏览的界面在开发过程中节省了大量时间!还有很多其他的优点,所以大家开始rest实现应该看看。我一开始是从 sweetpie 开始的,但后来完全改用 django-rest-framework