Optional url segment pattern in a Pyramid route

Viewed 106

I'm trying to create a website with optional url sub-paths:

  • /user - Returns general information on users
  • /user/edit - Edits the user

I've tried setting:

config.add_route('user', '/user/{action}')

@view_defaults(route_name="user")
class UserViews():

# not sure what (if anything) to put in @view_config here...
def user_general(self):
    return Response("General User Info"

@view_config(match_param="action=edit")
def edit(self):
    return Response("Editing user")

However while this works for /user/edit, it returns a 404 for /user

It also fails in the same way if I set 2 explicit routes with a shared path - e.g.:

config.add_route('login', '/user')
config.add_route('edit_user', '/user/edit')

I've tried things like setting match_params="action=" but can't get it to work.

Any ideas on how this can be achieved?

1 Answers

user_general inherits the default route configuration of the class, which requires an {action} match param. When you do not supply that in the request, the route for that view will never match, returning a 404 not found response.

You need to add a decorator with the route_name argument to user_general to override the default route for the view.

@view_config(
    route_name="user"
)
def user_general(self):

The following works for me as a complete example with some minor explicit naming conventions.

from wsgiref.simple_server import make_server
from pyramid.config import Configurator
from pyramid.response import Response
from pyramid.view import view_config, view_defaults


@view_defaults(route_name="user_action")
class UserViews():
    def __init__(self, context, request):
        self.request = request
        self.context = context

    @view_config(
        route_name="user_get",
        request_method="GET"
    )
    def get_user(request):
        return Response("I got you, Babe!")

    @view_config(
        match_param="action=edit"
    )
    def edit(self):
        return Response("Don't ever change, Babe!")

if __name__ == "__main__":
    with Configurator() as config:
        config.add_route("user_get", "/user")
        config.add_route('user_action', '/user/{action}')
        config.scan()
        app = config.make_wsgi_app()
    server = make_server("0.0.0.0", 6543, app)
    server.serve_forever()
Related