summaryrefslogtreecommitdiff
path: root/docs/narr/models.rst
diff options
context:
space:
mode:
authorChris McDonough <chrism@plope.com>2010-12-18 02:27:14 -0500
committerChris McDonough <chrism@plope.com>2010-12-18 02:27:14 -0500
commitfb6a5ce52a275f7798e82a34b5907ea118cbd2ff (patch)
tree29e80d0eb681676d1e0eb2707ca764dbf5491864 /docs/narr/models.rst
parentbf89764a7e3ccab6133c9ad43b8d9af4f5c4083b (diff)
downloadpyramid-fb6a5ce52a275f7798e82a34b5907ea118cbd2ff.tar.gz
pyramid-fb6a5ce52a275f7798e82a34b5907ea118cbd2ff.tar.bz2
pyramid-fb6a5ce52a275f7798e82a34b5907ea118cbd2ff.zip
model -> resource; resource -> asset
Diffstat (limited to 'docs/narr/models.rst')
-rw-r--r--docs/narr/models.rst331
1 files changed, 0 insertions, 331 deletions
diff --git a/docs/narr/models.rst b/docs/narr/models.rst
deleted file mode 100644
index 91828287f..000000000
--- a/docs/narr/models.rst
+++ /dev/null
@@ -1,331 +0,0 @@
-Models
-======
-
-A :term:`model` class is typically a simple Python class defined in a module.
-References to these classes and instances of such classes are omnipresent in
-:app:`Pyramid` when :term:`traversal` is used to build an application:
-
-- Model instances make up the object graph that :app:`Pyramid`
- will walk over when :term:`traversal` is used.
-
-- The ``context`` and ``containment`` arguments to
- :meth:`pyramid.config.Configurator.add_view` often
- reference a model class.
-
-- A :term:`root factory` returns a model instance.
-
-- A model instance is exposed to :term:`view` code as the :term:`context` of
- a view.
-
-In many :term:`traversal` based applications (particularly ones that use
-Zope-like patterns), model objects often store data and offer methods related
-to mutating that data.
-
-.. note::
-
- A terminology overlap confuses people who write applications that
- always use ORM packages such as SQLAlchemy, which has a very
- different notion of the definition of a "model". When using the API
- of common ORM packages, its conception of "model" is almost
- certainly not the same conception of "model" used by
- :app:`Pyramid`. In particular, it can be unnatural to think of
- :app:`Pyramid` model objects as "models" if you develop your
- application using :term:`traversal` and a relational database. When
- you develop such applications, the object graph *might* be composed
- completely of "model" objects (as defined by the ORM) but it also
- might not be. The things that :app:`Pyramid` refers to as
- "models" in such an application may instead just be stand-ins that
- perform a query and generate some wrapper *for* an ORM "model" or
- set of ORM models. This naming overlap is slightly unfortunate.
- However, many :app:`Pyramid` applications (especially ones which
- use :term:`ZODB`) do indeed traverse a graph full of literal model
- nodes. Each node in the graph is a separate persistent object that
- is stored within a database. This was the use case considered when
- coming up with the "model" terminology. However, if we had it to do
- all over again, we'd probably call these objects something
- different to avoid confusion.
-
-.. index::
- single: model constructor
-
-Defining a Model Constructor
-----------------------------
-
-An example of a model constructor, ``BlogEntry`` is presented below.
-It is implemented as a class which, when instantiated, becomes a model
-instance.
-
-.. code-block:: python
- :linenos:
-
- import datetime
-
- class BlogEntry(object):
- def __init__(self, title, body, author):
- self.title = title
- self.body = body
- self.author = author
- self.created = datetime.datetime.now()
-
-A model constructor may be essentially any Python object which is
-callable, and which returns a model instance. In the above example,
-the ``BlogEntry`` class can be called, returning a model instance.
-
-.. index::
- single: model interfaces
-
-.. _models_which_implement_interfaces:
-
-Model Instances Which Implement Interfaces
-------------------------------------------
-
-Model instances can optionally be made to implement an
-:term:`interface`. An interface is used to tag a model object with a
-"type" that can later be referred to within :term:`view
-configuration`.
-
-Specifying an interface instead of a class as the ``context`` or
-``containment`` arguments within :term:`view configuration` statements
-effectively makes it possible to use a single view callable for more
-than one class of object. If your application is simple enough that
-you see no reason to want to do this, you can skip reading this
-section of the chapter.
-
-For example, here's some code which describes a blog entry which also
-declares that the blog entry implements an :term:`interface`.
-
-.. code-block:: python
- :linenos:
-
- import datetime
- from zope.interface import implements
- from zope.interface import Interface
-
- class IBlogEntry(Interface):
- pass
-
- class BlogEntry(object):
- implements(IBlogEntry)
- def __init__(self, title, body, author):
- self.title = title
- self.body = body
- self.author = author
- self.created = datetime.datetime.now()
-
-This model consists of two things: the class which defines the model
-constructor (above as the class ``BlogEntry``), and an
-:term:`interface` attached to the class (via an ``implements``
-statement at class scope using the ``IBlogEntry`` interface as its
-sole argument).
-
-The interface object used must be an instance of a class that inherits
-from :class:`zope.interface.Interface`.
-
-A model class may *implement* zero or more interfaces. You specify
-that a model implements an interface by using the
-:func:`zope.interface.implements` function at class scope. The above
-``BlogEntry`` model implements the ``IBlogEntry`` interface.
-
-You can also specify that a *particular* model instance provides an
-interface, as opposed to its class as above, which implies that all
-instances do. To do so, use the :func:`zope.interface.directlyProvides`
-function:
-
-.. code-block:: python
- :linenos:
-
- from zope.interface import directlyProvides
- from zope.interface import Interface
-
- class IBlogEntry(Interface):
- pass
-
- class BlogEntry(object):
- def __init__(self, title, body, author):
- self.title = title
- self.body = body
- self.author = author
- self.created = datetime.datetime.now()
-
- entry = BlogEntry('title', 'body', 'author')
- directlyProvides(entry, IBlogEntry)
-
-:func:`zope.interface.directlyProvides` will replace any existing
-interface that was previously provided by an instance. If a model
-object already has instance-level interface declarations that you
-don't want to replace, use the :func:`zope.interface.alsoProvides`
-function:
-
-.. code-block:: python
- :linenos:
-
- from zope.interface import alsoProvides
- from zope.interface import directlyProvides
- from zope.interface import Interface
-
- class IBlogEntry1(Interface):
- pass
-
- class IBlogEntry2(Interface):
- pass
-
- class BlogEntry(object):
- def __init__(self, title, body, author):
- self.title = title
- self.body = body
- self.author = author
- self.created = datetime.datetime.now()
-
- entry = BlogEntry('title', 'body', 'author')
- directlyProvides(entry, IBlogEntry1)
- alsoProvides(entry, IBlogEntry2)
-
-:func:`zope.interface.alsoProvides` will augment the set of interfaces
-directly provided by an instance instead of overwriting them like
-:func:`zope.interface.directlyProvides` does.
-
-For more information about how model interfaces can be used by view
-configuration, see :ref:`using_model_interfaces`.
-
-.. index::
- single: model graph
- single: traversal graph
- single: object graph
- single: container nodes
- single: leaf nodes
-
-Defining a Graph of Model Instances for Traversal
--------------------------------------------------
-
-When :term:`traversal` is used (as opposed to a purely :term:`url
-dispatch` based application), :app:`Pyramid` expects to be able to
-traverse a graph composed of model instances. Traversal begins at a
-root model instance, and descends into the graph recursively via each
-found model's ``__getitem__`` method. :app:`Pyramid` imposes the
-following policy on model instance nodes in the graph:
-
-- Container nodes (i.e., nodes which contain other nodes) must supply
- a ``__getitem__`` method which is willing to resolve a unicode name
- to a subobject. If a subobject by that name does not exist in the
- container, ``__getitem__`` must raise a :exc:`KeyError`. If a
- subobject by that name *does* exist, the container should return the
- subobject (another model instance).
-
-- Leaf nodes, which do not contain other nodes, must not
- implement a ``__getitem__``, or if they do, their ``__getitem__``
- method must raise a :exc:`KeyError`.
-
-See :ref:`traversal_chapter` for more information about how traversal
-works against model instances.
-
-.. index::
- pair: location-aware; model
-
-.. _location_aware:
-
-Location-Aware Model Instances
-------------------------------
-
-Applications which use :term:`traversal` to locate the :term:`context`
-of a view must ensure that the model instances that make up the model
-graph are "location aware".
-
-In order for :app:`Pyramid` location, security, URL-generation, and
-traversal functions (i.e., functions in :ref:`location_module`,
-:ref:`traversal_module`, :ref:`url_module` and some in
-:ref:`security_module` ) to work properly against the model instances in
-an object graph, all nodes in the graph must be :term:`location` -aware.
-This means they must have two attributes: ``__parent__`` and
-``__name__``.
-
-The ``__parent__`` attribute should be a reference to the node's
-parent model instance in the graph. The ``__name__`` attribute should
-be the name that a node's parent refers to the node via
-``__getitem__``.
-
-The ``__parent__`` of the root object should be ``None`` and its
-``__name__`` should be the empty string. For instance:
-
-.. code-block:: python
- :linenos:
-
- class MyRootObject(object):
- __name__ = ''
- __parent__ = None
-
-A node returned from the root item's ``__getitem__`` method should have
-a ``__parent__`` attribute that is a reference to the root object, and
-its ``__name__`` attribute should match the name by which it is
-reachable via the root object's ``__getitem__``. A container under the
-root should have a ``__getitem__`` that returns objects with a
-``__parent__`` attribute that points at the container, and these
-subobjects should have a ``__name__`` attribute that matches the name by
-which they are retrieved from the container via ``__getitem__``.
-This pattern continues recursively down the graph.
-
-The ``__parent__`` attributes of each node form a linked list
-that points "upward" toward the root. This is analogous to the
-`..` entry in filesystem directories. If you follow the ``__parent__``
-values from any node in the traversal graph, you will eventually
-come to the root node, just like if you keep executing the
-``cd ..`` filesystem command, eventually you will reach the
-filesystem root directory.
-
-.. warning:: If your root model object has a ``__name__`` argument
- that is not ``None`` or the empty string, URLs returned by the
- :func:`pyramid.url.model_url` function and paths generated by
- the :func:`pyramid.traversal.model_path` and
- :func:`pyramid.traversal.model_path_tuple` APIs will be
- generated improperly. The value of ``__name__`` will be prepended
- to every path and URL generated (as opposed to a single leading
- slash or empty tuple element).
-
-.. sidebar:: Using :mod:`pyramid_traversalwrapper`
-
- If you'd rather not manage the ``__name__`` and ``__parent__``
- attributes of your models "by hand", an add-on package named
- :mod:`pyramid_traversalwrapper` can help.
-
- In order to use this helper feature, you must first install the
- :mod:`pyramid_traversalwrapper` package (available via PyPI), then register
- its ``ModelGraphTraverser`` as the traversal policy, rather than the
- default :app:`Pyramid` traverser. The package contains instructions for
- doing so.
-
- Once :app:`Pyramid` is configured with this feature, you will no
- longer need to manage the ``__parent__`` and ``__name__`` attributes
- on graph objects "by hand". Instead, as necessary, during traversal
- :app:`Pyramid` will wrap each object (even the root object) in a
- ``LocationProxy`` which will dynamically assign a ``__name__`` and a
- ``__parent__`` to the traversed object (based on the last traversed
- object and the name supplied to ``__getitem__``). The root object
- will have a ``__name__`` attribute of ``None`` and a ``__parent__``
- attribute of ``None``.
-
-.. index::
- single: model API functions
- single: url generation (traversal)
-
-:app:`Pyramid` API Functions That Act Against Models
--------------------------------------------------------
-
-A model instance is used as the :term:`context` provided to a view. See
-:ref:`traversal_chapter` and :ref:`urldispatch_chapter` for more information
-about how a model instance becomes the context.
-
-The APIs provided by :ref:`traversal_module` are used against model
-instances. These functions can be used to find the "path" of a model,
-the root model in an object graph, or generate a URL to a model.
-
-The APIs provided by :ref:`location_module` are used against model
-instances. These can be used to walk down an object graph, or
-conveniently locate one object "inside" another.
-
-Some APIs in :ref:`security_module` accept a model object as a
-parameter. For example, the
-:func:`pyramid.security.has_permission` API accepts a "context" (a
-model object) as one of its arguments; the ACL is obtained from this
-model or one of its ancestors. Other APIs in the
-:mod:`pyramid.security` module also accept :term:`context` as an
-argument, and a context is always a model.
-