6

this is very specific to what I am trying to do so I start describing what it is:

  • a Pyramid app serving plots like http://localhost:6543/path/to/myplot/plot001.png
  • if the plot is not available another image is served (work.png)
  • another part is the deform view which provides a HTML form to enter the configuration for a plot like: http://localhost:6543/path/to/myplot/plot001.png?action=edit. Note here the query string "action=edit".
  • the configuration consists of datafile, templates etc.
  • the form has save (to save the config) and render buttons (http://localhost:6543/path/to/myplot/plot001.png?action=render). Rendering results into a png file which then is used in a static way.

I figured out all the pieces like rendering using Matplotlib etc. but I am new to Pyramid and Deform. I also have a working view that serves the plot from file. The deform form kind of works, too. At the moment it is unclear to me how to best structure the ULRs to distinguish the serve, edit and render usecases. I guess in Pyramid talk this means how to configure the routes for serve_view and edit_view.

__init__.py:
    config.add_route('serve_route', 
        '/{project_name}/testruns/{testrun_name}/plots/{plot_name}.png')
    config.add_route('edit_route', 
        '/{project_name}/testruns/{testrun_name}/plots/{plot_name}.png')
# can I use query strings like "?action=edit" here to distinguish the difference?


views.py:
@view_config(context=Root, route_name='serve_route')
def plot_view(context, request):
... 
@view_config(context=Root, renderer='bunseki:templates/form.pt', route_name='edit_route')
def edit_view(request):
...

I the Pyramid manual I could not find reference how to set parameters in the route. I guess a pointer to some documentation or sample would be sufficient and I can figure out the details myself. Thank you!

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
moin moin
  • 2,263
  • 5
  • 32
  • 51
  • Pyramid has a mechanism they call Multidict. I think this is the way to go to access the query string. I will merge the two views plot and edit into one and make the distinction using something like the following: if 'edit' in request.GET.getall('action'): # edit the configuration – moin moin Aug 01 '11 at 14:15
  • What you say in the above comment is fine and it's probably the way I would do it; you can alternately add a custom predicate to the add_route statement which would disambiguate the two routes on the query string for matching purposes. See http://docs.pylonsproject.org/projects/pyramid/1.1/narr/urldispatch.html#custom-route-predicates – Chris McDonough Aug 01 '11 at 23:20

3 Answers3

12

There are two ways to do this depending on what you prefer for separating your code.

  1. Put all of the logic into your view, separated by 'if' statements on request.GET.get('action').

    config.add_route('plot', '/{project_name}/testruns/{testrun_name}/plots/{plot_name}.png')
    config.scan()
    
    @view_config(route_name='plot')
    def plot_view(request):
        action = request.GET('action')
        if action == 'edit':
            # do something
            return render_to_response('bunseki:templates/form.pt', {}, request)
    
        # return the png
    
  2. Register multiple views and delegate between them using Pyramid's view lookup mechanics.

    config.add_route('plot', '/{project_name}/testruns/{testrun_name}/plots/{plot_name}.png')
    config.scan()
    
    @view_config(route_name='plot')
    def plot_image_view(request):
        # return the plot image
    
    @view_config(route_name='plot', request_param='action=edit',
                 renderer='bunseki:templates/form.pt')
    def edit_plot_view(request):
        # edit the plot
        return {}
    
    # etc..
    

Hope this helps. It's an excellent example of registering a single url pattern, and using different views for different types of requests on that url.

tshepang
  • 12,111
  • 21
  • 91
  • 136
Michael Merickel
  • 23,153
  • 3
  • 54
  • 70
1

I'm not sure you can use contex=Root in that situation, but what you are asking for is probably the matchdict.

__init__.py:

config.add_route('serve_route', 
    '/{project_name}/testruns/{testrun_name}/plots/{plot_name}.png')

views.py:

@view_config(route_name='serve_route')
def plot_view(request):
    project_name = request.matchdict['project_name']
    action = request.params.get('action', None)

http://docs.pylonsproject.org/projects/pyramid/1.1/narr/urldispatch.html#matchdict

Edit:

If your question is more a general question regarding routing, you should create one route per action to keep the code of your view functions shorter and clearer. For example, if you want to edit and render, your routes could look something like this:

__init__.py:

config.add_route('render_plot',
    '/{project_name}/testruns/{testrun_name}/plots/{plot_name}.png')
config.add_route('edit_plot',
    '/{project_name}/testruns/{testrun_name}/plots/{plot_name}/edit')

views.py:

@view_config('render_plot')
def render(request):
    pass

@view_config('edit_plot', renderer='bunseki:templates/form.pt')
def edit(request):
    pass
Antoine Leclair
  • 17,540
  • 3
  • 26
  • 18
  • 1
    I do not think that matchdict is the way to go for URL parameters. Parameters do not have a defined order. I mean in case you have more than one parameter you can interchange them. As far as I understand matchdict it is meant to cover the URL part on the left side of "?". – moin moin Aug 01 '11 at 13:44
0

A more effective way will be to specify the action in the url. And you can even serve different actions on the same route name or multiple.

config.add_route('serve_route', '/{project_name}/testruns/{testrun_name}/plots/{action}/{plot_name}.png')

views.py
@view_config(context=Root, route_name='serve_route', action='view')
def plot_view(request):
    pass

Or with query string

`config.add_route('serve_route', 
    '/{project_name}/testruns/{testrun_name}/plots/{plot_name}.png')

views.py
@view_config(context=Root, route_name='serve_route')
def plot_view(request):
    try:
       action = getattr(self._request.GET, 'action')
    except AttributeError:
       raise 
jackotonye
  • 3,537
  • 23
  • 31