Paramètres de requête URL Tornado

J'ai joué avec Tornado, et j'ai écrit du code qui ne semble pas très agréable.

J'écris une application pour stocker des recettes à titre d'exemple. Ce sont mes gestionnaires:

handlers = [
    (r"/recipes/", RecipeHandler),
    (r"/recipes", RecipeSearchHandler), #so query params can be used to search
]

Cela m'a conduit à écrire ceci:

class RecipeHandler(RequestHandler):      
    def get(self):
        self.render('recipes/index.html')

class RecipeSearchHandler(RequestHandler):    
    def get(self):
        try:
            name = self.get_argument('name', True)
            self.write(name)
        # will do some searching
        except AssertionError:
            self.write("no params")
            # will probably redirect to /recipes/

Existe-t-il une meilleure façon d'aborder ces URL sans essayer/sauf? Je voudrais / recipes et / recipes / montrer la même chose, alors que / recipes?name = quelque chose ferait une recherche, et idéalement être un gestionnaire différent.

29
demandé sur colinjwebb 2012-05-23 23:21:51

4 réponses

Il existe un meilleur moyen pour les requêtes GET. Il y a une démo dans la source tornado sur github ici

# url handler
handlers = [(r"/entry/([^/]+)", EntryHandler),]

class EntryHandler(BaseHandler):
    def get(self, slug):
        entry = self.db.get("SELECT * FROM entries WHERE slug = %s", slug)
        if not entry: raise tornado.web.HTTPError(404)
        self.render("entry.html", entry=entry)

Tout "texte" correspondant à l'expression régulière sera passé à la méthode get de EntryHandler en tant qu'argument slug. Si l'url ne correspond à aucun gestionnaire, l'Utilisateur recevra une erreur 404.

Si vous souhaitez fournir une autre solution de secours, vous pouvez rendre le paramètre facultatif

(r"/entry/([^/]*)", EntryHandler),

class EntryHandler(BaseHandler):
    def get(self, slug=None):
        pass

Mise à Jour:

+1 pour le lien. Cependant ce n' Le modèle D'URL s'étend pour inclure plus de paramètres si je voulais rechercher comme ceci... /recettes?ingrédients = poulet & style = indien-colinjameswebb

Oui.

handlers = [
     (r'/(\d{4})/(\d{2})/(\d{2})/([a-zA-Z\-0-9\.:,_]+)/?', DetailHandler)
]

class DetailHandler(BaseHandler):
    def get(self, year, month, day, slug):
        pass
37
répondu mfussenegger 2014-01-16 17:20:53

get_argument vous permet de fournir une valeur par défaut:

details=self.get_argument("details", None, True)

S'il est fourni, aucune exception ne se produira si l'argument n'est pas fourni

32
répondu Casebash 2012-12-18 04:01:00

Tornado a également une fonction get_arguments. Il renvoie une liste d'arguments avec le nom donné. S'il n'est pas présent, il renvoie une liste vide ( [] ). Je l'ai trouvé plus propre de cette façon de désinfecter vos entrées de service web au lieu de try..catch blocs.

Exemple:
Supposons que j'ai un gestionnaire D'URL suivant:

(r"/recipe",GetRecipe)

Et le gestionnaire de requêtes:

class GetRecipe(RequestHandler):
    def get(self):
        recipe_id = self.get_arguments("rid")
        if recipe_id == []:
            # Handle me
            self.set_status(400)
            return self.finish("Invalid recipe id")
        self.write({"recipe_id":self.get_argument("rid")})


recipe_id liste organisera également la valeur, mais j'ai trouvé self.get_argument utilisation pratique de cette façon.

Maintenant, pour la résultats:

curl "http://localhost:8890/recipe" -v

*   Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 8890 (#0)
> GET /recipe HTTP/1.1
> User-Agent: curl/7.35.0
> Host: localhost:8890
> Accept: */*
> 
< HTTP/1.1 400 Bad Request
< Content-Length: 17
< Content-Type: text/html; charset=UTF-8
* Server TornadoServer/1.1.1 is not blacklisted
< Server: TornadoServer/1.1.1
< 
* Connection #0 to host localhost left intact
Invalid recipe id

curl "http://localhost:8890/recipe?rid=230" -v
*   Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 8890 (#0)
> GET /recipe?rid=230 HTTP/1.1
> User-Agent: curl/7.35.0
> Host: localhost:8890
> Accept: */*
> 
< HTTP/1.1 200 OK
< Content-Length: 20
< Etag: "d69ecb9086a20160178ade6b13eb0b3959aa13c6"
< Content-Type: text/javascript; charset=UTF-8
* Server TornadoServer/1.1.1 is not blacklisted
< Server: TornadoServer/1.1.1
< 
* Connection #0 to host localhost left intact
{"recipe_id": "230"}

9
répondu Aravindh 2015-12-23 08:57:54

Si vous souhaitez utiliser une approche plus dynamique pour le filtrage (au lieu d'une URL codée en dur), vous pouvez obtenir tous les paramètres/arguments d'URL passés en utilisant self.request.arguments dans le gestionnaire de requête.

class ApiHandler(RequestHandler):
    def get(self, path):
        filters = self.request.arguments
        for k,v in filters.items():
            # Do filtering etc...

Voir http://www.tornadoweb.org/en/stable/httputil.html#tornado.httputil.HTTPServerRequest.arguments

3
répondu frmdstryr 2017-02-09 14:21:18