In Pyramid, how can I use a different renderer based on contents of context?

可紊 提交于 2019-12-19 02:31:20

问题


I have 3 different product page layouts that I would like to display dependent on the information available about the products. Using traversal I have a class called ProductFinder that grabs all the information. For example the user goes to domain/green/small and ProductFinder will list all products from my DB that are green and small. This list is self.products in the ProductFinder class. In my __init__.py I have added the line:

config.add_view('app.views.products', name='')

In products.py I have:

from pyramid.view import view_config
@view_config(context='app.models.ProductFinder', renderer='productpage.mako')
def products(context, request):
    return dict(page=context)

Based on what's in context.products though I'd like to render a different mako. In Pylons I would have done something like:

def products(context, request):
    if len(context.products) == 1:
        return render("oneproduct.mako")
    elif len(context.product) == 2:
        return render("twoproducts.mako")

So how can I render a different template based on the contents of my context?


回答1:


I will start off by saying this sort of seems like something you want to take care of in your template.

However, you can influence which renderer is used as part of the view lookup in just about any way you want to. As you might already know you can use the same view handler for multiple views, you simply need to help Pyramid figure out which one to use.

For example:

from pyramid.view import view_config

def ProductLengthPredicate(length):
    def check_length(context, request):
        return len(context.products) == length
    return check_length

@view_config(context='app.models.ProductFinder', renderer='oneproduct.mako',
             custom_predicates=(ProductLengthPredicate(1),))
@view_config(context='app.models.ProductFinder', renderer='twoproducts.mako',
             custom_predicates=(ProductLengthPredicate(2),))
@view_config(context='app.models.ProductFinder', renderer='manyproducts.mako')
def products(context, request):
    return dict(page=context)

NB. Some people might be more interested in the render_to_response approach here because then they will not be relying on custom_predicates. But it is of course up to you!

@view_config(context='app.models.ProductFinder', renderer='manyproducts.mako')
def products(context, request)
    opts = dict(page=context)
    if len(context.products) == 1:
        return render_to_response('oneproduct.mako', opts, request)
    if len(context.products) == 2:
        return render_to_response('twoproducts.mako', opts, request)
    return opts

This works because Pyramid will ignore the renderers if your view returns a Response() which is exactly what render_to_response does.




回答2:


I'm not sure if it's the good way to go, but you could probably use request.override_renderer = 'oneproduct.mako'.

If it is just a different way of displaying your products depending on the quantity, you should do the decision in the template.



来源:https://stackoverflow.com/questions/6553569/in-pyramid-how-can-i-use-a-different-renderer-based-on-contents-of-context

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!