Подтвердить что ты не робот

Параметры запроса URL-адреса Tornado

Я играл с Tornado, и я написал код, который выглядит не очень приятным.

Я пишу приложение для хранения рецептов в качестве примера. Это мои обработчики:

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

Это привело меня к написанию:

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/

Есть ли лучший способ приблизиться к этим URL-адресам без try/except? Мне бы хотелось /recipes and/recipes/показать ту же самую вещь, тогда как /recipes? Name = что-то будет делать поиск и в идеале быть другим обработчиком.

4b9b3361

Ответ 1

Существует лучший способ для запросов GET. Существует демо-версия в источнике торнадо на github здесь

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

Любой "текст", который соответствует регулярному выражению, будет передан методу getHandler get как аргумент slug. Если URL-адрес не соответствует любому обработчику, пользователь получит ошибку 404.

Если вы хотите предоставить другой резерв, вы можете сделать параметр необязательным

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

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

Update:

+1 для ссылки. Однако этот шаблон URL распространяется на большее количество параметров, если я хотел бы выполнить поиск именно так... /рецепты? ингредиент = курица & style = indian - colinjameswebb

Да, да.

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

Ответ 2

get_argument позволяет указать значение по умолчанию:

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

Если это предусмотрено, то исключение не произойдет, если аргумент не указан

Ответ 3

Торнадо также имеет функцию get_arguments. Он возвращает список аргументов с заданным именем. Если нет, он возвращает пустой список ( [] ). Я счел это более чистым, чтобы очистить ваши входы веб-сервисов вместо блоков try..catch.

<Б > Пример:
Предположим, у меня есть следующий обработчик URL:

(r"/recipe",GetRecipe)

И обработчик запроса:

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 список также будет содержать значение, но я нашел self.get_argument использование удобным таким образом.

Теперь о результатах:

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"}

Ответ 4

Если вы хотите использовать более динамичный подход для фильтрации (вместо жестко закодированного URL), вы можете получить все переданные параметры/аргументы URL, используя self.request.arguments в обработчике запросов.

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

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