Differences between revisions 2 and 6 (spanning 4 versions)
Revision 2 as of 2006-10-28 00:04:33
Size: 7464
Editor: xlp223
Comment:
Revision 6 as of 2006-10-28 00:11:12
Size: 7026
Editor: xlp223
Comment:
Deletions are marked like this. Additions are marked like this.
Line 1: Line 1:
===================================================
Pylons Support for the Web Server Gateway Interface
===================================================
= Pylons Support for the Web Server Gateway Interface =
:author: James Gardner
Line 5: Line 4:
:author: James Gardner
Line 7: Line 5:

Line 16: Line 16:
Paste and WSGI
==============
== Paste and WSGI ==
Line 25: Line 23:
    from paste.deploy import loadapp
   
wsgi_app = loadapp('config:/path/to/config.ini')
 . from paste.deploy import loadapp wsgi_app = loadapp('config:/path/to/config.ini')
Line 32: Line 28:
    from paste.deploy import loadapp
   
wsgi_app = loadapp('config:/path/to/config.ini')
         from wsgiref import simple_server
   
httpd = simple_server.WSGIServer(('',8000), simple_server.WSGIRequestHandler)
    httpd.set_app(wsgi_app)
    httpd.serve_forever()
 . from paste.deploy import loadapp wsgi_app = loadapp('config:/path/to/config.ini') from wsgiref import simple_server
 httpd = simple_server.WSGIServer(('',8000), simple_server.WSGIRequestHandler) httpd.set_app(wsgi_app) httpd.serve_forever() ''
在pylons项目的开发中你可以使用{{{}}}paster serve{{{}}}命令来合并上面的两步,从配置文件创建一个WSGI app,并可以直接使用这个配置文件从而启动服务。
Line 40: Line 32:
在pylons项目的开发中你可以使用``paster serve``命令来合并上面的两步,从配置文件创建一个WSGI app,并可以直接使用这个配置文件从而启动服务。
 
Line 44: Line 34:
你也可以配置额外的WSGI middleware,application和更多直接使用的配置文件。更多不同的选项,你可以从`Paste Deploy Documentation <http://pythonpaste.org/deploy/>`_看到,这里我们就不重复了。 你也可以配置额外的WSGI middleware,application和更多直接使用的配置文件。更多不同的选项,你可以从{{{Paste Deploy Documentation <http://pythonpaste.org/deploy/>}}}_看到,这里我们就不重复了。
Line 46: Line 36:
Using a WSGI Application as a Pylons 0.9 Controller
---------------------------------------------------
Line 49: Line 37:
在pylons 0.9 controllers是从``pylons.controllers.WSGIController``派生而来,并且也是一个有效的WSGI application。除非你的controller是从以前的``pylons.controllers.Controller``派生得来,它也是被假定是一个WSGI application。这就是说你不必在你的controller中使用一个Pylons controller,只要你给它同一个名字,任何WSGI application都能起作用。
Line 51: Line 38:
举例来说,假如你用``paster controller hello``命令加了一个``hello`` controller,你可以改变它: == Using a WSGI Application as a Pylons 0.9 Controller ==

在pylons 0.9 controllers是从pylons.controllers.WSGIController派生而来,并且也是一个有效的WSGI application。除非你的controller是从以前的pylons.controllers.Controller派生得来,它也是被假定是一个WSGI application。这就是说你不必在你的controller中使用一个Pylons controller,只要你给它同一个名字,任何WSGI application都能起作用。举例来说,假如你用{{{}}}paster controller hello{{{}}}命令加了一个{{{}}}hello{{{}}} controller,你可以改变它:
Line 55: Line 44:
    def HelloController(environ, start_response):
        start_response('200 OK', [('Content-Type','text/html')])
       
return ['Hello World!']

或者使用``yield``语句:
 . def HelloController(environ, start_response):
  . start_response('200 OK', [('Content-Type','text/html')]) return ['Hello World!']
或者使用{{{}}}yield{{{}}}语句:
Line 63: Line 50:
    def HelloController(environ, start_response):
        start_response('200 OK', [('Content-Type','text/html')])
       
yield 'Hello '
       
yield 'World!'

或者使用标准的pylons ``Response`` 对象,它也是一个有效的WSGI response,和调用``start_response``有关的。
 . def HelloController(environ, start_response):
  . start_response('200 OK', [('Content-Type','text/html')]) yield 'Hello ' yield 'World!'
或者使用标准的pylons {{{}}}Response{{{}}} 对象,它也是一个有效的WSGI response,和调用{{{}}}start_response{{{}}}有关的。
Line 72: Line 56:
    def HelloController(environ, start_response):
        return Response('Hello World!')

你还可以使用``render()````render_response()``,像你在一个通常的controller action里一样。
 . def HelloController(environ, start_response):
  . return Response('Hello World!')
你还可以使用{{{}}}render(){{{}}}{{{}}}render_response(){{{}}},像你在一个通常的controller action里一样。
Line 81: Line 64:
    class HelloController:
        def __call__(self, environ, start_response):
            start_response('200 OK', [('Content-Type','text/html')])
            return ['Hello World!']
 . class HelloController:
  . def __call__(self, environ, start_response):
   . start_response('200 OK', [('Content-Type','text/html')]) return ['Hello World!']
所有在config/middleware.py中定义的标准pylons middleware依然还是有用的。
Line 86: Line 69:
所有在``config/middleware.py``中定义的标准pylons middleware依然还是有用的。
Line 88: Line 70:
Running a WSGI Application From Within a Controller
---------------------------------------------------
Line 91: Line 71:
很多情况你不想用一个WSGI application来替换你的完整controller,只想简单地从一个controller action运行一个WSGI application。如果你的project被称为``test``,你有一个WSGI application ``wsgi_app``,你可以这样做: == Running a WSGI Application From Within a Controller ==

很多情况你不想用一个WSGI application来替换你的完整controller,只想简单地从一个controller action运行一个WSGI application。如果你的project被称为{{{}}}test{{{}}},你有一个WSGI application {{{}}}wsgi_app{{{}}},你可以这样做:
Line 95: Line 77:
    from test.lib.base import *  . from test.lib.base import * def wsgi_app(environ, start_response):
  . start_response('200 OK',[('Content-type','text/html')])
  return ['<html>\n<body>\nHello World!\n</body>\n</html>']
 class HelloController(BaseController):
  . def index(self):
   . return wsgi_app(request.environ, self.start_response)
   .
== Configuring Middleware Within a Pylons Application ==
Line 97: Line 86:
    def wsgi_app(environ, start_response):
        start_response('200 OK',[('Content-type','text/html')])
        return ['<html>\n<body>\nHello World!\n</body>\n</html>']

    class HelloController(BaseController):
        def index(self):
            return wsgi_app(request.environ, self.start_response)

Configuring Middleware Within a Pylons Application
--------------------------------------------------

一个pylons applcation的middleware堆栈是直接写在项目的``config/middleware.py``文件中。也就是说你可以从堆栈中增加和移除你选择的部分。
一个pylons applcation的middleware堆栈是直接写在项目的{{{}}}config/middleware.py{{{}}}文件中。也就是说你可以从堆栈中增加和移除你选择的部分。
Line 116: Line 94:
    # YOUR MIDDLEWARE
   
# Put your own middleware here, so that any problems are caught by the error
   
# handling middleware underneath
         class KeyAdder:
        def __init__(self, app, key, value):
            self.app = app
           
if '.' not in key:
                raise Exception("WSGI environ keys must contain a '.' character")
            self.key = key
           
self.value = value
                    def __call__(self, environ, start_response):
            environ[key] = value
           
return self.app(environ, start_response)
                 app = KeyAdder(app, 'test.hello', 'Hello World')
 . # YOUR MIDDLEWARE # Put your own middleware here, so that any problems are caught by the error # handling middleware underneath
 class KeyAdder:
  . def __init__(self, app, key, value):
   . self.app = app if '.' not in key:
    . raise Exception("WSGI environ keys must contain a '.' character")
   self.key = key self.value = value
  def __call__(self, environ, start_response):
   . environ[key] = value return self.app(environ, start_response)
 app = KeyAdder(app, 'test.hello', 'Hello World')
Line 138: Line 107:
    return Response(request.environ['test.hello'])

你可以看到``Hello World!``信息了。
 . return Response(request.environ['test.hello'])
你可以看到{{{}}}Hello World!{{{}}}信息了。
Line 144: Line 112:
    *改变environ字典
    *改变状态
    *改变HTTP头信息
    *改变application的response body
 * 改变environ字典
 * 改变状态
 * 改变HTTP头信息
 * 改变application的response body
因为作为middleware可以做以上的事,你就可以创建authentication代码,错误处理等等,但是WSGI更有意义的是可能已经有人做好了相关的组件了。具体的你可以参见 {{{wsgi.org middleware list <http://wsgi.org/wsgi/Middleware_and_Utilities>}}}_ 或{{{Paste project <http://pythonpaste.org>}}}_,重用已经存在的middleware。
Line 149: Line 118:
因为作为middleware可以做以上的事,你就可以创建authentication代码,错误处理等等,但是WSGI更有意义的是可能已经有人做好了相关的组件了。具体的你可以参见 `wsgi.org middleware list <http://wsgi.org/wsgi/Middleware_and_Utilities>`_ 或`Paste project <http://pythonpaste.org>`_,重用已经存在的middleware。
Line 151: Line 119:
The Cascade
-----------
Line 154: Line 120:
在你的project中的``config/middleware.py``文件,middleware堆栈的最后,你可以发现其中的一个片断叫cascade: == The Cascade ==

在你的project中的{{{}}}config/middleware.py{{{}}}文件,middleware堆栈的最后,你可以发现其中的一个片断叫cascade:
Line 157: Line 125:
    # @@@ Cascade @@@     app = Cascade([static_app, javascripts_app, app])
     传入application的一个列表,``Cascade``将会按顺序执行。如果有一个返回404状态码,

. # @@@ Cascade @@@ app = Cascade([static_app, javascripts_app, app])
传入application的一个列表,{{{}}}Cascade{{{}}}将会按顺序执行。如果有一个返回404状态码,

Pylons Support for the Web Server Gateway Interface

:author: James Gardner

:date: 2006-07-23

Web Server Gateway Interface(WSGI)是python社区公认的规范,它旨在使得python frameworks,middleware和server之间互操作性成为可能。

尽管大多数python frameworks都允许它们的应用都作为WSGI应用来运行,而pylons 0.9 WSGI集成度更高,在全部堆栈中支持WSGI。可以预见,随着其他framework支持wsgi,我们将看到在python web开发中进入崭新的阶段。

WSGI的规则实际上非常简单,但是要解释清楚确是相当困难。要了解全部的相关信息,你要去http://www.python.org/peps/ppp-0333.html看pep 333。

这篇指南会给你一个基本知识,教你在pylons怎样使用WSGI application和middleware.

Paste and WSGI

大部分pylons的WSGI的能力得益于它紧密集成的Paste。Paste提供了相当多,而且必要的工具和middleware来部署WSGI application。它可以被看作一个相当底层的WSGI framework,它是为其他构建其上的web framework而设计的,pylons只是完全利用paste的其中一个framework。

如果你想,你可以从你的pylons配置文件中得到WSGI application 对象。比如:

.. code-block:: Python

  • from paste.deploy import loadapp wsgi_app = loadapp('config:/path/to/config.ini')

然后你使用一个WSGI server来启动这个文件的服务。这是一个使用包含在python 2.5中的wsgiref实现的一段代码:

.. code-block:: Python

  • from paste.deploy import loadapp wsgi_app = loadapp('config:/path/to/config.ini') from wsgiref import simple_server

    httpd = simple_server.WSGIServer((,8000), simple_server.WSGIRequestHandler) httpd.set_app(wsgi_app) httpd.serve_forever()

在pylons项目的开发中你可以使用paster serve命令来合并上面的两步,从配置文件创建一个WSGI app,并可以直接使用这个配置文件从而启动服务。

因为启动的pylons应用是一个WSGI application,就意味着你可以像处理WSGI application一样来做同样的事情。举个例子,给它加一个middleware chain或者通过fastcgi/scgi/cgi/mod_python/ajp来启动服务或者单独运行。

你也可以配置额外的WSGI middleware,application和更多直接使用的配置文件。更多不同的选项,你可以从Paste Deploy Documentation <http://pythonpaste.org/deploy/>_看到,这里我们就不重复了。

Using a WSGI Application as a Pylons 0.9 Controller

在pylons 0.9 controllers是从pylons.controllers.WSGIController派生而来,并且也是一个有效的WSGI application。除非你的controller是从以前的pylons.controllers.Controller派生得来,它也是被假定是一个WSGI application。这就是说你不必在你的controller中使用一个Pylons controller,只要你给它同一个名字,任何WSGI application都能起作用。举例来说,假如你用paster controller hello命令加了一个hello controller,你可以改变它:

.. code-block:: Python

  • def HelloController(environ, start_response):

    • start_response('200 OK', [('Content-Type','text/html')]) return ['Hello World!']

或者使用yield语句:

.. code-block:: Python

  • def HelloController(environ, start_response):

    • start_response('200 OK', [('Content-Type','text/html')]) yield 'Hello ' yield 'World!'

或者使用标准的pylons Response 对象,它也是一个有效的WSGI response,和调用start_response有关的。

.. code-block:: Python

  • def HelloController(environ, start_response):

    • return Response('Hello World!')

你还可以使用render()render_response(),像你在一个通常的controller action里一样。

你也可以在一个class中像写一个function一样来写你的WSGI application。

.. code-block:: Python

  • class HelloController:

    • def call(self, environ, start_response):

      • start_response('200 OK', [('Content-Type','text/html')]) return ['Hello World!']

所有在config/middleware.py中定义的标准pylons middleware依然还是有用的。

Running a WSGI Application From Within a Controller

很多情况你不想用一个WSGI application来替换你的完整controller,只想简单地从一个controller action运行一个WSGI application。如果你的project被称为test,你有一个WSGI application wsgi_app,你可以这样做:

.. code-block:: Python

  • from test.lib.base import * def wsgi_app(environ, start_response):
    • start_response('200 OK',[('Content-type','text/html')])

      return ['<html>\n<body>\nHello World!\n</body>\n</html>']

    class HelloController(BaseController):

    • def index(self):
      • return wsgi_app(request.environ, self.start_response)

Configuring Middleware Within a Pylons Application

一个pylons applcation的middleware堆栈是直接写在项目的config/middleware.py文件中。也就是说你可以从堆栈中增加和移除你选择的部分。

.. Warning:: 如果移除掉缺省的middleware,你将会发现pylons不能正常运转了!

比如,如果你想加一个middleware,它是用来给environ字典中加一个新关键字:

.. code-block:: Python

  • # YOUR MIDDLEWARE # Put your own middleware here, so that any problems are caught by the error # handling middleware underneath

    class KeyAdder:

    • def init(self, app, key, value):

      • self.app = app if '.' not in key:
        • raise Exception("WSGI environ keys must contain a '.' character")
        self.key = key self.value = value

      def call(self, environ, start_response):

      • environ[key] = value return self.app(environ, start_response)

    app = KeyAdder(app, 'test.hello', 'Hello World')

然后在你的controller:

.. code-block:: Python

  • return Response(request.environ['test.hello'])

你可以看到Hello World!信息了。

当然,这不是特别有用的东西。middleware类可以做四样事中一样或多样:

  • 改变environ字典
  • 改变状态
  • 改变HTTP头信息
  • 改变application的response body

因为作为middleware可以做以上的事,你就可以创建authentication代码,错误处理等等,但是WSGI更有意义的是可能已经有人做好了相关的组件了。具体的你可以参见 wsgi.org middleware list <http://wsgi.org/wsgi/Middleware_and_Utilities>_ 或Paste project <http://pythonpaste.org>_,重用已经存在的middleware。

The Cascade

在你的project中的config/middleware.py文件,middleware堆栈的最后,你可以发现其中的一个片断叫cascade:

.. code-block:: Python

  • # @@@ Cascade @@@ app = Cascade([static_app, javascripts_app, app])

传入application的一个列表,Cascade将会按顺序执行。如果有一个返回404状态码,

PyLons/wsgi (last edited 2009-12-25 07:11:09 by localhost)