ข้อเสนอแนะของ Python REST (บริการบนเว็บ) [ปิด]


321

มีรายการแนะนำบางส่วนของกรอบงาน REST แบบ Python ที่แตกต่างกันสำหรับใช้บนเซิร์ฟเวอร์เพื่อเขียน RESTful API ของคุณเองหรือไม่? โดยเฉพาะอย่างยิ่งกับข้อดีและข้อเสีย

โปรดเพิ่มคำแนะนำได้ที่นี่ :)


ต่อไปนี้เป็นบทแนะนำที่ดีเกี่ยวกับการใช้ web.py dreamsyssoft.com/blog/blog.php?/archives/…
Triton Man

คำตอบ:


192

สิ่งที่ต้องระวังในการออกแบบ RESTful API คือการรวม GET และ POST ราวกับว่ามันเป็นสิ่งเดียวกัน เป็นเรื่องง่ายที่จะทำผิดพลาดด้วยมุมมองที่อิงกับฟังก์ชั่นของDjangoและโปรแกรมมอบหมายงานเริ่มต้นของCherryPyแม้ว่ากรอบงานทั้งสองจะให้วิธีแก้ไขปัญหานี้ ( มุมมองระดับคลาสและMethodDispatcherตามลำดับ)

ใช้ HTTP คำกริยามีความสำคัญมากในส่วนที่เหลือและถ้าคุณระมัดระวังเป็นอย่างมากเกี่ยวกับเรื่องนี้คุณจะจบลงตกอยู่ในส่วนที่เหลือต่อต้านรูปแบบ

กรอบบางอย่างที่จะได้รับมันขวาweb.py , ขวดและขวด เมื่อรวมกับไลบรารีmimerender (การเปิดเผยอย่างสมบูรณ์: ฉันเขียนไว้) พวกเขาอนุญาตให้คุณเขียนเว็บเซอร์ RESTful ที่ดี:

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()

ตรรกะของบริการถูกนำไปใช้เพียงครั้งเดียวและการเลือกการนำเสนอที่ถูกต้อง (ยอมรับส่วนหัว) + ส่งไปยังฟังก์ชั่นการเรนเดอร์ที่เหมาะสม (หรือเทมเพลต) จะกระทำอย่างเป็นระเบียบเรียบร้อยและโปร่งใส

$ 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!

อัปเดต (เมษายน 2555) : เพิ่มข้อมูลเกี่ยวกับมุมมองระดับพื้นฐานของ Django, CherryPy's MethodDispatcher และกรอบขวดและขวด ไม่มีอยู่เมื่อถามคำถาม


12
สิ่งนี้ไม่ถูกต้อง Django ได้รับการสนับสนุนอย่างเต็มที่สำหรับการจดจำ POST vs GET และ จำกัด มุมมองเฉพาะวิธีการบางอย่างเท่านั้น
aehlke

20
ฉันหมายความว่าโดยค่าเริ่มต้น Django ปฏิบัติต่อ POST และ GET ราวกับว่ามันเป็นสิ่งเดียวกันซึ่งไม่สะดวกมากเมื่อคุณกำลังทำบริการ RESTful เพราะบังคับให้คุณทำ: ถ้า request.method == 'GET': do_something () elif request.method == 'โพสต์': do_something_else () web.py ไม่ได้ว่าปัญหา
มาร์ติน Blech

19
@Wahnfrieden: หากมีการสนับสนุนแบบดั้งเดิมใน Django สำหรับการจัดการคำกริยา HTTP ที่แตกต่างกัน (โดย "native" ฉันหมายถึงไม่จำเป็นต้องใช้ "ถ้า request.method == X") คุณช่วยชี้ฉันไปที่เอกสารบางส่วนได้หรือไม่?
มาร์ติน Blech

3
การรวมโพสต์และ GET ใช้ไม่ได้กับมุมมองแบบอิงคลาสของ Django (เพิ่มใน 1.3) แต่ฉันเชื่อว่าใช้ได้สำหรับรุ่นก่อนหน้า
ncoghlan

1
คำตอบไม่ถูกต้องเกี่ยวกับ CherryPy จากเอกสาร: "REST (Representational State Transfer) เป็นรูปแบบสถาปัตยกรรมที่เหมาะสมกับการนำไปใช้ใน CherryPy" - docs.cherrypy.org/dev/progguide/REST.html
Derek Litz

70

แปลกใจไม่มีใครกล่าวถึงขวด

from flask import Flask
app = Flask(__name__)

@app.route("/")
def hello():
    return "Hello World!"

if __name__ == "__main__":
    app.run()

7
กระติกน้ำก็ไม่ออกมีเมื่อคำถามที่ถูกถาม ...
มาร์ติน Blech

2
Flask ไม่ทำงานกับ Python 3.x
bitek

3
Flask.dev รองรับ Python 3
Sean Vieira

2
Flask รองรับ Python 3.3หรือสูงกว่า
mb21

3
noob ที่นี่นี่เป็นวิธีที่สงบหรือไม่
avi

23

เรากำลังใช้Djangoสำหรับบริการบนเว็บที่สงบ

โปรดทราบว่า - ออกจากกล่อง - Django ไม่มีการรับรองความถูกต้องอย่างละเอียดสำหรับความต้องการของเรา เราใช้ส่วนต่อประสาน Django-RESTซึ่งช่วยได้มาก [เรารีดมาตั้งแต่เราเองเพราะเราทำส่วนขยายมากมายจนกลายเป็นฝันร้ายในการบำรุงรักษา]

เรามี URL สองประเภท ได้แก่ : "html" URL ที่ใช้หน้า HTML ที่มุ่งเน้นมนุษย์และ URL "json" ซึ่งใช้การประมวลผลเชิงบริการเว็บ ฟังก์ชันมุมมองของเรามักจะมีลักษณะเช่นนี้

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 ดังนั้นให้พวกมันเป็นส่วนหนึ่งของคลาส callable หรือเขียนมัณฑนากรถ้ามันช่วยได้


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

11

ดูวิกิพีเดียPython Web Frameworks

คุณอาจไม่ต้องการเฟรมเวิร์กสแต็กเต็มรูปแบบแต่รายการที่เหลือยังคงค่อนข้างยาว


8

ผมชอบCherryPy นี่คือตัวอย่างของการบริการเว็บสงบ:

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; นี่เป็นตัวอย่างการทำงานที่สมบูรณ์ซึ่งสามารถเข้าใจได้แม้กับคนที่ไม่ทราบกรอบ หากคุณเรียกใช้รหัสนี้คุณจะเห็นผลลัพธ์ในเว็บเบราว์เซอร์ของคุณทันที เช่นไปที่http: // localhost: 8080 / celc_to_fahr? degrees = 50จะแสดง122.0ในเว็บเบราว์เซอร์ของคุณ


35
นั่นเป็นตัวอย่างที่ดี แต่ไม่มีอะไรเหลือเฟือเกี่ยวกับเรื่องนี้
aehlke

3
@ Wahnfrieden: คุณช่วยพวกเราที่เหลือด้วยการชี้แจงว่าทำไมคุณไม่คิดว่าข้างต้นนั้นสงบแล้ว? จากมุมมองของฉันดูเหมือนว่าเป็นตัวอย่างคลาสสิกของ REST และดูเหมือนจะไม่ทำลายกฎหรือข้อ จำกัด ใด ๆ ของระบบ RESTful
lilbyrdie

42
ในแง่ง่ายๆสิ่งที่ CherryPy ทำตัวอย่างข้างต้นคือการเปิดเผยวิธีการเป็นกระบวนการระยะไกล "HTTP callable" นั่นคือ RPC มันเป็นคำกริยาที่มุ่งเน้นทั้งหมด สถาปัตยกรรมที่สงบเงียบมุ่งเน้นไปที่ทรัพยากรที่จัดการโดยเซิร์ฟเวอร์จากนั้นนำเสนอชุดการดำเนินการที่จำกัดอย่างมากสำหรับทรัพยากรเหล่านั้น: โดยเฉพาะ POST (สร้าง), GET (อ่าน), PUT (อัพเดต) และลบ (ลบ) การจัดการทรัพยากรเหล่านี้โดยเฉพาะอย่างยิ่งการเปลี่ยนสถานะของพวกเขาผ่านทาง PUT เป็นเส้นทางที่สำคัญโดยที่ "สิ่งที่เกิดขึ้น"
verveguy

2
คุณสามารถเขียน RESTfull API ได้มากขึ้นโดยใช้ CherryPy docs.cherrypy.org/stable/progguide/REST.html
Radian


8

ฉันไม่เห็นเหตุผลใด ๆ ที่จะใช้ Django เพื่อเปิดเผย REST api มีโซลูชันที่เบาและยืดหยุ่นกว่า Django นำของอื่น ๆ มาวางบนโต๊ะซึ่งไม่จำเป็นเสมอไป แน่นอนว่าไม่จำเป็นหากคุณต้องการเปิดเผยรหัสบางส่วนเป็นบริการ REST

ประสบการณ์ส่วนตัวของฉัน fwiw คือเมื่อคุณมีกรอบขนาดเดียวที่เหมาะกับทุกคนคุณจะเริ่มใช้ ORM ปลั๊กอินของมันและอื่น ๆ เพียงเพราะมันง่ายและในเวลาไม่นานที่คุณต้องพึ่งพา มันยากมากที่จะกำจัด

การเลือกเฟรมเวิร์กของเว็บเป็นการตัดสินใจที่ยากลำบากและฉันจะหลีกเลี่ยงการเลือกโซลูชันสแต็กเต็มรูปแบบเพื่อเปิดเผย REST api

ตอนนี้ถ้าคุณต้องการ / ต้องการใช้ Django จริงๆแล้ว Piston เป็นเฟรมเวิร์ค REST ที่ดีสำหรับแอพ django

ที่ถูกกล่าวว่า CherryPy ดูดีเช่นกัน แต่ดูเหมือน RPC มากกว่า REST

ดูตัวอย่าง (ฉันไม่เคยใช้) อาจจะเป็น web.py ที่ดีที่สุดและสะอาดที่สุดหากคุณต้องการ REST



6

ในปี 2010 ชุมชน Pylons และ repoze.bfg "เข้าร่วมกับกองกำลัง" เพื่อสร้างพีระมิดซึ่งเป็นเฟรมเวิร์กเว็บที่อิงกับ repoze.bfg เป็นส่วนใหญ่ จะยังคงปรัชญากรอบพ่อแม่ของตนและสามารถนำมาใช้สำหรับบริการสงบ มันคุ้มค่าที่จะดู


ด้วย Pyramid คุณสามารถใช้ประโยชน์ของCorniceซึ่งให้ผู้ช่วยเหลือที่มีประโยชน์สำหรับการสร้างและจัดทำเอกสารบริการเว็บ REST
Calvin

5

Pistonเป็นเฟรมเวิร์กที่มีความยืดหยุ่นสูงสำหรับการใช้ RESTful APIs สำหรับแอ็พพลิเคชัน Django


5

ดูเหมือนว่ากรอบงานเว็บหลามทุกประเภทสามารถนำอินเตอร์เฟส RESTful ไปใช้ได้ทันที

สำหรับ Django นอกเหนือจาก Deliciouspie และลูกสูบแล้ว django-rest-framework เป็นสิ่งที่ควรค่าแก่การพูดถึง ฉันได้โยกย้ายหนึ่งในโครงการของฉันไปอย่างราบรื่น

Django REST framework เป็นเฟรมเวิร์ค REST ที่มีน้ำหนักเบาสำหรับ Django ซึ่งมีจุดประสงค์เพื่อให้ง่ายต่อการสร้าง 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 เอกสารอธิบายตนเอง (เช่น webservice สบู่ตาม) และแม้กระทั่ง sandbox เพื่อทดสอบเล็กน้อย สะดวกสบายมาก ๆ

ลิงค์: http://django-rest-framework.org/


2
โดยเฉพาะอย่างยิ่งส่วนต่อประสานที่สามารถเรียกดูได้ช่วยประหยัดเวลาได้มากในขณะที่กำลังพัฒนา! ข้อดีอื่น ๆ อีกมากมายดังนั้นทุกคนที่เริ่มใช้งานส่วนที่เหลือควรดู ฉันเริ่มด้วย Deliciouspie แต่เปลี่ยนเป็น django-rest-framework อย่างสมบูรณ์
michel.iamit

3

ฉันไม่ได้เป็นผู้เชี่ยวชาญในโลกหลาม แต่ฉันใช้djangoซึ่งเป็นกรอบงานเว็บที่ยอดเยี่ยมและสามารถใช้เพื่อสร้างกรอบงานที่เงียบสงบ


3

web2pyรวมถึงการสนับสนุนการสร้าง RESTful API อย่างง่ายดายซึ่งอธิบายไว้ที่นี่และที่นี่ (วิดีโอ) โดยเฉพาะอย่างยิ่งดูที่parse_as_restช่วยให้คุณกำหนดรูปแบบ URL ที่ร้องขอแผนที่ args กับแบบสอบถามฐานข้อมูล; และsmart_queryซึ่งช่วยให้คุณสามารถส่งคำสั่งภาษาธรรมชาติโดยพลการใน URL


ลิงก์ที่กล่าวถึงไม่มีอีกต่อไป
milovanderlinden

ลิงค์ได้รับการอัพเดทแล้ว - ลองอีกครั้ง
แอนโทนี่

2

ฉันคุณกำลังใช้ Django แล้วคุณสามารถพิจารณาDjango-tastypieเป็นทางเลือกให้กับDjango ลูกสูบ มันเป็นเรื่องง่ายที่จะปรับแต่งไปยังแหล่งข้อมูลที่ไม่ใช่ออมกว่าลูกสูบและมีดีเอกสาร


0

ฉันขอแนะนำ TurboGears หรือขวด:

TurboGears:

  • verbose น้อยกว่า django
  • มีความยืดหยุ่นมากขึ้นและใช้ HTML น้อยลง
  • แต่: ชื่อเสียงน้อยกว่า

ขวด:

  • เร็วมาก
  • ง่ายมากที่จะเรียนรู้
  • แต่: เรียบง่ายและไม่เป็นผู้ใหญ่

0

เรากำลังทำงานบนเฟรมเวิร์กสำหรับบริการ REST ที่เข้มงวดลองดูhttp://prestans.googlecode.com

ในช่วงต้นอัลฟ่าในขณะนี้เรากำลังทดสอบกับ mod_wsgi และ AppEngine ของ Google

กำลังมองหาผู้ทดสอบและข้อเสนอแนะ ขอบคุณ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.