(機械翻訳)ピラミッドのクイックツアー

ピラミッドは小さなものから始まり大きなものに仕上げます。 Pyramidのこのクイックツアー*は、あなたがPython Webフレームワークの初心者であろうと、急いでプロであろうと、Pyramidを評価したい人のためのものです。各トピックの詳細な扱いについては、:ref: `quick_tutorial`を試してみてください。

このツアーでサンプルコードをカットアンドペーストしたい場合は、&quot;docs / quick_tour &quot;ディレクトリのPyramidリポジトリにあるソースコードを参照してください。 <https://github.com/Pylons/pyramid/> `。ソースコードをダウンロードした場合は、同じ場所にツアーがあります。

インストール

標準のPython環境設定を済ませたら、Pyramidを使い始めるのは簡単です。残念ながら&quot;標準&quot;はPythonではそれほど単純ではありません。このクイックツアーでは、Python <https://www.python.org/downloads/> _、 venv <https://packaging.python.org/en/latest/projects/#venv> _(または Python 2.7用のvirtualenv <https://packaging.python.org/en/latest/projects/#virtualenv> `_)、 pip <https://packaging.python.org/en/latest/projects/#pip> `_、``setuptools <https://packaging.python.org/en/latest/projects/#easy-install> `_。

ちょっとしたタイピングを省き、仮想環境にインストールされたモジュール、スクリプト、パッケージを確実に使用するために、環境変数も設定します。

たとえば、LinuxのPython 3.6以降では、次のようになります。

# set an environment variable to where you want your virtual environment
$ export VENV=~/env
# create the virtual environment
$ python3 -m venv $VENV
# install pyramid
$ $VENV/bin/pip install pyramid
# or for a specific released version
$ $VENV/bin/pip install "pyramid==1.9.2"

Windowsの場合:

# set an environment variable to where you want your virtual environment
c:\> set VENV=c:\env
# create the virtual environment
c:\> python -m venv %VENV%
# install pyramid
c:\> %VENV%\Scripts\pip install pyramid
# or for a specific released version
c:\> %VENV%\Scripts\pip install "pyramid==1.9.2"

もちろん、PyramidはPython 2.7以降でうまく動作します。このクイックツアーの例もそうです。簡単にするためにPython 3を公開しています。 Pyramidは2011年10月にPython 3をサポートしていました。簡単にするために、残りの例ではUNIXコマンドのみを表示します。

参考

参照::ref: クイックチュートリアルセクションの要件<qtut_requirements> `、:ref: installing_unix`、:ref: あなたがインストールする前に<installing_chapter> `、:ref:`ソースbin / activateの代わりに$ VENV / bin / pipを使用してからpip <venv-bin-pip-vs-source-bin-activate> `、および:ref: WindowsシステムへのPyramidのインストール<installing_windows> `

こんにちは世界

Microframeworksは、学習が非常に小さな第一歩から最も効果的に始まることを示しています。 Pyramidには小さなアプリケーションがあります:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
from wsgiref.simple_server import make_server
from pyramid.config import Configurator
from pyramid.response import Response


def hello_world(request):
    return Response('<h1>Hello World!</h1>')


if __name__ == '__main__':
    with Configurator() as config:
        config.add_route('hello', '/')
        config.add_view(hello_world, route_name='hello')
        app = config.make_wsgi_app()
    server = make_server('0.0.0.0', 6543, app)
    server.serve_forever()

この簡単な例は簡単に実行できます。これを `` app.py``として保存し、それを実行してください:

$ $VENV/bin/python ./app.py

次にhttp:// localhost:6543 /をブラウザで開き、 `` Hello World! ``というメッセージが表示されます。

Python Webプログラミングの新機能?そうであれば、モジュール内のいくつかの行に説明があります:

  1. Line 10. if __name__ == '__main__': is Python's way of saying "Start here when running from the command line".
  2. Lines 11-13. Use Pyramid's configurator in a context manager to connect view code to a particular URL route.
  3. *ライン6-7 *。 :term: `response`を生成するビューコードを実装します。
  4. Lines 14-16. Publish a WSGI app using an HTTP server.

この例に示すように、:term: `configurator`はピラミッドの開発において中心的な役割を果たします。 doc: `../ narr / configuration`を介して疎結合部分からアプリケーションをビルドすることはピラミッドの中心的なアイデアです。このクイックツアーでは定期的に再考する予定です。

参考

参照::ref: クイックチュートリアルHello World <qtut_hello_world> `、:ref: firstapp_chapter`、:ref: `1つのファイル内のTodoリストアプリケーション<cookbook:single-file-tutorial> `

Webリクエストとレスポンスの処理

Web用に開発するとは、Web要求を処理することを意味します。これはWebアプリケーションの重要な部分であるため、Web開発者はWeb要求のための堅牢で成熟したソフトウェアを必要とします。

Pyramidは、Python Web開発の既存の世界(仮想環境、パッケージ、cookiecutters、Python 3を最初に採用したものの1つなど)に常にうまく収まっています。ピラミッドは要求と応答の処理のためによく使われる:term: WebOb Pythonライブラリに目を向けました。上の例では、ピラミッドは `` hello_world``を `` request``と呼んでいます:ref: `WebOb <webob_chapter> `

実際に要求と応答のいくつかの機能を見てみましょう:

def hello_world(request):
    # Some parameters from a request such as /?name=lisa
    url = request.url
    name = request.params.get('name', 'No Name Provided')

    body = 'URL %s with name: %s' % (url, name)
    return Response(
        content_type="text/plain",
        body=body
    )

このピラミッドビューでは、 `` request.url``からURLを取得します。また、ブラウザでhttp:// localhost:6543 /?name = aliceにアクセスした場合、その名前はレスポンスの本文に含まれます:

URL http://localhost:6543/?name=alice with name: alice

最後に、レスポンスのコンテンツタイプを設定し、レスポンスを返します。

参考

参照::ref: クイックチュートリアルリクエストとレスポンス<qtut_request_response> `と:ref: webob_chapter`です。

ビュー

上の例では、 `` hello_world``関数は&quot;view &quot;です。ピラミッドビューでは、Web要求を受け入れて応答を返す主要な方法があります。

これまでの例では、すべてを1つのファイルに格納しています。

  • ビュー関数
  • コンフィギュレータへの登録
  • それをURLにマップするルート
  • WSGIアプリケーションランチャ

ビューを独自の `` views.py``モジュールに移動し、 `` app.py``を変更してそのモジュールをスキャンし、ビューを設定するデコレータを探しましょう。

最初に改訂された `` app.py``:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
from wsgiref.simple_server import make_server
from pyramid.config import Configurator

if __name__ == '__main__':
    with Configurator() as config:
        config.add_route('home', '/')
        config.add_route('hello', '/howdy')
        config.add_route('redirect', '/goto')
        config.add_route('exception', '/problem')
        config.scan('views')
        app = config.make_wsgi_app()
    server = make_server('0.0.0.0', 6543, app)
    server.serve_forever()

ルートを追加しましたが、ビューコードも削除しました。ビューとその登録(デコレータ経由)は `` views.py``モジュールにあり、 `` config.scan( &#39;views&#39;) ``でスキャンされます。

要求と応答の処理に焦点を当てた `` views.py``モジュールが追加されました:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
from pyramid.compat import escape

from pyramid.httpexceptions import HTTPFound
from pyramid.response import Response
from pyramid.view import view_config


# First view, available at http://localhost:6543/
@view_config(route_name='home')
def home_view(request):
    return Response('<p>Visit <a href="/howdy?name=lisa">hello</a></p>')


# /howdy?name=alice which links to the next view
@view_config(route_name='hello')
def hello_view(request):
    name = request.params.get('name', 'No Name')
    body = '<p>Hi %s, this <a href="/goto">redirects</a></p>'
    # pyramid.compat.escape to prevent Cross-Site Scripting (XSS) [CWE 79]
    return Response(body % escape(name))


# /goto which issues HTTP redirect to the last view
@view_config(route_name='redirect')
def redirect_view(request):
    return HTTPFound(location="/problem")


# /problem which causes a site error
@view_config(route_name='exception')
def exception_view(request):
    raise Exception()

我々は4つの視点を持ち、それぞれが別の視点につながっています。 http:// localhost:6543 /で始めると、次のビューへのリンクを含む応答が得られます。 `` hello_view``(URL `` / howdy``にあります)は `` redirect_view``へのリンクを持ち、最終的なビューにリダイレクトします。

以前は、 `` config.add_view``がビューを設定する一つの方法として見えました。このセクションでは、 `` @ view_config``について説明します。 Pyramidの設定は、前の例の `` config.add_view``のように、term: `必須の設定`をサポートしています。 Python:term: `decorator`がビューの上の行に置かれている:term:`宣言的な設定 &#39;を使うこともできます。どちらの方法も同じ最終的な構成になります。したがって、通常は単に味の問題です。

参考

参照::ref: クイックチュートリアルビュー<qtut_views> `、:doc: ../ narr / views`、:doc: ../ narr / viewconfig、および:ref:` debugging_view_configuration`です。

ルーティング

Webアプリケーションの作成は、通常、洗練されたURL設計を意味します。私たちは要求と見解のためにいくつかのピラミッド機械を見ただけです。ルーティングに役立つ機能を見てみましょう。

上では、PyramidのビューへのURLのルーティングの基本を確認しました。

  • プロジェクトの&quot;setup &quot;コードは、URLの一部と一致するときに使用されるルート名を登録します。
  • そのルート名に対してビューが呼び出されるように設定されています。

注釈

なぜこれを2回するのですか?他のPython Webフレームワークを使用すると、ルートを作成して1つのステップでビューに関連付けることができます。 :ref: `routes_need_ordering`に示すように、複数のルートが同じURLパターンと一致する可能性があります。推測を支援する方法を提供するのではなく、Pyramidでは順序を明示することができます。ピラミッドは、この問題を回避するための設備も提供しています。

URLの一部をビューのデータとして利用できるようにするにはどうすればよいですか?このルート宣言は、たとえば次のように使用できます。

6
        config.add_route('hello', '/howdy/{first}/{last}')

これにより、 `` / howdy / amy / smith`のようなURLは、 ``最初に ``````最後に ``スミス `に割り当てられます。このデータをビューで使用することができます。

5
6
7
8
@view_config(route_name='hello')
def hello_world(request):
    body = '<h1>Hi %(first)s %(last)s!</h1>' % request.matchdict
    return Response(body)

`` request.matchdict``には、ルート宣言の&quot;置換パターン&quot;(中括弧)と一致するURLの値が含まれています。この情報は、あなたのビューで使用することができます。

参考

参照::ref: クイックチュートリアルルーティング<qtut_routing> `、:doc: ../ narr / urldispatch`、:ref: debug_routematch_section、:doc:` ../ narr / router`です。

テンプレート

ああ。私たちは独自の ``レスポンス ``を作り、レスポンスボディにHTMLを埋めました。通常、PythonではHTML文字列を直接埋め込むことはありませんが、代わりにテンプレート言語を使用します。

Pyramidは、特定のデータベースシステム、フォームライブラリなどを強制するものではありません。それは交換可能性を奨励します。これは幸運なことにテンプレートにも当てはまります。開発者はテンプレート言語についての強い見解を持っています。つまり、Pylonsプロジェクトは、Chameleon、Jinja2、Makoのバインドを正式にサポートしています。このステップでは、カメレオンを使いましょう。

私たちのPyramidアプリケーションで、カメレオンを:term: renderer &#39;として有効にするPyramid:term: add-on`という `` pyramid_chameleon``を追加しましょう:

$ $VENV/bin/pip install pyramid_chameleon

パッケージがインストールされた状態で、テンプレートバインディングを設定に `` app.py``で含めることができます:

6
7
8
        config.add_route('hello', '/howdy/{name}')
        config.include('pyramid_chameleon')
        config.scan('views')

`` views.py``ファイルを変更しましょう:

1
2
3
4
5
6
from pyramid.view import view_config


@view_config(route_name='hello', renderer='hello_world.pt')
def hello_world(request):
    return dict(name=request.matchdict['name'])

ああ、それは良く見えます。私たちはPythonコードに焦点を当てています。私たちの `` @ view_config``デコレータはテンプレートファイルを指すa:term: renderer`を指定します。私たちの見解はデータを返すだけで、テンプレート ` hello_world.pt``に与えられます:

<!DOCTYPE html>
<html lang="en">
<head>
    <title>Quick Glance</title>
</head>
<body>
<h1>Hello ${name}</h1>
</body>
</html>

私たちのビューは `` dict(name = request.matchdict [&#39;name&#39;]) ``を返すので、 `` $ {name} ``を介してテンプレート内の変数として `` name``を使うことができます。

参考

参照::ref: クイックチュートリアルテンプレート<qtut_templating> `、:doc: ../ narr / templates`、:ref: debugging_templates、:ref:` available_template_system_bindings`です。

Jinja2を使ったテンプレート

私たちは、ピラミッドがテンプレート言語を別のものよりも好まないと言っただけです。それを証明する時間。 Jinja2は、Djangoのテンプレートをモデルにした、人気のあるテンプレートシステムです。ピラミッドのアプリケーションでJinja2をterm: renderer &#39;として使用できるようにするPyramid:term: add-on`を `` pyramid_jinja2``に追加しましょう:

$ $VENV/bin/pip install pyramid_jinja2

パッケージがインストールされたら、テンプレートバインディングを設定に含めることができます:

6
7
8
        config.add_route('hello', '/howdy/{name}')
        config.include('pyramid_jinja2')
        config.scan('views')

ビューの唯一の変更点はレンダラーを `` .jinja2``ファイルで指すことです:

4
5
6
@view_config(route_name='hello', renderer='hello_world.jinja2')
def hello_world(request):
    return dict(name=request.matchdict['name'])

私たちのJinja2テンプレートは、以前のテンプレートに非常に似ています:

<!DOCTYPE html>
<html lang="en">
<head>
    <title>Hello World</title>
</head>
<body>
<h1>Hello {{ name }}!</h1>
</body>
</html>

Pyramidのテンプレートアドオンは、新しい種類のレンダラーをアプリケーションに登録します。レンダラー登録は、さまざまな種類のファイル拡張子にマップされます。この場合、拡張子を `` .pt``から `` .jinja2``に変更すると、 `` pyramid_jinja2``レンダラを通してビュー応答が渡されます。

参考

参照::ref: クイックチュートリアルJinja2 <qtut_jinja2> `、 Jinja2ホームページ<http://jinja.pocoo.org/> _、and:ref: pyramid_jinja2概要<jinja2:overview> `

静的資産

もちろん、Webは単にマークアップ以上のものです。 CSS、JS、イメージなどの静的アセットが必要です。ピラミッドがいくつかの静的資産を提供するディレクトリにWebアプリケーションを向けてみましょう。まず、 `` app.py``の:term: `configurator`をもう一度呼び出してみましょう:

6
7
8
        config.add_route('hello', '/howdy/{name}')
        config.add_static_view(name='static', path='static')
        config.include('pyramid_jinja2')

これは私たちのWSGIアプリケーションに、http:// localhost:6543 / static /の下のリクエストをPythonモジュールの横にある `` static``ディレクトリ内のファイルとディレクトリにマップするように指示します。

次に `` static``という名前のディレクトリを作り、そこに `` app.css``を配置します:

body {
    margin: 2em;
    font-family: sans-serif;
}

今私たちがする必要があるのは、 `` <head> `` Jinja2テンプレート `` hello_world.jinja2``の ``

4
5
6
    <title>Hello World</title>
    <link rel="stylesheet" href="/static/app.css"/>
</head>

このリンクは、CSSが `` / static / ``で始まるURLにあると想定しています。サイトが後で `` / somesite / static / ``の下で動かされるとどうなるでしょうか?あるいは、Web開発者がディスク上の配置を変更するのでしょうか? Pyramidには、URL生成に柔軟性を持たせるためのヘルパーが用意されています。

4
5
6
    <title>Hello World</title>
    <link rel="stylesheet" href="{{ request.static_url('__main__:static/app.css') }}"/>
</head>

`` request.static_url``を使って静的アセットへの完全なURLを生成することで、コンフィグレーションとの同期を維持し、後でリファクタリングの柔軟性を得ることができます。

参考

参照::ref: クイックチュートリアル静的アセット<qtut_static_assets> `、:doc: ../ narr / assets`、:ref: prevent_http_caching、および:ref:` influencing_http_caching`です。

JSONを返す

現代のWebアプリケーションはレンダリングされたHTML以上のものです。動的ページでは、JSONとしてサーバーデータを要求することで、JavaScriptを使用してブラウザのUIを更新します。 PyramidはこれをJSONレンダラーでサポートしています:

 9
10
11
@view_config(route_name='hello_json', renderer='json')
def hello_json(request):
    return [1, 2, 3]

これは、PythonのJSONサポートを呼び出してJSONにデータをシリアル化し、適切なHTTPヘッダーを設定する、JSON:term: `renderer`を通していくつかのデータを返すビューを結び付けます。

私たちのアプリが `` hello.json``のリクエストにどのように応答するかを知るために、 `` app.py``へのルートを追加する必要もあります。

6
7
8
        config.add_route('hello', '/howdy/{name}')
        config.add_route('hello_json', 'hello.json')
        config.add_static_view(name='static', path='static')

参考

参照::ref: クイックチュートリアルJSON <qtut_json> `、:ref: views_which_use_a_renderer`、:ref: json_renderer、:ref:` adding_and_overriding_renderers`です。

ビュークラス

これまでのところ、われわれの見解は単純で自由な機能であった。あなたの意見は何度も関連しています。同じデータを表示または操作する方法が異なる場合や、複数の操作を処理するREST APIの場合があります。これらをまとめて:ref: `viewクラス<class_as_view>以下の目標を達成します。

  • グループビュー
  • 反復的なデフォルトを一元化する
  • 州とヘルパーを共有する

以下は、 &quot;Hello World&quot;の例です。フォームの表示、変更の保存、または `` views.py``の削除ボタンを押します:

 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# One route, at /howdy/amy, so don't repeat on each @view_config
@view_defaults(route_name='hello')
class HelloWorldViews:
    def __init__(self, request):
        self.request = request
        # Our templates can now say {{ view.name }}
        self.name = request.matchdict['name']

    # Retrieving /howdy/amy the first time
    @view_config(renderer='hello.jinja2')
    def hello_view(self):
        return dict()

    # Posting to /howdy/amy via the "Edit" submit button
    @view_config(request_param='form.edit', renderer='edit.jinja2')
    def edit_view(self):
        print('Edited')
        return dict()

    # Posting to /howdy/amy via the "Delete" submit button
    @view_config(request_param='form.delete', renderer='delete.jinja2')
    def delete_view(self):
        print('Deleted')
        return dict()

ご覧のとおり、3つのビューは論理的にグループ化されています。具体的には:

  • `` / howdy / amy``に行くと最初のビューが返されます。このURLは、オプションで `` @ view_defaults``を使って集中的に設定する `` hello``ルートにマップされています。
  • 2番目のビューは、フォームデータに `` form.edit``を含むフィールドが含まれている場合に返されます。たとえば、 `` <input type="submit" name="form.edit" value="Save"> ``。このルールは、そのビューの `` @ view_config``で指定されます。
  • 3番目のビューは、 `` <input type="submit" name="form.delete" value="Delete"> ``

1つの経路だけが必要で、ビュークラスの上の1つの場所に記載されています。また、 `` name``の代入は `` __init__``関数で行われます。私たちのテンプレートは `` {{view.name}} ``を使うことができます。

ピラミッド・ビュー・クラスは、組み込みおよびカスタムの述部と組み合わされて、さらに多くの機能を提供します。

  • ファンクションビューと同じビュー構成パラメータ
  • request_param`、 `` request_method``、 `` accept``、 `` header``、 `` xhr``、containmentなどのリクエストやデータの情報に基づいて、複数のビューにつながる1つのルート``、 `` custom_predicates``

参考

参照::ref: クイックチュートリアルのビュークラス<qtut_view_classes> `、:ref:`クイックチュートリアル他のビュークラス<qtut_more_view_classes> `、:ref: class_as_view`です。

cookiecuttersによるクイックプロジェクトの起動

これまでのところ、* Quick Tour *のすべてを単一のPythonファイルとして実行しました。 Pythonパッケージなし、構造体なし。しかし、ほとんどのピラミッドプロジェクトはこのように開発されていません。

開始プロセスを簡単にするために、Pylonsプロジェクトは次のものを提供しています。プロジェクトテンプレートからサンプルPyramidプロジェクトを生成するterm: cookiecutter これらのcookiecuttersはPyramidとその依存関係もインストールします。

まず、cookiecutterをインストールする必要があります。

$ $VENV/bin/pip install cookiecutter

cookiecutterの `` pyramid-cookiecutter-starter``を使って、現在のディレクトリにピラミッドプロジェクトを作成し、次のコマンドのためにプロンプ​​トに値を入力してみましょう。

$ $VENV/bin/cookiecutter gh:Pylons/pyramid-cookiecutter-starter --checkout 1.9-branch

最初の項目の入力を求められたら、returnキーを押してデフォルトの `` yes``を受け入れます。

You've cloned ~/.cookiecutters/pyramid-cookiecutter-starter before.
Is it okay to delete and re-clone it? [yes]: yes
project_name [Pyramid Scaffold]: hello_world
repo_name [hello_world]: hello_world
Select template_language:
1 - jinja2
2 - chameleon
3 - mako
Choose from 1, 2, 3 [1]: 1

次に、次のコマンドを実行します。

# Change directory into your newly created project.
$ cd hello_world
# Create a new virtual environment...
$ python3 -m venv env
# ...where we upgrade packaging tools...
$ env/bin/pip install --upgrade pip setuptools
# ...and into which we install our project and its testing requirements.
$ env/bin/pip install -e ".[testing]"
# Reset our environment variable for a new virtual environment.
$ export VENV=~/hello_world/env

Pythonの標準(パッケージング)とPyramidの設定を適切にセットアップして、完全機能を備えたPyramidプロジェクトの方向に向かっています。これには、アプリケーションを実行するための新しい方法が含まれます。

$ $VENV/bin/pserve development.ini

`` pserve``と設定をもっと深く見てみましょう。

参考

参照::ref: クイックチュートリアルCookiecutters <qtut_cookiecutters> `、:ref: project_narr`、:doc: `../ narr / cookiecutters`です。

`` pserve``で動作するアプリケーション

cookiecutterに入る前に、私たちのプロジェクトでは、いくつかの操作の詳細がコードに混在していました。なぜ私のメインコードは、私が欲しいHTTPサーバーと、実行するポート番号を気にする必要がありますか?

`` pserve``はPyramidのアプリケーションランナーで、コードから操作の詳細を分離します。 Pyramidをインストールすると、 `` pserve``という小さなコマンドプログラムがあなたの `` bin``ディレクトリに書き出されます。このプログラムは実行可能なPythonモジュールです。それは非常に小さく、ほとんどの脳をインポートによって取得します。

`` --help``で `` pserve``を実行すると、そのオプションのいくつかを見ることができます。そうすることで、 `` pserve``にあなたの開発ファイルを見て、変更時にサーバをリロードするように要求することができます:

$ $VENV/bin/pserve development.ini --reload

`` pserve``コマンドには他の多くのオプションと操作があります。しかし、ほとんどの作業は、あなたが `` pserve``に提供する設定ファイルで表現されているように、プロジェクトの配線から来ています。この設定ファイルを見てみましょう。

参考

参照::ref: what_is_this_pserve_thing

`` .ini``ファイルによる設定

*クイックツアー*では、Pyramidの設定システムに初めて触れました。その時点で、私たちはすべての設定をPythonコードで行いました。たとえば、私たちのHTTPサーバー用に選択されたポート番号は、Pythonコードのところにありました。私たちのcookiecutterはこの決定を `` development.ini``ファイルに移しました:

###
# app configuration
# https://docs.pylonsproject.org/projects/pyramid/en/latest/narr/environment.html
###

[app:main]
use = egg:hello_world

pyramid.reload_templates = true
pyramid.debug_authorization = false
pyramid.debug_notfound = false
pyramid.debug_routematch = false
pyramid.default_locale_name = en
pyramid.includes =
    pyramid_debugtoolbar

# By default, the toolbar only appears for clients from IP addresses
# '127.0.0.1' and '::1'.
# debugtoolbar.hosts = 127.0.0.1 ::1

###
# wsgi server configuration
###

[server:main]
use = egg:waitress#main
listen = localhost:6543

###
# logging configuration
# https://docs.pylonsproject.org/projects/pyramid/en/latest/narr/logging.html
###

[loggers]
keys = root, hello_world

[handlers]
keys = console

[formatters]
keys = generic

[logger_root]
level = INFO
handlers = console

[logger_hello_world]
level = DEBUG
handlers =
qualname = hello_world

[handler_console]
class = StreamHandler
args = (sys.stderr,)
level = NOTSET
formatter = generic

[formatter_generic]
format = %(asctime)s %(levelname)-5.5s [%(name)s:%(lineno)s][%(threadName)s] %(message)s

すばやく高レベルの外観を取ってみましょう。最初に `` .ini``ファイルはセクションに分割されます:

  • `` [app:main] ``はWSGIアプリケーションを設定します
  • `` [server:main] ``はWSGIサーバー設定を保持しています
  • その後のさまざまなセクションで、Pythonロギングシステムを設定します

この構成では、いくつかの決定事項があります。

  1. WSGI app: What package has our WSGI application in it? use = egg:hello_world in the app section tells the configuration what application to load.
  2. *自動テンプレートリロードによる簡単な開発:*開発モードでは、Jinja2テンプレートを編集するときにサーバーを再起動する必要はありません。 `` pyramid.reload_templates = true``はこのポリシーを設定します。これは本番環境では異なる場合があります。
  3. ウェブサーバーの選択: `` use = egg:waitress#main``は `` pserve``に `` waitress``サーバーを使用するよう指示します。
  4. インタフェース: `` listen = localhost:6543``は、IPv4とIPv6の両方についてポート6543上のすべてのインタフェースを待ち受けるように `` waitress``を指示します。

さらに、このcookiecutterによって生成された `` development.ini``は、Pythonの標準ロギングをビルドしました。ここでは、コンソールに、たとえば、トレースバック情報だけでなく、来るすべてのリクエストのログが表示されます。

参考

参照::ref: クイックチュートリアルアプリケーションの設定<qtut_ini> `、:ref: environment_chapter`と:doc: ../ narr / paste

`` debugtoolbar``による簡単な開発

基本を紹介しながら、開発とデバッグの生産性を上げる方法も示したいと考えています。たとえば、テンプレートのリロードについて説明したところで、アプリケーションリロードのために `` --reload``を前に示しました。

`` pyramid_debugtoolbar``は、あなたのブラウザでいくつかのツールを利用できる人気のPyramidアドオンです。プロジェクトに追加すると、構成に関するいくつかの点が示されます。

cookiecutter `` pyramid-cookiecutter-starter``は `` setup.py``にアドオン `` pyramid_debugtoolbar``を追加するようにパッケージを設定しています:

11
12
13
14
15
16
17
requires = [
    'plaster_pastedeploy',
    'pyramid',
    'pyramid_jinja2',
    'pyramid_debugtoolbar',
    'waitress',
]

以前に実行したときにインストールされました:

$ $VENV/bin/pip install -e ".[testing]"

`` pyramid_debugtoolbar``パッケージはPyramidアドオンです。つまり、その設定をWebアプリケーションに含める必要があります。 cookiecutterは、 `` pyramid.includes``ファシリティを使って `` development.ini``で既にこれを世話してくれました:

14
15
pyramid.includes =
    pyramid_debugtoolbar

ブラウザウィンドウの右側にピラミッドのロゴが表示されます。クリックすると、デバッグ情報への内密アクセスを可能にする新しいウィンドウが開きます。さらに、Webアプリケーションでエラーが発生した場合は、画面に素晴らしいトレースバックが表示されます。このツールバーを無効にしたい場合は、コードを変更する必要はありません。関連する `` .ini``設定ファイルの `` pyramid.includes``から削除することができます。

参考

参照::ref: クイックチュートリアルpyramid_debugtoolbar <qtut_debugtoolbar> `と:ref: pyramid_debugtoolbar <toolbar:overview> `

ユニットテストと `` py.test``

Yikes!私たちはこれを遠くに持っており、まだテストについて議論していません。これは、Pyramidがリリース前から完全なテストカバレッジに深いコミットメントを持っているため、特に厳しいです。

我々の `` pyramid-cookiecutter-starter`` cookiecutterは、ユニットテストと機能テストを1つずつ持つ `` tests.py``モジュールを生成しました。また、テストランナーとして `` py.test``、ビューテストを実行するための `` WebTest``、私たちに叫ぶ `` pytest-cov``ツールといったテスト要件を持つ `` setup.py``を設定しましたテストされていないコードの場合:

19
20
21
22
23
tests_require = [
    'WebTest >= 1.3.1',  # py3 compat
    'pytest',
    'pytest-cov',
]
43
44
45
    extras_require={
        'testing': tests_require,
    },

`` $ VENV / bin / pip install -e &quot;コマンドを実行したときにテスト要件をインストールしました。[testing] &quot; ``。これですべてのテストを実行できます:

$ $VENV/bin/py.test --cov --cov-report=term-missing

これにより、次の出力が得られます。

=========================== test session starts ===========================
platform darwin -- Python 3.6.0, pytest-3.0.5, py-1.4.32, pluggy-0.4.0
rootdir: /Users/stevepiercy/hello_world, inifile: pytest.ini
plugins: cov-2.4.0
collected 2 items

hello_world/tests.py ..

------------- coverage: platform darwin, python 3.6.0-final-0 -------------
Name                                      Stmts   Miss  Cover   Missing
-----------------------------------------------------------------------
hello_world/__init__.py                       8      0   100%
hello_world/views.py                          3      0   100%
-----------------------------------------------------------------------
TOTAL                                        11      0   100%


========================= 2 passed in 1.37 seconds =========================

私たちのテストは合格し、その適用範囲は完全です。私たちのテストはどのように見えましたか?

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import unittest

from pyramid import testing


class ViewTests(unittest.TestCase):
    def setUp(self):
        self.config = testing.setUp()

    def tearDown(self):
        testing.tearDown()

    def test_my_view(self):
        from .views import my_view
        request = testing.DummyRequest()
        info = my_view(request)
        self.assertEqual(info['project'], 'hello_world')


class FunctionalTests(unittest.TestCase):
    def setUp(self):
        from hello_world import main
        app = main({})
        from webtest import TestApp
        self.testapp = TestApp(app)

    def test_root(self):
        res = self.testapp.get('/', status=200)
        self.assertTrue(b'Pyramid' in res.body)

ピラミッドは、テストのセットアップとティアダウンで使用するテストライターのためのヘルパーを提供します。私たちの最初のテストは、ビューをインポートし、ダミーリクエストを行い、ビューが期待したものを返すかどうかを確認します。私たちの2番目のテストでは、要求からWebルートへの応答本文に、期待した内容が含まれていることが検証されています。

参考

参照::ref: クイックチュートリアルユニットテスト<qtut_unit_testing> `、:ref:`クイックチュートリアル機能テスト<qtut_functional_testing> `、および:ref: testing_chapter`

ロギング

Webアプリケーション内で何が起こっているのかを知ることは重要です。開発時には、出力を収集する必要があります。プロダクションでは、他の人がサイトを使用している状況を検出する必要があります。 *ロギング*が必要です。

幸いにもPyramidは通常のPythonのロギング手法を使用しています。あなたのプロジェクトの `` development.ini``ファイルには、いくつかの合理的なデフォルト値を設定する行がいくつかあります。次に、Pyramidによって送信されたメッセージが表示されます(たとえば、新しい要求が入った場合)。

あなたのコードにメッセージを記録したいのですか?あなたのPythonモジュールでは、 `` views.py``でロギングをインポートして設定します:

3
4
import logging
log = logging.getLogger(__name__)

あなたのコードでログメッセージを作成できるようになりました:

7
8
def my_view(request):
    log.debug('Some Message')

これは `` DEBUG``ログレベルの `` Some Message``を `` development.ini``のアプリケーション設定ロガーに記録します。それを制御するのは何ですか?設定ファイルのこれらの強調されたセクション

34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
[loggers]
keys = root, hello_world

[handlers]
keys = console

[formatters]
keys = generic

[logger_root]
level = INFO
handlers = console

[logger_hello_world]
level = DEBUG
handlers =
qualname = hello_world

私たちのアプリケーション、 `` hello_world``という名前のパッケージは、ロガーとしてセットアップされ、 `` DEBUG`以上のレベルでメッセージを記録するように設定されています。 http:// localhost:6543にアクセスすると、コンソールに次のように表示されます。

2016-12-25 03:03:57,059 DEBUG [hello_world.views:8][waitress] Some Message

参考

参照::ref: クイックチュートリアルロギング<qtut_logging> `と:ref: logging_chapter`です。

セッション

Webアプリケーションを使用する人は、半永久的なデータを保存する必要があるタスクを頻繁に実行します。たとえば、ショッピングカートです。これは:term: `session`と呼ばれます。

Pyramidにはセッションのための基本的な組み込みサポートがあります。 `` pyramid_redis_sessions``のようなサードパーティパッケージは、より豊かなセッションサポートを提供します。または、独自のカスタムセッションエンジンを作成することもできます。 :doc: 組込みセッションサポート&lt;../ narr / sessions&gt;`を見てみましょう。私たちの ` __init __。py``ではまず最初に必要なセッションをインポートします:

1
2
from pyramid.config import Configurator
from pyramid.session import SignedCookieSessionFactory

警告

セッション文書でも指摘されているように、この実装例は、セキュリティの意味を持つ設定での使用を意図したものではありません。

&quot;factory &quot;を作り、:term: configurator`の `session_factory``引数に渡してください:

10
11
12
13
    config.add_route('home', '/')
    my_session_factory = SignedCookieSessionFactory('itsaseekreet')
    config.set_session_factory(my_session_factory)
    config.scan()

Pyramidの:term: request`オブジェクトには、 views.py``のビューコードで使用できる `session``属性が追加されました:

 7
 8
 9
10
11
12
13
14
def my_view(request):
    log.debug('Some Message')
    session = request.session
    if 'counter' in session:
        session['counter'] += 1
    else:
        session['counter'] = 0
    return {'project': 'hello_world'}

セッションのカウンタインクリメントを表示するには、Jinja2テンプレート `` templates / mytemplate.jinja2``を更新する必要があります:

4
5
6
7
8
<div class="content">
  <h1><span class="font-semi-bold">Pyramid</span> <span class="smaller">Starter project</span></h1>
  <p class="lead">Welcome to <span class="font-normal">hello_world</span>, a&nbsp;Pyramid application generated&nbsp;by<br><span class="font-normal">Cookiecutter</span>.</p>
  <p>Counter: {{ request.session.counter }}</p>
</div>

参考

参照::ref: クイックチュートリアルセッション<qtut_sessions> `、:ref: sessions_chapter`、:ref: flash_messages、:ref:` session_module`、:term: `pyramid_redis_sessions`です。

データベース

Webアプリケーションとは、データを意味します。データとはデータベースを意味します。頻繁にSQLデータベース。 SQLデータベースは、しばしば&quot;ORM &quot;(オブジェクト・リレーショナル・マッパー)を意味します。Pythonでは、ORMは通常、メガ・クオリティの* SQLAlchemy *をもたらします。

PyramidとSQLAlchemyは素晴らしい友達です。その友情には調理師がいる!

$ cd ~
$ env/bin/cookiecutter gh:Pylons/pyramid-cookiecutter-alchemy --checkout 1.9-branch

最初の項目の入力を求められたら、returnキーを押してデフォルトの `` yes``を受け入れます。

You've cloned ~/.cookiecutters/pyramid-cookiecutter-alchemy before.
Is it okay to delete and re-clone it? [yes]: yes
project_name [Pyramid Scaffold]: sqla_demo
repo_name [sqla_demo]: sqla_demo

その後、以下のコマンドを実行します。

# Change directory into your newly created project.
$ cd sqla_demo
# Create a new virtual environment...
$ python3 -m venv env
# ...where we upgrade packaging tools...
$ env/bin/pip install --upgrade pip setuptools
# ...and into which we install our project and its testing requirements.
$ env/bin/pip install -e ".[testing]"
# Reset our environment variable for a new virtual environment.
$ export VENV=~/sqla_demo/env

すべての依存関係がインストールされたSQLAlchemyアプリケーションのサンプルが用意されました。サンプルプロジェクトは、テーブルを使用してSQLiteデータベースを初期化するためのコンソールスクリプトを提供します。それを実行してから、アプリケーションを起動してみましょう:

$ $VENV/bin/initialize_sqla_demo_db development.ini
$ $VENV/bin/pserve development.ini

ORMは、データベース構造のプログラミング言語へのマッピングを容易にします。 SQLAlchemyはこのマッピングに&quot;models &quot;を使用します。 cookiecutterはサンプルモデルを生成しました:

11
12
13
14
15
class MyModel(Base):
    __tablename__ = 'models'
    id = Column(Integer, primary_key=True)
    name = Column(Text)
    value = Column(Integer)

Web要求とシステムの残りの間のロジックを仲介するビューコードは、SQLAlchemyのおかげでデータに簡単にアクセスできます。

13
        one = query.filter(MyModel.name == 'one').first()

参考

参照::ref: クイックチュートリアルデータベース<qtut_databases> `、 SQLAlchemy <http://www.sqlalchemy.org/> _、:ref: making_a_console_script`、:ref: bfg_sql_wiki_tutorial、および:ref:` pyramid_tmによるアプリケーショントランザクション<tm:overview> `

フォーム

開発者はWebフォームに関する多くの意見を持っているため、Python用の多くのフォームライブラリがあります。 Pyramidはフォームライブラリを直接バンドルしませんが、* Deform はフォームによく使われる選択肢で、関連する Colander *スキーマシステムです。

たとえば、wikiページを編集するフォームが必要な場合を考えてみましょう。フォームには2つのフィールドが必要です.1つは必須タイトル、もう1つは本文のリッチテキストエディタです。 Deformでは、これをColanderスキーマとして表現できます。

class WikiPage(colander.MappingSchema):
    title = colander.SchemaNode(colander.String())
    body = colander.SchemaNode(
        colander.String(),
        widget=deform.widget.RichTextWidget()
    )

これで、既存のページのフォームデータを使用して、フォームのHTMLをレンダリングできます。

form = self.wiki_form.render()

フォームの提出、検証、および保存を処理したいと思います。

# Get the form data that was posted
controls = self.request.POST.items()
try:
    # Validate and either raise a validation error
    # or return deserialized data from widgets
    appstruct = wiki_form.validate(controls)
except deform.ValidationFailure as e:
    # Bail out and render form with errors
    return dict(title=title, page=page, form=e.render())

# Change the content and redirect to the view
page['title'] = appstruct['title']
page['body'] = appstruct['body']

DeformとColanderは、フォーム、ウィジェット、スキーマ、および検証に非常に柔軟な組み合わせを提供します。最近のバージョンのDeformには、:ref: `小売モード<deform:retail>カスタムフォームでDeform機能を利用するためのものです。

Deformは、Twitterブートストラップの魅力的なCSSと、より強力な選択、チェックボックス、日付と時刻のウィジェットを使用しています。

参考

参照::ref: クイックチュートリアルフォーム<qtut_forms> `、:ref:`変形<deform:overview> `、および:ref: Colander <colander:overview> `

結論

この*クイックツアー*については少し詳しく説明しました。 Pyramidの概念の長いリストを紹介しましたが、その多くはPyramidの開発者ドキュメントに詳しく説明されています。