Content Types and Request Extensions are supported by both tg.controllers.TGController and tg.controllers.RestController. Request extensions allow the user to provide a specifier at the end of their data stream which specifies how they would like their data retrieved, using a dot operator.
TurboGears Controllers gives the developer the ability to attach a mime-type to their methods to express data in using different protocols. The most common usage for this is with json, a standard protocol used for Asynchronous JavaScript. Consider the following code snippet:
users = "sally", "dave", "john"
class Forum(TGController):
@expose('json')
def users(self):
return {'users':users}
This allows you to map a URL like /forum/users.json
Sometimes you want a controller to return content based on the extension provided by the user, or the lack-there-of. You can cascade multiple expose decorators to accomplish this. Consider this example: you have a page which lists the user in a table which is generated using JavaScript. JS makes an asynchronous call to your web application to fill the data. It makes sense to fetch the data for the Json call, but not for the rendering of the HTML template used to render the data. Here is the users example again which expresses this use case:
users = "sally", "dave", "john"
class Forum(TGController):
@expose(myproject.templates.forum.users)
@expose('json')
def users(self):
if pylons.request.response_type == 'application/json':
return {'users':users}
return {}
The users method will service both /forum/users/ and /forum/users.json. Simply provide the JavaScript code with a link to users.json and you are good to go. This makes providing your users with RESTful URLs much simpler. You could imagine using this capability to expose your application’s resources for SOAP, or XML-RPC.
By default, only json/application and text/html are defined mimetypes. If you would like to use additional mime-types you must register them with your application’s config. You can accomplish this by adding the following code your your app_cfg.py file:
base_config.mimetype_lookup = {'.ext':'my-mimetype'}
Setting the Content-Type for your return data is often used to tell the web browser how to display that data to the user. For instance, if you want the browser to open an Excel file as such, you need to tell the browser that the data coming back is in Excel format. Sometimes we want to set the content-type for our response within the controller method. By providing the @expose decorator with a “CUSTOM_CONTENT_TYPE” indicator we are able to accomplish this. Here is an example of how to return a simple .csv file that the browser will treat as an attachment:
import pylons
from tg.controllers import CUSTOM_CONTENT_TYPE
class MyController:
@expose(content_type=CUSTOM_CONTENT_TYPE)
def stats(self):
pylons.request['Content-Type'] = 'text/csv'
pylons.request['Content-Disposition'] = 'attachment;filename=stats.csv'
return '1,2,3'