07:带视图的基本Web处理

使用装饰器和多个视图组织视图模块。

背景

对于目前为止的例子, hello_world 功能是一个“视图”。在Pyramid中,视图是接受Web请求和返回响应的主要方式。

到目前为止,我们的示例将所有内容放在一个文件中:

  • 视图功能

  • 它在配置程序中的注册

  • 将其映射到URL的路由

  • wsgi应用程序启动程序

让我们将视图移到它们自己的视图中 views.py 模块化并更改启动代码以扫描该模块,查找设置视图的装饰器。我们还要添加第二个视图并更新我们的测试。

目标

  • 将视图移动到配置程序扫描的模块中。

  • 创建进行声明性配置的装饰器。

步骤

  1. 让我们首先使用前一个包作为新分发的起点,然后使其处于活动状态:

    cd ..; cp -r functional_testing views; cd views
    $VENV/bin/pip install -e .
    
  2. 我们的 views/tutorial/__init__.py 缩短了很多:

    1from pyramid.config import Configurator
    2
    3
    4def main(global_config, **settings):
    5    config = Configurator(settings=settings)
    6    config.add_route('home', '/')
    7    config.add_route('hello', '/howdy')
    8    config.scan('.views')
    9    return config.make_wsgi_app()
    
  3. 让我们添加一个模块 views/tutorial/views.py 重点处理请求和响应:

     1from pyramid.response import Response
     2from pyramid.view import view_config
     3
     4
     5# First view, available at http://localhost:6543/
     6@view_config(route_name='home')
     7def home(request):
     8    return Response('<body>Visit <a href="/howdy">hello</a></body>')
     9
    10
    11# /howdy
    12@view_config(route_name='hello')
    13def hello(request):
    14    return Response('<body>Go back <a href="/">home</a></body>')
    
  4. 更新测试以涵盖两个新视图:

     1import unittest
     2
     3from pyramid import testing
     4
     5
     6class TutorialViewTests(unittest.TestCase):
     7    def setUp(self):
     8        self.config = testing.setUp()
     9
    10    def tearDown(self):
    11        testing.tearDown()
    12
    13    def test_home(self):
    14        from .views import home
    15
    16        request = testing.DummyRequest()
    17        response = home(request)
    18        self.assertEqual(response.status_code, 200)
    19        self.assertIn(b'Visit', response.body)
    20
    21    def test_hello(self):
    22        from .views import hello
    23
    24        request = testing.DummyRequest()
    25        response = hello(request)
    26        self.assertEqual(response.status_code, 200)
    27        self.assertIn(b'Go back', response.body)
    28
    29
    30class TutorialFunctionalTests(unittest.TestCase):
    31    def setUp(self):
    32        from tutorial import main
    33        app = main({})
    34        from webtest import TestApp
    35
    36        self.testapp = TestApp(app)
    37
    38    def test_home(self):
    39        res = self.testapp.get('/', status=200)
    40        self.assertIn(b'<body>Visit', res.body)
    41
    42    def test_hello(self):
    43        res = self.testapp.get('/howdy', status=200)
    44        self.assertIn(b'<body>Go back', res.body)
    
  5. 现在运行测试:

    $VENV/bin/pytest tutorial/tests.py -q
    ....
    4 passed in 0.28 seconds
    
  6. 运行 Pyramid 应用程序时使用:

    $VENV/bin/pserve development.ini --reload
    
  7. 在浏览器中打开http://localhost:6543/和http://localhost:6543/howdy。

分析

我们添加了更多的URL,但也从中删除了应用程序启动代码中的视图代码。 tutorial/__init__.py . 我们的视图及其视图注册(通过装饰器)现在位于一个模块中 views.py ,通过扫描 config.scan('.views') .

我们有两种观点,每一种观点都是相互引导的。如果从http://localhost:6543/开始,将得到一个响应,其中包含指向下一个视图的链接。这个 hello 视图(在URL上可用 /howdy )有返回第一个视图的链接。

此步骤还显示URL中显示的名称、将URL映射到视图的“路由”的名称以及视图的名称都可能不同。更多关于路线的信息。

早些时候我们看到 config.add_view 作为配置视图的一种方法。本节介绍 @view_config . Pyramid的配置支持 imperative configuration ,比如 config.add_view 在上一个示例中。您也可以使用 declarative configuration ,其中一条 Python decorator 放置在视图上方的行上。这两种方法都会产生相同的最终配置,因此,这通常只是一个简单的品味问题。

额外credit

  1. 圆点在哪 .views 意味着?

  2. 为什么可能 assertIn 在测试响应中的文本时,比 assertEqual 是吗?