5:向层次结构添加资源

每种类型有多个视图,允许在资源树的任何位置添加内容。

背景

我们现在有多种类型的东西,但是每个资源类型只有一个视图。我们需要能够向容器添加内容,然后查看和编辑资源。

We will use the previously mentioned concept of named views. A name is a part of the URL that appears after the resource identifier. 例如:

@view_config(context=Folder, name='add_document')

…表示此URL::

http://localhost:6543/some_folder/add_document

…将匹配正在配置的视图。就好像您有一个面向对象的Web,它对由URL表示的资源进行操作。

目标

  • 允许在资源树中添加和编辑内容。

  • 创建一个发布数据的简单表单。

  • 创建获取发布数据、创建资源并重定向到新添加的资源的视图。

  • 按类型创建命名视图。

步骤

  1. 我们将使用前面的步骤作为起点:

    $ cd ..; cp -r typeviews addcontent; cd addcontent
    $ $VENV/bin/python setup.py develop
    
  2. 我们的观点 addcontent/tutorial/views.py 需要特定类型的注册:

     1from random import randint
     2
     3from pyramid.httpexceptions import HTTPFound
     4from pyramid.location import lineage
     5from pyramid.view import view_config
     6
     7from .resources import (
     8    Root,
     9    Folder,
    10    Document
    11    )
    12
    13
    14class TutorialViews(object):
    15    def __init__(self, context, request):
    16        self.context = context
    17        self.request = request
    18        self.parents = reversed(list(lineage(context)))
    19
    20    @view_config(renderer='templates/root.jinja2',
    21                 context=Root)
    22    def root(self):
    23        page_title = 'Quick Tutorial: Root'
    24        return dict(page_title=page_title)
    25
    26    @view_config(renderer='templates/folder.jinja2',
    27                 context=Folder)
    28    def folder(self):
    29        page_title = 'Quick Tutorial: Folder'
    30        return dict(page_title=page_title)
    31
    32    @view_config(name='add_folder', context=Folder)
    33    def add_folder(self):
    34        # Make a new Folder
    35        title = self.request.POST['folder_title']
    36        name = str(randint(0, 999999))
    37        new_folder = Folder(name, self.context, title)
    38        self.context[name] = new_folder
    39
    40        # Redirect to the new folder
    41        url = self.request.resource_url(new_folder)
    42        return HTTPFound(location=url)
    43
    44    @view_config(name='add_document', context=Folder)
    45    def add_document(self):
    46        # Make a new Document
    47        title = self.request.POST['document_title']
    48        name = str(randint(0, 999999))
    49        new_document = Document(name, self.context, title)
    50        self.context[name] = new_document
    51
    52        # Redirect to the new document
    53        url = self.request.resource_url(new_document)
    54        return HTTPFound(location=url)
    55
    56    @view_config(renderer='templates/document.jinja2',
    57                 context=Document)
    58    def document(self):
    59        page_title = 'Quick Tutorial: Document'
    60        return dict(page_title=page_title)
    
  3. 在中生成可重用的代码段 addcontent/tutorial/templates/addform.jinja2 添加内容:

     1<p>
     2    <form class="form-inline"
     3          action="{{ request.resource_url(context, 'add_folder') }}"
     4          method="POST">
     5        <div class="form-group">
     6            <input class="form-control" name="folder_title"
     7                   placeholder="New folder title..."/>
     8        </div>
     9        <input type="submit" class="btn" value="Add Folder"/>
    10    </form>
    11</p>
    12<p>
    13    <form class="form-inline"
    14          action="{{ request.resource_url(context, 'add_document') }}"
    15          method="POST">
    16        <div class="form-group">
    17            <input class="form-control" name="document_title"
    18                   placeholder="New document title..."/>
    19        </div>
    20        <input type="submit" class="btn" value="Add Document"/>
    21    </form>
    22</p>
    
  4. 将此代码段添加到 addcontent/tutorial/templates/root.jinja2

     1{% extends "templates/layout.jinja2" %}
     2{% block content %}
     3
     4    <h2>{{ context.title }}</h2>
     5    <p>The root might have some other text.</p>
     6    {% include "templates/contents.jinja2" %}
     7
     8    {% include "templates/addform.jinja2" %}
     9
    10{% endblock content %}
    
  5. 表格需要在 addcontent/tutorial/templates/folder.jinja2

    1{% extends "templates/layout.jinja2" %}
    2{% block content %}
    3
    4    <h2>{{ context.title }}</h2>
    5    {% include "templates/contents.jinja2" %}
    6
    7    {% include "templates/addform.jinja2" %}
    8
    9{% endblock content %}
    
  6. $ $VENV/bin/nosetests 应报告正在运行4个测试。

  7. 运行 Pyramid 应用程序时使用:

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

分析

现在我们的观点代表一个更丰富的系统,其中可以处理表单数据来修改树中的内容。我们通过将命名视图附加到资源类型,使它们成为面向对象操作的自然系统来实现这一点。

To mimic uniqueness, we randomly choose a satisfactorily large number. 为了真正的唯一性,我们还需要检查该数字是否已经存在于资源树的同一级别。

We'll start to address a couple of issues brought up in the Extra Credit below in the next step of this tutorial, 6:在ZODB中存储资源 .

Extra Credit

  1. 如果添加文件夹和文档,然后重新启动应用程序,会发生什么情况?

  2. 如果删除伪随机伪唯一命名约定并用固定值替换它,会发生什么情况?