ВУЗ: Не указан

Категория: Не указан

Дисциплина: Не указана

Добавлен: 02.01.2026

Просмотров: 2752

Скачиваний: 0

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.

36. ZODB + TRAVERSAL WIKI TUTORIAL

this view will use the templates/edit.pt template file as a renderer. We share the same template between add and edit views, thus edit.pt instead of add.pt.

The add_page function will be invoked when a user clicks on a WikiWord which isn’t yet represented as a page in the system. The check function within the view_page view generates URLs to this view. It also acts as a handler for the form that is generated when we want to add a page resource. The context of the add_page view is always a Wiki resource (not a Page resource).

The request subpath in Pyramid is the sequence of names that are found after the view name in the URL segments given in the PATH_INFO of the WSGI request as the result of traversal. If our add view is invoked via, e.g. http://localhost:6543/add_page/SomeName, the subpath will be a tuple: (’SomeName’,).

The add view takes the zeroth element of the subpath (the wiki page name), and aliases it to the name attribute in order to know the name of the page we’re trying to add.

If the view rendering is not a result of a form submission (if the expression ’form.submitted’ in request.params is False), the view renders a template. To do so, it generates a “save url” which the template use as the form post URL during rendering. We’re lazy here, so we’re trying to use the same template (templates/edit.pt) for the add view as well as the page edit view. To do so, we create a dummy Page resource object in order to satisfy the edit form’s desire to have some page object exposed as page, and we’ll render the template to a response.

If the view rendering is a result of a form submission (if the expression ’form.submitted’ in request.params is True), we scrape the page body from the form data, create a Page object using the name in the subpath and the page body, and save it into “our context” (the Wiki) using the __setitem__ method of the context. We then redirect back to the view_page view (the default view for a page) for the newly created page.

The edit_page view function

The edit_page function will be configured to respond when the context is a Page resource and the view name is edit_page. We’ll provide it with a @view_config decorator which names the string edit_page as its view name (via name=), the class tutorial.models.Page as its context, and the renderer named templates/edit.pt. This means that when a Page resource is the context, and a view name exists as the result of traversal named edit_page, this view will be used. We inform Pyramid this view will use the templates/edit.pt template file as a renderer.

The edit_page function will be invoked when a user clicks the “Edit this Page” button on the view form. It renders an edit form but it also acts as the form post view callable for the form it renders. The context of the edit_page view will always be a Page resource (never a Wiki resource).

410


36.6. DEFINING VIEWS

If the view execution is not a result of a form submission (if the expression ’form.submitted’ in request.params is False), the view simply renders the edit form, passing the page resource, and a save_url which will be used as the action of the generated form.

If the view execution is a result of a form submission (if the expression ’form.submitted’ in request.params is True), the view grabs the body element of the request parameter and sets it as the data attribute of the page context. It then redirects to the default view of the context (the page), which will always be the view_page view.

36.6.3 Viewing the Result of all Our Edits to views.py

The result of all of our edits to views.py will leave it looking like this:

1

from docutils.core import publish_parts

2

import re

3

 

4

from pyramid.httpexceptions import HTTPFound

5

from pyramid.view import view_config

6

 

7

from .models import Page

8

 

9

# regular expression used to find WikiWords

10

wikiwords = re.compile(r"\b([A-Z]\w+[A-Z]+\w+)")

11

12@view_config(context=’.models.Wiki’)

13def view_wiki(context, request):

14return HTTPFound(location=request.resource_url(context, ’FrontPage’))

15

16@view_config(context=’.models.Page’, renderer=’templates/view.pt’)

17def view_page(context, request):

18wiki = context.__parent__

19

20def check(match):

21word = match.group(1)

22if word in wiki:

23

page = wiki[word]

24

view_url = request.resource_url(page)

25return ’<a href="%s">%s</a>’ % (view_url, word)

26else:

27

add_url = request.application_url + ’/add_page/’ + word

28

return ’<a href="%s">%s</a>’ % (add_url, word)

29

30content = publish_parts(context.data, writer_name=’html’)[’html_body’]

31content = wikiwords.sub(check, content)

411


36. ZODB + TRAVERSAL WIKI TUTORIAL

32edit_url = request.resource_url(context, ’edit_page’)

33return dict(page = context, content = content, edit_url = edit_url)

34

35 @view_config(name=’add_page’, context=’.models.Wiki’,

36

renderer=’templates/edit.pt’)

37def add_page(context, request):

38name = request.subpath[0]

39if ’form.submitted’ in request.params:

40body = request.params[’body’]

41page = Page(body)

42page.__name__ = name

43page.__parent__ = context

44context[name] = page

45return HTTPFound(location = request.resource_url(page))

46save_url = request.resource_url(context, ’add_page’, name)

47page = Page(’’)

48page.__name__ = name

49page.__parent__ = context

50return dict(page = page, save_url = save_url)

51

52 @view_config(name=’edit_page’, context=’.models.Page’,

53

renderer=’templates/edit.pt’)

54def edit_page(context, request):

55if ’form.submitted’ in request.params:

56context.data = request.params[’body’]

57return HTTPFound(location = request.resource_url(context))

58

 

59

return dict(page = context,

60

save_url = request.resource_url(context, ’edit_page’))

36.6.4 Adding Templates

Most view callables we’ve added expected to be rendered via a template. The default templating systems in Pyramid are Chameleon and Mako. Chameleon is a variant of ZPT, which is an XML-based templating language. Mako is a non-XML-based templating language. Because we had to pick one, we chose Chameleon for this tutorial.

The templates we create will live in the templates directory of our tutorial package. Chameleon templates must have a .pt extension to be recognized as such.

412


36.6. DEFINING VIEWS

The view.pt Template

The view.pt template is used for viewing a single Page. It is used by the view_page view function. It should have a div that is “structure replaced” with the content value provided by the view. It should also have a link on the rendered page that points at the “edit” URL (the URL which invokes the edit_page view for the page being viewed).

Once we’re done with the view.pt template, it will look a lot like the below:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" xmlns:tal="http://xml.zope.org/namespaces/tal">

<head>

<title>${page.__name__} - Pyramid tutorial wiki (based on TurboGears 20-Minute Wiki)</title>

<meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/> <meta name="keywords" content="python web application" />

<meta name="description" content="pyramid web application" /> <link rel="shortcut icon"

href="/static/favicon.ico" /> <link rel="stylesheet"

href="/static/pylons.css"

type="text/css" media="screen" charset="utf-8" />

<!--[if lte IE 6]> <link rel="stylesheet"

href="/static/ie6.css"

type="text/css" media="screen" charset="utf-8" /> <![endif]-->

</head>

<body>

<div id="wrap">

<div id="top-small">

<div class="top-small align-center">

<div>

<img width="220" height="50" alt="pyramid" src="/static/pyramid-small.png" />

</div>

</div>

</div>

<div id="middle">

<div class="middle align-right">

<div id="left" class="app-welcome align-left">

Viewing <b><span tal:replace="page.__name__">Page Name Goes Here</span></b><br/>

You can return to the

413


36. ZODB + TRAVERSAL WIKI TUTORIAL

<a href="${request.application_url}">FrontPage</a>.<br/>

</div>

<div id="right" class="app-welcome align-right"></div>

</div>

</div>

<div id="bottom">

<div class="bottom">

<div tal:replace="structure content"> Page text goes here.

</div>

<p>

<a tal:attributes="href edit_url" href=""> Edit this page

</a>

</p>

</div>

</div>

</div>

<div id="footer"> <div class="footer"

>© Copyright 2008-2011, Agendaless Consulting.</div>

</div>

</body>

</html>

latex-note.png

The names available for our use in a template are always those that are present in the dictionary returned by the view callable. But our templates make use of a request object that none of our tutorial views return in their dictionary. This value appears as if “by magic”. However, request is one of several names that are available “by default” in a template when a template renderer is used. See *.pt or *.txt: Chameleon Template Renderers for more information about other names that are available by default in a template when a template is used as a renderer.

The edit.pt Template

The edit.pt template is used for adding and editing a Page. It is used by the add_page and edit_page view functions. It should display a page containing a form that POSTs back to the

414

36.6. DEFINING VIEWS

“save_url” argument supplied by the view. The form should have a “body” textarea field (the page data), and a submit button that has the name “form.submitted”. The textarea in the form should be filled with any existing page data when it is rendered.

Once we’re done with the edit.pt template, it will look a lot like the below:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" xmlns:tal="http://xml.zope.org/namespaces/tal">

<head>

<title>${page.__name__} - Pyramid tutorial wiki (based on TurboGears 20-Minute Wiki)</title>

<meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/> <meta name="keywords" content="python web application" />

<meta name="description" content="pyramid web application" /> <link rel="shortcut icon"

href="/static/favicon.ico" /> <link rel="stylesheet"

href="/static/pylons.css"

type="text/css" media="screen" charset="utf-8" />

<!--[if lte IE 6]> <link rel="stylesheet"

href="/static/ie6.css"

type="text/css" media="screen" charset="utf-8" /> <![endif]-->

</head>

<body>

<div id="wrap">

<div id="top-small">

<div class="top-small align-center">

<div>

<img width="220" height="50" alt="pyramid" src="/static/pyramid-small.png" />

</div>

</div>

</div>

<div id="middle">

<div class="middle align-right">

<div id="left" class="app-welcome align-left">

Editing <b><span tal:replace="page.__name__">Page Name Goes Here</span></b><br/>

You can return to the

<a href="${request.application_url}">FrontPage</a>.<br/>

</div>

<div id="right" class="app-welcome align-right"></div>

</div>

415