Question

I am looking for a way to redirect users to different routes/templates that is compatible with using @view_config.

I have a function that reads in an uploaded file and attempts to create a new model based on the file content. I was wondering if there was a clean way that I can redirect the user to one of two urls, based on whether the creation of the new model succeeds or there is an error.

If the model creation is successful, I want to redirect the user to the model page. If there is an error, I want to redirect the user to an error page. However, am having trouble breaking out the original function (load_model)'s view_config when rendering the error page.

@view_config(renderer="error.mak")
@view_config(renderer="model.mak",
        route_name='load_model_route')
def load_model(self):
   ...
   model = Model.find_model(model_name)
   if model:
      #redirect to model_route
   else:
      #redirect to model_error_route

Each route would have a @view_config that binds it to a function.

Was it helpful?

Solution

What you are asking is not "How to redirect" but "How to change renderer in the view function". To answer quickly, I think you could use:

request.override_renderer = 'other-renderer.mak'

But I don't think it's a good idea. Here's the usual pattern that is used most of the time to handle form submission:

from pyramid.httpexceptions import HTTPFound, HTTPNotFound
from pyramid.url import route_url
from your_app import Model, some_stuff, save_to_db

@view_config(route_name='new_model',
        renderer='model/new.mak', request_method='GET')
def new(request):
    """Shows the empty form."""
    return {'model': Model(), 'errors': {}}

@view_config(route_name='create_model',
        renderer='model/new.mak', request_method='POST')
def create(request):
    """Receives submitted form."""
    model = some_stuff()
    if len(model.errors) = 0: # is valid
        # do your stuff, then redirect
        save_to_db(model)
        return HTTPFound(route_url('show_model', request, model_id=model.id))
    # is invalid
    return {'model': model, 'errors': model.errors}

@view_config(route_name='show_model',
    renderer='model/show.mak', request_method='GET')
def show(request):
    """Shows details of one model."""
    model = Model.find(request.matchdict['model_id'])
    if model is None:
        return HTTPNotFound()
    return {'model': model}

In short:

  • You show an empty form when you have a GET on the route for a new model.
  • You handle the form submission (POST) in a different view function
    • If the data is valid, you do your stuff, then you redirect with HTTPFound
    • If the data is invalid, you return a dict to show the form again, with errors this time
  • You use the same renderer in the GET and POST, but the one in the POST is only used in case of invalid data (otherwise, you redirect).
  • You have another view function to show the created model.

OTHER TIPS

Antoine showed a more general solution, but here's an attempt to stick to your basic format.

The idea is that you want to do some processing and then redirect the user to either a success or a failure page. You can redirect to a failure page if you want to just the same way you redirect to a success page, but I'll show a different version where you just show the error page in load, but if load works you redirect to the model.

config.add_route('show_model', '/models/{id}')
config.add_route('load_model', '/load_model')

@view_config(route_name='load_model', renderer='error.mak')
def load_model(self):
    # ...
    model = Model.find_model(model_name)
    if model:
        return HTTPFound(self.request.route_url('show_model', id=model.id))
    return {} # some dict of stuff required to render 'error.mak'

@view_config(route_name='show_model', renderer='model.mak')
def show_model(self):
    id = request.matchdict['id']
    model = Model.get_model_by_id(id)
    # be aware model could fail to load in this new request
    return {'model': model} # a dict of stuff required to render 'model.mak'
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top