-
Notifications
You must be signed in to change notification settings - Fork 60
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #37 from hfaran/urlannotations
URL Annotations
- Loading branch information
Showing
13 changed files
with
306 additions
and
43 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
**This documentation is automatically generated.** | ||
|
||
**Output schemas only represent `data` and not the full output; see output examples and the JSend specification.** |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
#!/usr/bin/env python2.7 | ||
|
||
# ---- The following so demo can be run without having to install package ----# | ||
import sys | ||
sys.path.append("../../") | ||
# ---- Can be removed if Tornado-JSON is installed ----# | ||
|
||
# This module contains essentially the same boilerplate | ||
# as the corresponding one in the helloworld example; | ||
# refer to that for details. | ||
|
||
import json | ||
import tornado.ioloop | ||
from tornado_json.routes import get_routes | ||
from tornado_json.application import Application | ||
|
||
|
||
def main(): | ||
import cars | ||
routes = get_routes(cars) | ||
print("Routes\n======\n\n" + json.dumps( | ||
[(url, repr(rh)) for url, rh in routes], | ||
indent=2) | ||
) | ||
application = Application(routes=routes, settings={}) | ||
|
||
application.listen(8888) | ||
tornado.ioloop.IOLoop.instance().start() | ||
|
||
|
||
if __name__ == '__main__': | ||
main() |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
from tornado_json.requesthandlers import APIHandler | ||
|
||
|
||
DATA = { | ||
"Ford": { | ||
"Fusion": { | ||
"2013": "http://www.ford.ca/cars/fusion/2013/", | ||
"2014": "http://www.ford.ca/cars/fusion/2014/" | ||
}, | ||
"Taurus": { | ||
"2013": "http://www.ford.ca/cars/taurus/2013/", | ||
"2014": "http://www.ford.ca/cars/taurus/2014/" | ||
} | ||
} | ||
} | ||
|
||
|
||
class CarsAPIHandler(APIHandler): | ||
|
||
# APIHandler has two "special" attributes: | ||
# * __url_names__ : | ||
# This is a list of names you'd like the | ||
# the requesthandler to be called in auto- | ||
# generated routes, i.e., since the absolute | ||
# path of this handler (in context of the | ||
# ``cars`` package) is, ``cars.api.CarsAPIHandler``, | ||
# if you've read earlier documentation, you'll | ||
# know that the associated URL to this that | ||
# will be autogenerated is "/api/carsapi". | ||
# __url_names__ can change the last ``carsapi`` | ||
# part to whatever is in the list. So in this | ||
# case, we change it to "/api/cars". If we added | ||
# additional names to the list, we would generate | ||
# more routes with the given names. | ||
# Of course, this isn't an actual handler, just | ||
# a handy superclass that we'll let all of the handlers | ||
# below inherit from so they can have a base URL of | ||
# "/api/cars" also, but extended to match additional | ||
# things based on the parameters of their ``get`` methods. | ||
# | ||
# An important note on __url_names__ is that by default, | ||
# it exists as ``__url_names__ = ["__self__"]``. The | ||
# ``__self__`` is a special value, which means that the | ||
# requesthandler should get a URL such as the ones you | ||
# assigned to the handlers in the Hello World demo. | ||
# You can either ADD to the list to keep this, or | ||
# create a new list to not. | ||
# | ||
# * __urls__ : | ||
# I'll mention __urls__ as well; this let's you just | ||
# assign a completely custom URL pattern to match to | ||
# the requesthandlers, i.e., I could add something like, | ||
# ``__urls__ = [r"/api/cars/?"]`` | ||
# and that would give me the exact same URL mapped | ||
# to this handler, but defined by me. Note that both | ||
# URLs generated from ``__url_names__`` and URLs provided | ||
# by you in ``__urls__`` will be created and assigned to | ||
# the associated requesthandler, so make sure to modify/overwrite | ||
# both attributes to get only the URLs mapped that you want. | ||
# | ||
__url_names__ = ["cars"] | ||
|
||
|
||
class MakeListHandler(CarsAPIHandler): | ||
|
||
def get(self): | ||
self.success(DATA.keys()) | ||
|
||
|
||
class MakeHandler(CarsAPIHandler): | ||
|
||
def get(self, make): | ||
try: | ||
self.success(DATA[make]) | ||
except KeyError: | ||
self.fail("No data on such make `{}`.".format(make)) | ||
|
||
|
||
class ModelHandler(CarsAPIHandler): | ||
|
||
def get(self, make, model): | ||
try: | ||
self.success(DATA[make][model]) | ||
except KeyError: | ||
self.fail("No data on `{} {}`.".format(make, model)) | ||
|
||
|
||
class YearHandler(CarsAPIHandler): | ||
|
||
def get(self, make, model, year): | ||
try: | ||
self.success(DATA[make][model][year]) | ||
except KeyError: | ||
self.fail("No data on `{} {} {}`.".format(year, make, model)) | ||
|
||
|
||
# Routes for the handlers above will look like this: | ||
# | ||
# [ | ||
# [ | ||
# "/api/cars/?", | ||
# "<class 'cars.api.MakeListHandler'>" | ||
# ], | ||
# [ | ||
# "/api/cars/(?P<make>[a-zA-Z0-9_]+)/(?P<model>[a-zA-Z0-9_]+)/?$", | ||
# "<class 'cars.api.ModelHandler'>" | ||
# ], | ||
# [ | ||
# "/api/cars/(?P<make>[a-zA-Z0-9_]+)/(?P<model>[a-zA-Z0-9_]+)/(?P<year>[a-zA-Z0-9_]+)/?$", | ||
# "<class 'cars.api.YearHandler'>" | ||
# ], | ||
# [ | ||
# "/api/cars/(?P<make>[a-zA-Z0-9_]+)/?$", | ||
# "<class 'cars.api.MakeHandler'>" | ||
# ] | ||
# ] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
Creating a REST API Using URL Annotations | ||
========================================= | ||
|
||
You may have noticed that the automatic URL generation | ||
is meant to be quick and easy-to-use for simple cases (creating an | ||
API in 15 minutes kind of thing). | ||
|
||
It is more powerful though, however, as you can customize it | ||
to get the URLs for RequestHandlers how you want without | ||
having to make additions to output from ``routes.get_routes`` | ||
yourself. This is done through the use of "URL annotations". | ||
``APIHandler`` and ``ViewHandler`` have two "magic" attributes | ||
(``__urls__`` and ``__url_names__``) that allow you to define custom routes right in the handler | ||
body. See relevant documentation in the | ||
`REST API <https://github.com/hfaran/Tornado-JSON/blob/master/demos/rest_api/cars/api/__init__.py>`__ | ||
example in the demos. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.