对Python REST(Web服务)框架的建议?[关闭]


321

在服务器端使用这些基于Python的不同REST框架的建议列表中是否可以编写自己的RESTful API?最好有优点和缺点。

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


Answers:


192

设计RESTful API时要注意的一点是GET和POST的合并,就好像它们是同一件事一样。使用Django基于函数的视图CherryPy的默认分派器很容易犯此错误,尽管这两个框架现在都提供了解决此问题的方法(分别基于类的视图MethodDispatcher)。

HTTP谓词在REST 中非常重要,除非对此特别小心,否则最终会陷入REST反模式

一些正确的框架是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标头)+分配给正确的呈现函数(或模板)的操作是整齐,透明的。

$ 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 and Bottle框架的信息。提出问题时,两者都不存在。


12
这是不正确的,Django完全支持识别POST与GET并将视图限制为仅某些方法。
aehlke

20
我的意思是,默认情况下,Django将POST和GET视为同一对象,这在您执行RESTful服务时非常不便,因为它会强制您执行以下操作:if request.method =='GET':do_something() ELIF request.method == 'POST':do_something_else的()web.py不存在这样的问题
马丁布莱什

19
@Wahnfrieden:如果Django中有本机支持来分别处理不同的HTTP动词(通过“本机”,我的意思是不需要“ if request.method == X”),请您指出一些文档吗?
马丁·布莱奇

3
POST和GET的合并不适用于Django的基于类的视图(在1.3中添加),但是我认为对于早期版本有效。
ncoghlan,2011年

1
关于CherryPy,答案不正确。来自Docs:“ REST(代表性状态转移)是一种非常适合在CherryPy中实施的体系结构样式。” - docs.cherrypy.org/dev/progguide/REST.html
德里克·利兹


23

我们正在将Django用于RESTful Web服务。

请注意,开箱即用的Django没有满足我们需求的足够细粒度的身份验证。我们使用了Django-REST接口,它帮了很多忙。[我们已经推出了自己的产品,因为我们进行了太多扩展,已经成为维护的噩梦。]

我们有两种URL:实现面向人的HTML页面的“ html” URL和实现面向Web服务的处理的“ json” URL。我们的视图功能通常看起来像这样。

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,因此请使其成为可调用类的一部分,或者在有帮助的情况下编写装饰器。


2
d的可怕重复= someUsefulThing ...甚至Django的人也建议DRY。
temoto

5
@temoto:如果y = someUsefulThing(...)是“糟糕的重复”,那么对所有函数和方法的所有引用都是“糟糕的”。我不明白如何避免多次引用一个函数。
S.Lott

5
@temoto:“当您需要更改传递给someUsefulThing的参数时,有可能在所有调用中都忘记这样做了”?什么?那个“糟糕”如何?这是多次引用一个函数的琐碎结果。我无法理解您在说什么,以及函数引用是“可怕的”,因为它不可避免。
S.Lott

4
请参阅已接受的答案。结果表达式{'message':'Hello,'+ name +'!'}对于所有演示文稿只编写一次。
temoto

3
您的htmlView和jsonView函数为相同的数据提供不同的表示形式,对吧?所以someUsefulThing(request, object_id)是一个数据检索表达式。现在,您在程序中的不同点有了两个相同表达式的副本。在接受的答案中,数据表达式只写入一次。someUsefulThing用一个长字符串替换您的呼叫,例如,paginate(request, Post.objects.filter(deleted=False, owner=request.user).order_by('comment_count'))然后看一下代码。我希望它能说明我的观点。
temoto


8

我真的很喜欢CherryPy。这是一个宁静的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在您的Web浏览器中。


35
那是一个很好的例子,但是没有任何RESTful的。
aehlke

3
@Wahnfrieden:您能通过阐明为什么您认为上述内容不是RESTful来帮助我们其他人吗?从我的角度来看,它看起来像是REST的经典示例,并且似乎没有违反RESTful系统的任何规则或约束。
lilbyrdie

42
简单来说,上面的CherryPy示例正在做的是将方法公开为“ HTTP可调用”远程过程。那就是RPC。它完全以“动词”为导向。RESTful体系结构专注于服务器管理的资源,然后在这些资源上提供非常有限的一组操作:具体地说,就是POST(创建),GET(读取),PUT(更新)和DELETE(删除)。这些资源的操纵,特别是通过PUT 改变其状态,是“东西发生”的关键途径。
verveguy



8

我看不出有任何理由使用Django来公开REST api,有更轻便,更灵活的解决方案。Django将很多其他东西带到了表中,这些东西并非总是需要的。如果您只想将某些代码公开为REST服务,则可以肯定不需要。

我的个人经验是,一旦有了一个千篇一律的框架,您就会开始使用它的ORM,其插件等,只是因为它很容易,而且在任何时候您都最终没有依赖关系这很难摆脱。

选择一个Web框架是一个艰难的决定,并且我会避免为了展示REST api而选择一个完整的堆栈解决方案。

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

话虽如此,CherryPy看起来也非常不错,但是看起来比REST更像RPC。

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



6

在2010年,Pylons和repoze.bfg社区“联合起来”创建了Pyramid,这是一个基于repoze.bfg的网络框架。它保留了其父框架的理念,并且可以用于RESTful服务。值得一看。


使用Pyramid,您可以使用Cornice,它提供了用于构建和记录REST Web服务的有用帮助器。
加尔文(Calvin)


5

似乎所有种类的python Web框架现在都可以实现RESTful接口。

对于Django,除了好吃的东西和活塞,django-rest-framework是一个很有前途的值得一提的东西。我已经顺利地迁移了我的一个项目。

Django REST框架是适用于Django的轻量级REST框架,旨在简化构建相互连接,自描述的RESTful Web 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/


2
特别是可浏览的界面在开发时节省了大量时间!还有许多其他优点,因此每个人都可以开始实施休息。我从开始开始,但是完全转向django-rest-framework
michel.iamit 2012年

3

我不是python世界的专家,但是我一直在使用django,它是一个出色的Web框架,可用于创建一个宁静的框架。




0

我强烈推荐TurboGears或Bottle:

TurboGears:

  • 不如django冗长
  • 更灵活,更少HTML
  • 但是:不太有名

瓶子:

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.