Pyramid: How to create-use custom dispatcher?

本秂侑毒 提交于 2019-12-11 16:24:16

问题


Besides the root url request, which will be sent to a view, I want to have a dispatcher that I will route all the requests to different views which I will chose depending on my custom dispatcher's rules.

How can I create a dispatcher? I have read the docs over and over again yet I can not figure it out.

I want to parse the *remainder of url and then dispatch the request accordingly.


回答1:


Pyramid will dispatch the request to a view registered via add_view or view_config. If you want to dispatch this again to your own code, just remember that from Pyramid's perspective the renderer/permission defined on the original view will be used... so don't use those. The request effectively enters your Pyramid view, then you have your own mini-framework that will handle it from there.

I suggest thinking about how to dispatch things in the context of Pyramid views, for example the pyramid_rpc package does some cool stuff to dispatch to views based on the content in the body of an RPC request (not just the URL). See the custom predicate within add_jsonrpc_method to know what I'm talking about.

Anyway, assuming you still want to do your own thing, all you have to do is register a view in Pyramid for whatever pattern you want.

config.add_route('my_framework', '/foo/{the_rest:.*}')

@view_config(route_name='my_framework')
def my_framework_view(request):
    url = request.matchdict['the_rest']
    # do your frameworky stuff here
    if url == 'foo/bar':
        return some_other_view(request)
    return HTTPNotFound()

Anyway, it should be clear that this is a framework on top of a framework and probably a code smell in a lot of cases.




回答2:


It really depends on the structure or you URLS and your "custom dispatcher rules", but for many cases you can use URL traversal instead of URL dispatch to achieve what you want. Due to the fact that URL traversal uses __getitem__ method of the parent resource, where you can write normal Python code, it may allow you more flexibility.

Example: imagine you have the following URLS:

/food/banana
/food/potato
/food/tomato
/food/apple

and you want to have different views for fruit and vegetables. You can do something like this:

class FoodResource(object):
    def __getitem__(self, name):
        if name in ["banana", "apple"]:
            return FruitResource(self, name)
        if name in ["potato", "tomato"]:
            return VegetableResource(self, name)

then you can register views for FruitResource and VegetableResource:

@view_config(context=FruitResource):
def view_fruit(context, request):
    ...

@view_config(context=VegetableResource):
def view_vegetable(context, request):
    ...

You can have different sets of views registered for Fruits and Vegetables, so /foor/banana/make_jam and /food/apple/make_jam will be vaild URLs for fruits only, and for vegetables you'll have, say, /food/potato/make_soup:

@view_config(context=FruitResource, name="make_jam"):
def view_fruit_make_jam(context, request):
    ...

@view_config(context=VegetableResource, name="make_soup"):
def view_vegetable_make_soup(context, request):
    ...

Then your FruitResource and VegetableResource can have their own __getitem__ methods, so you can have potentially different sets of "subitems" - /food/banana/skin, /food/banana/flesh etc, with their own views assigned to them - /food/banana/skin/peel, /food/banana/flesh/eat, where peel and eat are views registered for imaginary FruitSkinResource and FruitFleshResource.

And you can have custom permissions for fruits and vegetables, so accessing /food/apple/make_jam may require one permission and /food/potato/make_soup another.




回答3:


I think you could use pyramid's event system docs this is looks like hack but I think it is the easiest way.



来源:https://stackoverflow.com/questions/11139358/pyramid-how-to-create-use-custom-dispatcher

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