Skip to content.

Personal tools
You are here: Home » Weird Stuff You Can Do With Pyramid URL Dispatch
 
 

Weird Stuff You Can Do With Pyramid URL Dispatch

Weird stuff you can do with Pyramid "url dispatch".

Here's some weird stuff you can do with Pyramid URL dispatch.

You can do the boring thing by associating a route directly with a view callable:

  config.add_route('blogentry', '/blog/{id}', 
                   view='mypackage.views.blog_entry_view')

When the above route is matched, for example, when the path of the inbound URL is blog/123, the view callable defined in the mypackage.views.blog_entry_view view callable will be called. Yawn.

To spice things up a bit, you can also associate a number of views with a route:

  config.add_route('blogentry', '/blog/{id}')

"Wait, what? I don't see any associated view callables there!" That's right, perceptive reader. When you want to associate more than one view with a particular route, the associations are usually done nearer to the view code itself:

  from pyramid.view import view_config

  @view_config(route_name='blogentry', request_method='GET')
  def get_blogentry(request):
      ...

  @view_config(route_name='blogentry', request_method='POST')
  def post_blogentry(request):
      ...

In this case, when the blogentry route is matched during a request, if the request_method of the request is GET, the get_blogentry view callable will be invoked. But if the request_method of the request is POST, the post_blogentry view callable will be invoked. The route_name and request_method arguments to view_config are view predicate arguments. When this route matches, for these particular views to be considered, the route that matched must be blogentry, and the request_method must be GET for get_blogentry or POST for post_blogentry.

Still kinda boring. Let's add more stuff:

  from pyramid.view import view_config

  @view_config(route_name='blogentry', request_method='GET', xhr=True)
  def get_blogentry_xhr(request):
      ...

  @view_config(route_name='blogentry', request_method='GET')
  def get_blogentry(request):
      ...

  @view_config(route_name='blogentry', request_method='POST')
  def post_blogentry(request):
      ...

We added another view callable named get_blogentry_xhr above. This view will be matched when the blogentry route is matched, when the request method is GET and when the request is an XMLHttpRequest from JavaScript. But if a "normal" client invokes a URL that matches the blogentry route, with either GET or POST one of get_blogentry or post_blogentry will still be used. The view with the greatest number of predicates that match is considered "the best match". Just keep tacking on predicates to the view config to get specific-er and specific-er.

All of the view predicates we've used so far are "built-in" view predicates (there are a list of them in the docs). But we can also define our own view predicates:

  def example_dot_com_host(info, request):
      if request.host == 'www.example.com:
          return True

That's a custom predicate there. It returns True if the hostname is www.example.com. Here's how we use it:

  @view_config(route_name='blogentry', request_method='GET')
  def get_blogentry(request):
      ...

  @view_config(route_name='blogentry', request_method='POST')
  def post_blogentry(request):
      ...

  @view_config(route_name='blogentry', request_method='GET', 
               custom_predicates=(example_dot_com_host,))
  def get_blogentry_example_com(request):
      ...

  @view_config(route_name='blogentry', request_method='POST', 
               custom_predicates=(example_dot_com_host,))
  def post_blogentry_example_com(request):
      ...

We added two views above, get_blogentry_example_com and post_blogentry_example_com. Our custom predicate will return True if the request hostname is www.example.com. So these views will be found when the blogentry route matches, when the request method is either GET or POST, and when the request's hostname is www.example.com. Otherwise, it will fall back to the next most specific view (either get_blogentry or post_blogentry).

Anyway, just sayin.

Created by chrism
Last modified 2010-12-21 05:18 PM