Recommandations du cadre Python REST (services Web)? [fermé]


321

Existe-t-il une liste de recommandations de différents frameworks REST basés sur Python à utiliser côté serveur pour écrire vos propres API RESTful? De préférence avec des avantages et des inconvénients.

N'hésitez pas à ajouter des recommandations ici. :)


Voici un bon tutoriel sur l'utilisation de web.py dreamsyssoft.com/blog/blog.php?/archives/…
Triton Man

Réponses:


192

Une chose à laquelle il faut faire attention lors de la conception d'une API RESTful est la fusion de GET et POST, comme si c'était la même chose. Il est facile de commettre cette erreur avec les vues basées sur les fonctions de Django et le répartiteur par défaut de CherryPy , bien que les deux frameworks fournissent désormais un moyen de contourner ce problème ( vues basées sur les classes et MethodDispatcher , respectivement).

Les verbes HTTP sont très importants dans REST, et à moins que vous ne soyez très prudent à ce sujet, vous finirez par tomber dans un anti-modèle REST .

Certains frameworks qui réussissent sont web.py , Flask et Bottle . Lorsqu'ils sont combinés avec la bibliothèque mimerender (divulgation complète: je l'ai écrite), ils vous permettent d'écrire de jolis services Web 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()

La logique du service n'est implémentée qu'une seule fois, et la sélection de représentation correcte (en-tête Accept) + la répartition vers la fonction de rendu appropriée (ou modèle) est effectuée de manière ordonnée et transparente.

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

Mise à jour (avril 2012) : ajout d'informations sur les vues basées sur les classes de Django, les frameworks MethodDispatcher et Flask and Bottle de CherryPy. Aucun n'existait à l'époque où la question a été posée.


12
C'est incorrect, Django a un support complet pour reconnaître POST vs GET et limiter les vues à seulement certaines méthodes.
aehlke

20
Je voulais dire que, par défaut, Django traite POST et GET comme s'ils étaient la même chose, ce qui est très gênant lorsque vous effectuez des services RESTful car cela vous oblige à faire: if request.method == 'GET': do_something () elif request.method == 'POST': do_something_else () web.py n'a pas ce problème
Martin Blech

19
@Wahnfrieden: S'il existe une prise en charge native dans Django pour gérer les différents verbes HTTP séparément (par "natif", je veux dire ne pas avoir besoin de "if request.method == X"), pourriez-vous me signaler une documentation?
Martin Blech

3
La fusion de POST et GET ne s'applique pas aux vues basées sur la classe de Django (ajoutées en 1.3), mais je crois que c'est valable pour les versions antérieures.
ncoghlan

1
La réponse est incorrecte à propos de CherryPy. De Docs: "REST (Representational State Transfer) est un style architectural bien adapté à l'implémentation dans CherryPy." - docs.cherrypy.org/dev/progguide/REST.html
Derek Litz

70

Surpris, personne n'a mentionné la fiole .

from flask import Flask
app = Flask(__name__)

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

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

7
Flask n'était pas là quand la question a été posée ...
Martin Blech

2
Flask ne fonctionne pas avec Python 3.x
bitek

3
Flask.dev prend désormais en charge Python 3
Sean Vieira

2
Flask prend en charge Python 3.3 ou supérieur.
mb21

3
noob ici, comment c'est un RESTful?
avi

23

Nous utilisons Django pour les services Web RESTful.

Notez que - hors de la boîte - Django n'avait pas d'authentification assez fine pour nos besoins. Nous avons utilisé l' interface Django-REST , ce qui a beaucoup aidé. [Nous avons depuis lancé la nôtre parce que nous avions fait tellement d'extensions que c'était devenu un cauchemar de maintenance.]

Nous avons deux types d'URL: les URL "html" qui implémentent les pages HTML orientées vers l'homme, et les URL "json" qui implémentent le traitement orienté services Web. Nos fonctions d'affichage ressemblent souvent à ceci.

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

Le fait étant que la fonctionnalité utile est prise en compte dans les deux présentations. La présentation JSON n'est généralement qu'un seul objet qui a été demandé. La présentation HTML comprend souvent toutes sortes d'aides à la navigation et d'autres indices contextuels qui aident les gens à être productifs.

Les jsonViewfonctions sont toutes très similaires, ce qui peut être un peu ennuyeux. Mais c'est Python, alors faites-les partie d'une classe appelable ou écrivez des décorateurs si cela vous aide.


2
Répétition affreuse de d = someUsefulThing ... Même les gars de Django suggèrent SEC.
temoto

5
@temoto: S'il y = someUsefulThing(...)s'agit d'une "répétition horrible", toutes les références à toutes les fonctions et méthodes sont "horribles". Je n'arrive pas à comprendre comment éviter de référencer une fonction plus d'une fois.
S.Lott

5
@temoto: "Lorsque vous devez modifier des arguments passés à someUsefulThing, il y a une chance que l'on oublie de le faire dans tous les appels"? Quoi? Comment est-ce "horrible"? C'est une conséquence triviale de référencer une fonction plus d'une fois. Je n'arrive pas à comprendre de quoi vous parlez et comment la référence de fonction est "horrible" car elle est incontournable.
S.Lott

4
Voir la réponse acceptée. L'expression de résultat {'message': 'Bonjour', '+ nom +'! '} Est écrite une fois pour toutes les présentations.
temoto

3
Vos fonctions htmlView et jsonView servent des représentations différentes pour les mêmes données, non? Il en someUsefulThing(request, object_id)va de même pour une expression de récupération de données. Vous avez maintenant deux copies de la même expression à différents points de votre programme. Dans la réponse acceptée, l'expression de données est écrite une fois. Remplacez votre someUsefulThingappel par une longue chaîne, comme paginate(request, Post.objects.filter(deleted=False, owner=request.user).order_by('comment_count'))et regardez le code. J'espère que cela illustrera mon propos.
temoto


8

J'aime vraiment CherryPy . Voici un exemple de service Web reposant:

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

Cela souligne ce que j'aime vraiment chez CherryPy; il s'agit d'un exemple complètement fonctionnel qui est très compréhensible même pour quelqu'un qui ne connaît pas le cadre. Si vous exécutez ce code, vous pouvez immédiatement voir les résultats dans votre navigateur Web; par exemple, visiter http: // localhost: 8080 / celc_to_fahr? degrés = 50 s'affichera 122.0dans votre navigateur Web.


35
C'est un bel exemple, mais il n'y a rien de reposant à ce sujet.
aehlke

3
@Wahnfrieden: Pourriez-vous nous aider en clarifiant pourquoi vous ne pensez pas que ce qui précède est RESTful? De mon point de vue, cela ressemble à un exemple classique de REST et ne semble enfreindre aucune des règles ou contraintes d'un système RESTful.
lilbyrdie

42
En termes simples, ce que fait l'exemple CherryPy ci-dessus est d'exposer des méthodes en tant que procédures distantes "appelables HTTP". C'est RPC. Il est entièrement orienté "verbe". Les architectures RESTful se concentrent sur les ressources gérées par un serveur et offrent ensuite un ensemble très limité d'opérations sur ces ressources: spécifiquement, POST (créer), GET (lire), PUT (mettre à jour) et DELETE (supprimer). La manipulation de ces ressources, en particulier la modification de leur état via PUT, est la voie clé par laquelle "des choses arrivent".
verveguy

2
Vous pouvez écrire plus d'API RESTfull à l'aide de CherryPy docs.cherrypy.org/stable/progguide/REST.html
Radian


8

Je ne vois aucune raison d'utiliser Django juste pour exposer une API REST, il existe des solutions plus légères et plus flexibles. Django apporte beaucoup d'autres choses à la table, qui ne sont pas toujours nécessaires. Bien sûr, pas nécessaire si vous souhaitez uniquement exposer du code en tant que service REST.

Mon expérience personnelle, fwiw, est qu'une fois que vous avez un cadre unique, vous commencerez à utiliser son ORM, ses plugins, etc. simplement parce que c'est facile, et en un rien de temps vous finirez par avoir une dépendance c'est très difficile à éliminer.

Le choix d'un framework web est une décision difficile, et j'éviterais de choisir une solution de pile complète juste pour exposer une api REST.

Maintenant, si vous avez vraiment besoin / voulez utiliser Django, alors Piston est un joli framework REST pour les applications django.

Cela étant dit, CherryPy a l'air vraiment bien aussi, mais semble plus RPC que REST.

En regardant les exemples (je ne l'ai jamais utilisé), web.py est probablement le meilleur et le plus propre si vous n'avez besoin que de REST.


6

Voici une discussion dans les documents CherryPy sur REST: http://docs.cherrypy.org/dev/progguide/REST.html

En particulier, il mentionne un répartiteur CherryPy intégré appelé MethodDispatcher, qui invoque des méthodes basées sur leurs identificateurs de verbe HTTP (GET, POST, etc ...).


6

En 2010, les communautés Pylons et repoze.bfg "ont uni leurs forces" pour créer Pyramid , un framework web basé principalement sur repoze.bfg. Il conserve les philosophies de ses cadres parents et peut être utilisé pour les services RESTful . Ça vaut le coup d'oeil.


Avec Pyramid, vous pouvez utiliser Cornice , qui fournit des aides utiles pour la création et la documentation des services Web REST.
Calvin


5

Il semble que toutes sortes de frameworks web python puissent implémenter des interfaces RESTful maintenant.

Pour Django, outre tastypie et piston, django-rest-framework est prometteur et mérite d'être mentionné. J'ai déjà fait migrer l'un de mes projets en douceur.

Le framework Django REST est un framework REST léger pour Django, qui vise à faciliter la création d'API Web RESTful bien connectées et auto-descriptives.

Exemple rapide:

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

Prenez l'exemple du site officiel, tous les codes ci-dessus fournissent une API, un document auto-expliqué (comme un service Web basé sur du savon) et même un bac à sable pour tester un peu. Très pratique.

Liens: http://django-rest-framework.org/


2
En particulier, l'interface navigable permet de gagner beaucoup de temps lors du développement! Beaucoup d'autres avantages, donc tout le monde qui commence la mise en œuvre du repos devrait y jeter un œil. J'ai commencé avec tastypie, mais je suis passé complètement à django-rest-framework
michel.iamit

3

Je ne suis pas un expert du monde python mais j'utilise django qui est un excellent framework web et peut être utilisé pour créer un framework reposant.


3

web2py inclut le support pour construire facilement des API RESTful, décrites ici et ici (vidéo). En particulier, regardez parse_as_rest, qui vous permet de définir des modèles d'URL qui mappent les arguments des requêtes aux requêtes de base de données; et smart_query, ce qui vous permet de passer des requêtes arbitraires en langage naturel dans l'URL.


Les liens mentionnés ne sont plus disponibles
milovanderlinden

Les liens ont été mis à jour - réessayez.
Anthony


0

Je recommande fortement TurboGears ou Bottle:

TurboGears:

  • moins verbeux que django
  • plus flexible, moins orienté HTML
  • mais: moins célèbre

Bouteille:

  • très vite
  • très facile à apprendre
  • mais: minimaliste et pas mature

0

Nous travaillons sur un cadre pour des services REST stricts, consultez http://prestans.googlecode.com

C'est au début d'Alpha en ce moment, nous testons contre mod_wsgi et AppEngine de Google.

Vous recherchez des testeurs et des commentaires. Merci.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.