意见

Pyramid 和 Pylons 之间最大的区别在于视图的结构,以及它们如何调用模板和访问状态变量。这是一个大主题,因为它涉及模板、渲染器、请求变量、URL生成器等,其中一些主题有许多方面。所以我们就从某个地方开始,继续前进,让它自己组织起来,不管它落下了什么。

First let's review Pylons' view handling. In Pylons, a view is called an "action", and is a method in a controller class. Pylons has specific rules about the controller's module name, class name, and base class. When Pylons matches a URL to a route, it uses the routes 'controller' and 'action' variables to look up the controller and action. It instantiates the controller and calls the action. The action may take arguments with the same name as routing variables in the route; Pylons will pass in the current values from the route. The action normally returns a string, usually by calling render(template_name) to render a template. Alternatively, it can return a WebOb Response . The request's state data is handled by magic global variables which contain the values for the current request. (This includes equest parameters, response attributes, template variables, session variables, URL generator, cache object, and an "application globals" object.)

View functions and view methods

Pyramid view callable can be a function or a method, and it can be in any location. The most basic form is a function that takes a request and returns a response:

from pyramid.response import Response

def my_view(request):
    return Response("Hello, world!")

A view method may be in any class. A class containing view methods is conventionally called a "view class" or a "handler". If a view is a method, the request is passed to the class constructor, and the method is called without arguments. ::

1
2
3
4
5
6
class MyHandler(object):
    def __init__(self, request):
        self.request = request

    def my_view(self):
        return Response("Hello, classy world!")

The Pyramid structure has three major benefits.

  • 最重要的是,它更容易测试。单元测试可以使用一个假请求调用一个视图,并返回传递给模板的dict。它可以直接检查数据变量,而不是从HTML中解析它们。
  • 它更简单,更模块化。没有魔法球。
  • 你可以随意组织自己喜欢的视图。

Typical view usage

Merely defining a view is not enough to make Pyramid use it. 你必须 register config.add_view() 或使用 @view_config 装饰者。

The most common way to use views is with the @view_config 装饰者。This both marks the callable as a view and allows you to specify a template. It's also common to define a base class for common code shared by view classes. The following is borrowed from the Akhet demo. ::

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
from pyramid.view import view_config

class Handler(object):
    def __init__(self, request):
        self.request = request

class Main(Handler):

    @view_config(route_name="home", renderer="index.mako")
    def index(self):
        return {"project": "Akhet Demo"}

应用程序的主要功能有 config.scan() line, which imports all application modules looking for @view_config 装饰工。For each one it calls config.add_view(view) with the same keyword arguments. The scanner also recognizes a few other decorators which we'll see later. If you know that all your views are in a certain module or subpackage, you can scan only that one: config.scan(".views") .

例子 @view_config decorator has two arguments, 'route_name' and 'renderer'. The 'route_name' argument is required when using URL dispatch, to tell Pyramid which route should invoke this view. The "renderer" argument names a template to invoke. In this case, the view's return value is a dict of data variables for the template. (This takes the place of Pylons' 'c' variable, and mimics TurboGears' usage pattern.) The renderer takes care of creating a Response object for you.

查看配置参数

以下参数可以传递给 @view_configconfig.add_view @view_defaultsclass to specify them in one place.

This list includes only arguments commonly used in Pylons-like applications. The full list is in View Configuration 在 Pyramid 手册中。参数的谓词/非谓词区别与 add_route 争论。可以为一个路由注册多个视图,每个视图都有不同的谓词参数,以便在不同的情况下调用不同的视图。

有些论点是共同的 add_routeadd_view . In the route's case it determines whether the route will match a URL. In the view's case it determines whether the view will match the route.

route_name

[谓词]要将此视图附加到的路由。使用URL调度时需要。

渲染器

[非谓词]呈现器或模板的名称。在下面的渲染器中讨论。

许可

[非谓词]一个字符串,用于命名当前用户调用视图必须具有的权限。

http_cache

[非谓词]影响响应中的“expires”和“cache control”HTTP头。这将告诉浏览器是否缓存响应以及缓存的时间。该值可以是一个整数,指定要缓存的秒数,a datetime.timedelta instance, or zero to prevent caching. This is equivalent to calling request.response.cache_expires(value) within the view code.

语境

context

request_method

[谓词]字符串“get”、“post”、“put”、“delete”、“head”之一。请求方法必须等于此值才能选择视图。REST应用程序通常为同一个路由注册多个视图,每个视图使用不同的请求方法。

request_param

[predicate] This can be a string such as "foo", indicating that the request must have a query parameter or POST variable named "foo" in order for this view to be chosen. Alternatively, if the string contains "=" such as "foo=1", the request must both have this parameter and 其值必须符合指定,否则将不选择此视图。

match_param

[谓词]与request_param相似,但引用matchdict中的路由变量。除了“foo”和“foo=1”语法之外,还可以传递键/值对的dict:所有这些路由变量都必须存在并具有指定的值。

xhr, accept, header, path_info

[predicate] These work like the corresponding arguments to config.add_route .

custom_predicates

[predicate] The value is a list of functions. Each function should take a contextrequest argument, and return true or false whether the arguments are acceptable to the view. The view will be chosen only if all functions return true. Note that the function arguments are different than the corresponding option to config.add_route .

一个视图选项 not 与url调度一起使用是“name”参数。这只在遍历中使用。

渲染器

A renderer json 序列化程序,它接受有限的类型。)

renderer="string"renderer="json"renderer="jsonp" . 模板渲染器由模板的文件扩展名调用,因此 renderer="mytemplate.mako"renderer="mytemplate.mak" 去Mako。Note that you'll need to specify a Mako search path in the INI file or main function:

[app:main]
mako.directories = my_app_package:templates

假设您可以为Mako渲染器传递一个资产规格,而不是一个相对路径,因此避免定义一个Mako搜索路径,但我不能让它工作。 Chameleon 模板以.pt结尾,必须指定为资产规格。

可以为其他模板引擎注册第三方渲染器,也可以在不同的文件扩展名下重新注册渲染器。Akhet演示有一个示例,通过Mako使Pyramid发送以.html结尾的模板。

You can also invoke a renderer inside view code. ::

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
from pyramid.renderers import render, render_to_response

variables = {"dear": "Mr A", "sincerely": "Miss Z",
    "date": datetime.date.today()}

# Render a template to a string.
letter = render("form_letter.mako", variables, request=self.request)

# Render a template to a Response object.
return render_to_response("mytemplate.mako", variables,
    request=self.request)

调试视图

如果您认为某个路由或视图不应该被选中,请尝试将“pyramid.debuguNotFound”和/或“pyramid.debugroutematch”设置为“true in” 开发公司. It will log its reasoning to the console.

Multiple views using the same callable

You can stack multiple @view_config onto the same view method or function, in cases where the templates differ but the view logic is the same. ::

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
@view_config(route_name="help", renderer="help.mak")
@view_config(route_name="faq", renderer="faq.mak")
@view_config(route_name="privacy", renderer="privacy_policy.mak")
def template(request):
    return {}

@view_config(route_name="info", renderer="info.mak")
@view-config(route_name="info_json", renderer="json")
def info(request):
    return {}