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 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043
|
.. _view_config_chapter:
.. _view_configuration:
.. _view_lookup:
View Configuration
==================
.. index::
single: view lookup
:term:`View lookup` is the :app:`Pyramid` subsystem responsible for finding and
invoking a :term:`view callable`. :term:`View configuration` controls how
:term:`view lookup` operates in your application. During any given request,
view configuration information is compared against request data by the view
lookup subsystem in order to find the "best" view callable for that request.
In earlier chapters, you have been exposed to a few simple view configuration
declarations without much explanation. In this chapter we will explore the
subject in detail.
.. index::
pair: resource; mapping to view callable
pair: URL pattern; mapping to view callable
Mapping a Resource or URL Pattern to a View Callable
----------------------------------------------------
A developer makes a :term:`view callable` available for use within a
:app:`Pyramid` application via :term:`view configuration`. A view
configuration associates a view callable with a set of statements that
determine the set of circumstances which must be true for the view callable to
be invoked.
A view configuration statement is made about information present in the
:term:`context` resource and the :term:`request`.
View configuration is performed in one of two ways:
- By running a :term:`scan` against application source code which has a
:class:`pyramid.view.view_config` decorator attached to a Python object as
per :ref:`mapping_views_using_a_decorator_section`.
- By using the :meth:`pyramid.config.Configurator.add_view` method as per
:ref:`mapping_views_using_imperative_config_section`.
.. index::
single: view configuration parameters
.. _view_configuration_parameters:
View Configuration Parameters
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
All forms of view configuration accept the same general types of arguments.
Many arguments supplied during view configuration are :term:`view predicate`
arguments. View predicate arguments used during view configuration are used to
narrow the set of circumstances in which :term:`view lookup` will find a
particular view callable.
:term:`View predicate` attributes are an important part of view configuration
that enables the :term:`view lookup` subsystem to find and invoke the
appropriate view. The greater the number of predicate attributes possessed by
a view's configuration, the more specific the circumstances need to be before
the registered view callable will be invoked. The fewer the number of
predicates which are supplied to a particular view configuration, the more
likely it is that the associated view callable will be invoked. A view with
five predicates will always be found and evaluated before a view with two, for
example.
This does not mean however, that :app:`Pyramid` "stops looking" when it finds a
view registration with predicates that don't match. If one set of view
predicates does not match, the "next most specific" view (if any) is consulted
for predicates, and so on, until a view is found, or no view can be matched up
with the request. The first view with a set of predicates all of which match
the request environment will be invoked.
If no view can be found with predicates which allow it to be matched up with
the request, :app:`Pyramid` will return an error to the user's browser,
representing a "not found" (404) page. See :ref:`changing_the_notfound_view`
for more information about changing the default :term:`Not Found View`.
Other view configuration arguments are non-predicate arguments. These tend to
modify the response of the view callable or prevent the view callable from
being invoked due to an authorization policy. The presence of non-predicate
arguments in a view configuration does not narrow the circumstances in which
the view callable will be invoked.
.. _nonpredicate_view_args:
Non-Predicate Arguments
+++++++++++++++++++++++
``permission``
The name of a :term:`permission` that the user must possess in order to
invoke the :term:`view callable`. See :ref:`view_security_section` for more
information about view security and permissions.
If ``permission`` is not supplied, no permission is registered for this view
(it's accessible by any caller).
``attr``
The view machinery defaults to using the ``__call__`` method of the
:term:`view callable` (or the function itself, if the view callable is a
function) to obtain a response. The ``attr`` value allows you to vary the
method attribute used to obtain the response. For example, if your view was
a class, and the class has a method named ``index`` and you wanted to use
this method instead of the class's ``__call__`` method to return the
response, you'd say ``attr="index"`` in the view configuration for the view.
This is most useful when the view definition is a class.
If ``attr`` is not supplied, ``None`` is used (implying the function itself
if the view is a function, or the ``__call__`` callable attribute if the view
is a class).
``renderer``
Denotes the :term:`renderer` implementation which will be used to construct a
:term:`response` from the associated view callable's return value.
.. seealso:: See also :ref:`renderers_chapter`.
This is either a single string term (e.g., ``json``) or a string implying a
path or :term:`asset specification` (e.g., ``templates/views.pt``) naming a
:term:`renderer` implementation. If the ``renderer`` value does not contain
a dot (``.``), the specified string will be used to look up a renderer
implementation, and that renderer implementation will be used to construct a
response from the view return value. If the ``renderer`` value contains a
dot (``.``), the specified term will be treated as a path, and the filename
extension of the last element in the path will be used to look up the
renderer implementation, which will be passed the full path.
When the renderer is a path—although a path is usually just a simple relative
pathname (e.g., ``templates/foo.pt``, implying that a template named "foo.pt"
is in the "templates" directory relative to the directory of the current
:term:`package`)—the path can be absolute, starting with a slash on UNIX or a
drive letter prefix on Windows. The path can alternatively be a :term:`asset
specification` in the form ``some.dotted.package_name:relative/path``, making
it possible to address template assets which live in a separate package.
The ``renderer`` attribute is optional. If it is not defined, the "null"
renderer is assumed (no rendering is performed and the value is passed back
to the upstream :app:`Pyramid` machinery unchanged). Note that if the view
callable itself returns a :term:`response` (see :ref:`the_response`), the
specified renderer implementation is never called.
``http_cache``
When you supply an ``http_cache`` value to a view configuration, the
``Expires`` and ``Cache-Control`` headers of a response generated by the
associated view callable are modified. The value for ``http_cache`` may be
one of the following:
- A nonzero integer. If it's a nonzero integer, it's treated as a number of
seconds. This number of seconds will be used to compute the ``Expires``
header and the ``Cache-Control: max-age`` parameter of responses to
requests which call this view. For example: ``http_cache=3600`` instructs
the requesting browser to 'cache this response for an hour, please'.
- A ``datetime.timedelta`` instance. If it's a ``datetime.timedelta``
instance, it will be converted into a number of seconds, and that number of
seconds will be used to compute the ``Expires`` header and the
``Cache-Control: max-age`` parameter of responses to requests which call
this view. For example: ``http_cache=datetime.timedelta(days=1)``
instructs the requesting browser to 'cache this response for a day,
please'.
- Zero (``0``). If the value is zero, the ``Cache-Control`` and ``Expires``
headers present in all responses from this view will be composed such that
client browser cache (and any intermediate caches) are instructed to never
cache the response.
- A two-tuple. If it's a two-tuple (e.g., ``http_cache=(1,
{'public':True})``), the first value in the tuple may be a nonzero integer
or a ``datetime.timedelta`` instance. In either case this value will be
used as the number of seconds to cache the response. The second value in
the tuple must be a dictionary. The values present in the dictionary will
be used as input to the ``Cache-Control`` response header. For example:
``http_cache=(3600, {'public':True})`` means 'cache for an hour, and add
``public`` to the Cache-Control header of the response'. All keys and
values supported by the ``webob.cachecontrol.CacheControl`` interface may
be added to the dictionary. Supplying ``{'public':True}`` is equivalent to
calling ``response.cache_control.public = True``.
Providing a non-tuple value as ``http_cache`` is equivalent to calling
``response.cache_expires(value)`` within your view's body.
Providing a two-tuple value as ``http_cache`` is equivalent to calling
``response.cache_expires(value[0], **value[1])`` within your view's body.
If you wish to avoid influencing the ``Expires`` header, and instead wish to
only influence ``Cache-Control`` headers, pass a tuple as ``http_cache`` with
the first element of ``None``, i.e., ``(None, {'public':True})``.
``wrapper``
The :term:`view name` of a different :term:`view configuration` which will
receive the response body of this view as the ``request.wrapped_body``
attribute of its own :term:`request`, and the :term:`response` returned by
this view as the ``request.wrapped_response`` attribute of its own request.
Using a wrapper makes it possible to "chain" views together to form a
composite response. The response of the outermost wrapper view will be
returned to the user. The wrapper view will be found as any view is found.
See :ref:`view_lookup`. The "best" wrapper view will be found based on the
lookup ordering. "Under the hood" this wrapper view is looked up via
``pyramid.view.render_view_to_response(context, request,
'wrapper_viewname')``. The context and request of a wrapper view is the same
context and request of the inner view.
If ``wrapper`` is not supplied, no wrapper view is used.
``decorator``
A :term:`dotted Python name` to a function (or the function itself) which
will be used to decorate the registered :term:`view callable`. The decorator
function will be called with the view callable as a single argument. The
view callable it is passed will accept ``(context, request)``. The decorator
must return a replacement view callable which also accepts ``(context,
request)``. The ``decorator`` may also be an iterable of decorators, in which
case they will be applied one after the other to the view, in reverse order.
For example::
@view_config(..., decorator=(decorator2, decorator1))
def myview(request):
...
Is similar to doing::
@view_config(...)
@decorator2
@decorator1
def myview(request):
...
All view callables in the decorator chain must return a response object
implementing :class:`pyramid.interfaces.IResponse` or raise an exception:
.. code-block:: python
def log_timer(wrapped):
def wrapper(context, request):
start = time.time()
response = wrapped(context, request)
duration = time.time() - start
response.headers['X-View-Time'] = '%.3f' % (duration,)
log.info('view took %.3f seconds', duration)
return response
return wrapper
``mapper``
A Python object or :term:`dotted Python name` which refers to a :term:`view
mapper`, or ``None``. By default it is ``None``, which indicates that the
view should use the default view mapper. This plug-point is useful for
Pyramid extension developers, but it's not very useful for "civilians" who
are just developing stock Pyramid applications. Pay no attention to the man
behind the curtain.
Predicate Arguments
+++++++++++++++++++
These arguments modify view lookup behavior. In general the more predicate
arguments that are supplied, the more specific and narrower the usage of the
configured view.
``name``
The :term:`view name` required to match this view callable. A ``name``
argument is typically only used when your application uses :term:`traversal`.
Read :ref:`traversal_chapter` to understand the concept of a view name.
If ``name`` is not supplied, the empty string is used (implying the default
view).
``context``
An object representing a Python class of which the :term:`context` resource
must be an instance *or* the :term:`interface` that the :term:`context`
resource must provide in order for this view to be found and called. This
predicate is true when the :term:`context` resource is an instance of the
represented class or if the :term:`context` resource provides the represented
interface; it is otherwise false.
If ``context`` is not supplied, the value ``None``, which matches any
resource, is used.
``route_name``
If ``route_name`` is supplied, the view callable will be invoked only when
the named route has matched.
This value must match the ``name`` of a :term:`route configuration`
declaration (see :ref:`urldispatch_chapter`) that must match before this view
will be called. Note that the ``route`` configuration referred to by
``route_name`` will usually have a ``*traverse`` token in the value of its
``pattern``, representing a part of the path that will be used by
:term:`traversal` against the result of the route's :term:`root factory`.
If ``route_name`` is not supplied, the view callable will only have a chance
of being invoked if no other route was matched. This is when the
request/context pair found via :term:`resource location` does not indicate it
matched any configured route.
``request_type``
This value should be an :term:`interface` that the :term:`request` must
provide in order for this view to be found and called.
If ``request_type`` is not supplied, the value ``None`` is used, implying any
request type.
*This is an advanced feature, not often used by "civilians"*.
``request_method``
This value can be either a string (such as ``"GET"``, ``"POST"``,
``"PUT"``, ``"DELETE"``, ``"HEAD"``, or ``"OPTIONS"``) representing an HTTP
``REQUEST_METHOD`` or a tuple containing one or more of these strings. A
view declaration with this argument ensures that the view will only be called
when the ``method`` attribute of the request (i.e., the ``REQUEST_METHOD`` of
the WSGI environment) matches a supplied value.
.. versionchanged:: 1.4
The use of ``"GET"`` also implies that the view will respond to ``"HEAD"``.
If ``request_method`` is not supplied, the view will be invoked regardless of
the ``REQUEST_METHOD`` of the :term:`WSGI` environment.
``request_param``
This value can be any string or a sequence of strings. A view declaration
with this argument ensures that the view will only be called when the
:term:`request` has a key in the ``request.params`` dictionary (an HTTP
``GET`` or ``POST`` variable) that has a name which matches the supplied
value.
If any value supplied has an ``=`` sign in it, e.g.,
``request_param="foo=123"``, then the key (``foo``) must both exist in the
``request.params`` dictionary, *and* the value must match the right hand side
of the expression (``123``) for the view to "match" the current request.
If ``request_param`` is not supplied, the view will be invoked without
consideration of keys and values in the ``request.params`` dictionary.
``match_param``
This param may be either a single string of the format "key=value" or a tuple
containing one or more of these strings.
This argument ensures that the view will only be called when the
:term:`request` has key/value pairs in its :term:`matchdict` that equal those
supplied in the predicate. For example, ``match_param="action=edit"`` would
require the ``action`` parameter in the :term:`matchdict` match the right
hand side of the expression (``edit``) for the view to "match" the current
request.
If the ``match_param`` is a tuple, every key/value pair must match for the
predicate to pass.
If ``match_param`` is not supplied, the view will be invoked without
consideration of the keys and values in ``request.matchdict``.
.. versionadded:: 1.2
``containment``
This value should be a reference to a Python class or :term:`interface` that
a parent object in the context resource's :term:`lineage` must provide in
order for this view to be found and called. The resources in your resource
tree must be "location-aware" to use this feature.
If ``containment`` is not supplied, the interfaces and classes in the lineage
are not considered when deciding whether or not to invoke the view callable.
See :ref:`location_aware` for more information about location-awareness.
``xhr``
This value should be either ``True`` or ``False``. If this value is
specified and is ``True``, the :term:`WSGI` environment must possess an
``HTTP_X_REQUESTED_WITH`` header (i.e., ``X-Requested-With``) that has the
value ``XMLHttpRequest`` for the associated view callable to be found and
called. This is useful for detecting AJAX requests issued from jQuery,
Prototype, and other Javascript libraries.
If ``xhr`` is not specified, the ``HTTP_X_REQUESTED_WITH`` HTTP header is not
taken into consideration when deciding whether or not to invoke the
associated view callable.
``accept``
The value of this argument represents a match query for one or more mimetypes
in the ``Accept`` HTTP request header. If this value is specified, it must
be in one of the following forms: a mimetype match token in the form
``text/plain``, a wildcard mimetype match token in the form ``text/*``, or a
match-all wildcard mimetype match token in the form ``*/*``. If any of the
forms matches the ``Accept`` header of the request, this predicate will be
true.
If ``accept`` is not specified, the ``HTTP_ACCEPT`` HTTP header is not taken
into consideration when deciding whether or not to invoke the associated view
callable.
``header``
This value represents an HTTP header name or a header name/value pair.
If ``header`` is specified, it must be a header name or a
``headername:headervalue`` pair.
If ``header`` is specified without a value (a bare header name only, e.g.,
``If-Modified-Since``), the view will only be invoked if the HTTP header
exists with any value in the request.
If ``header`` is specified, and possesses a name/value pair (e.g.,
``User-Agent:Mozilla/.*``), the view will only be invoked if the HTTP header
exists *and* the HTTP header matches the value requested. When the
``headervalue`` contains a ``:`` (colon), it will be considered a name/value
pair (e.g., ``User-Agent:Mozilla/.*`` or ``Host:localhost``). The value
portion should be a regular expression.
Whether or not the value represents a header name or a header name/value
pair, the case of the header name is not significant.
If ``header`` is not specified, the composition, presence, or absence of HTTP
headers is not taken into consideration when deciding whether or not to
invoke the associated view callable.
``path_info``
This value represents a regular expression pattern that will be tested
against the ``PATH_INFO`` WSGI environment variable to decide whether or not
to call the associated view callable. If the regex matches, this predicate
will be ``True``.
If ``path_info`` is not specified, the WSGI ``PATH_INFO`` is not taken into
consideration when deciding whether or not to invoke the associated view
callable.
``check_csrf``
If specified, this value should be one of ``None``, ``True``, ``False``, or a
string representing the "check name". If the value is ``True`` or a string,
CSRF checking will be performed. If the value is ``False`` or ``None``, CSRF
checking will not be performed.
If the value provided is a string, that string will be used as the "check
name". If the value provided is ``True``, ``csrf_token`` will be used as the
check name.
If CSRF checking is performed, the checked value will be the value of
``request.params[check_name]``. This value will be compared against the
value of ``request.session.get_csrf_token()``, and the check will pass if
these two values are the same. If the check passes, the associated view will
be permitted to execute. If the check fails, the associated view will not be
permitted to execute.
Note that using this feature requires a :term:`session factory` to have been
configured.
.. versionadded:: 1.4a2
``physical_path``
If specified, this value should be a string or a tuple representing the
:term:`physical path` of the context found via traversal for this predicate
to match as true. For example, ``physical_path='/'``,
``physical_path='/a/b/c'``, or ``physical_path=('', 'a', 'b', 'c')``. This
is not a path prefix match or a regex, but a whole-path match. It's useful
when you want to always potentially show a view when some object is traversed
to, but you can't be sure about what kind of object it will be, so you can't
use the ``context`` predicate. The individual path elements between slash
characters or in tuple elements should be the Unicode representation of the
name of the resource and should not be encoded in any way.
.. versionadded:: 1.4a3
``effective_principals``
If specified, this value should be a :term:`principal` identifier or a
sequence of principal identifiers. If the
:meth:`pyramid.request.Request.effective_principals` method indicates that
every principal named in the argument list is present in the current request,
this predicate will return True; otherwise it will return False. For
example: ``effective_principals=pyramid.security.Authenticated`` or
``effective_principals=('fred', 'group:admins')``.
.. versionadded:: 1.4a4
``custom_predicates``
If ``custom_predicates`` is specified, it must be a sequence of references to
custom predicate callables. Use custom predicates when no set of predefined
predicates do what you need. Custom predicates can be combined with
predefined predicates as necessary. Each custom predicate callable should
accept two arguments, ``context`` and ``request``, and should return either
``True`` or ``False`` after doing arbitrary evaluation of the context
resource and/or the request. If all callables return ``True``, the
associated view callable will be considered viable for a given request.
If ``custom_predicates`` is not specified, no custom predicates are used.
``predicates``
Pass a key/value pair here to use a third-party predicate registered via
:meth:`pyramid.config.Configurator.add_view_predicate`. More than one
key/value pair can be used at the same time. See
:ref:`view_and_route_predicates` for more information about third-party
predicates.
.. versionadded:: 1.4a1
Inverting Predicate Values
++++++++++++++++++++++++++
You can invert the meaning of any predicate value by wrapping it in a call to
:class:`pyramid.config.not_`.
.. code-block:: python
:linenos:
from pyramid.config import not_
config.add_view(
'mypackage.views.my_view',
route_name='ok',
request_method=not_('POST')
)
The above example will ensure that the view is called if the request method is
*not* ``POST``, at least if no other view is more specific.
This technique of wrapping a predicate value in ``not_`` can be used anywhere
predicate values are accepted:
- :meth:`pyramid.config.Configurator.add_view`
- :meth:`pyramid.view.view_config`
.. versionadded:: 1.5
.. index::
single: view_config decorator
.. _mapping_views_using_a_decorator_section:
Adding View Configuration Using the ``@view_config`` Decorator
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. warning::
Using this feature tends to slow down application startup slightly, as more
work is performed at application startup to scan for view configuration
declarations. For maximum startup performance, use the view configuration
method described in :ref:`mapping_views_using_imperative_config_section`
instead.
The :class:`~pyramid.view.view_config` decorator can be used to associate
:term:`view configuration` information with a function, method, or class that
acts as a :app:`Pyramid` view callable.
Here's an example of the :class:`~pyramid.view.view_config` decorator that
lives within a :app:`Pyramid` application module ``views.py``:
.. code-block:: python
:linenos:
from resources import MyResource
from pyramid.view import view_config
from pyramid.response import Response
@view_config(route_name='ok', request_method='POST', permission='read')
def my_view(request):
return Response('OK')
Using this decorator as above replaces the need to add this imperative
configuration stanza:
.. code-block:: python
:linenos:
config.add_view('mypackage.views.my_view', route_name='ok',
request_method='POST', permission='read')
All arguments to ``view_config`` may be omitted. For example:
.. code-block:: python
:linenos:
from pyramid.response import Response
from pyramid.view import view_config
@view_config()
def my_view(request):
""" My view """
return Response()
Such a registration as the one directly above implies that the view name will
be ``my_view``, registered with a ``context`` argument that matches any
resource type, using no permission, registered against requests with any
request method, request type, request param, route name, or containment.
The mere existence of a ``@view_config`` decorator doesn't suffice to perform
view configuration. All that the decorator does is "annotate" the function
with your configuration declarations, it doesn't process them. To make
:app:`Pyramid` process your :class:`pyramid.view.view_config` declarations, you
*must* use the ``scan`` method of a :class:`pyramid.config.Configurator`:
.. code-block:: python
:linenos:
# config is assumed to be an instance of the
# pyramid.config.Configurator class
config.scan()
Please see :ref:`decorations_and_code_scanning` for detailed information about
what happens when code is scanned for configuration declarations resulting from
use of decorators like :class:`~pyramid.view.view_config`.
See :ref:`configuration_module` for additional API arguments to the
:meth:`~pyramid.config.Configurator.scan` method. For example, the method
allows you to supply a ``package`` argument to better control exactly *which*
code will be scanned.
All arguments to the :class:`~pyramid.view.view_config` decorator mean
precisely the same thing as they would if they were passed as arguments to the
:meth:`pyramid.config.Configurator.add_view` method save for the ``view``
argument. Usage of the :class:`~pyramid.view.view_config` decorator is a form
of :term:`declarative configuration`, while
:meth:`pyramid.config.Configurator.add_view` is a form of :term:`imperative
configuration`. However, they both do the same thing.
.. index::
single: view_config placement
.. _view_config_placement:
``@view_config`` Placement
++++++++++++++++++++++++++
A :class:`~pyramid.view.view_config` decorator can be placed in various points
in your application.
If your view callable is a function, it may be used as a function decorator:
.. code-block:: python
:linenos:
from pyramid.view import view_config
from pyramid.response import Response
@view_config(route_name='edit')
def edit(request):
return Response('edited!')
If your view callable is a class, the decorator can also be used as a class
decorator. All the arguments to the decorator are the same when applied against
a class as when they are applied against a function. For example:
.. code-block:: python
:linenos:
from pyramid.response import Response
from pyramid.view import view_config
@view_config(route_name='hello')
class MyView(object):
def __init__(self, request):
self.request = request
def __call__(self):
return Response('hello')
More than one :class:`~pyramid.view.view_config` decorator can be stacked on
top of any number of others. Each decorator creates a separate view
registration. For example:
.. code-block:: python
:linenos:
from pyramid.view import view_config
from pyramid.response import Response
@view_config(route_name='edit')
@view_config(route_name='change')
def edit(request):
return Response('edited!')
This registers the same view under two different names.
The decorator can also be used against a method of a class:
.. code-block:: python
:linenos:
from pyramid.response import Response
from pyramid.view import view_config
class MyView(object):
def __init__(self, request):
self.request = request
@view_config(route_name='hello')
def amethod(self):
return Response('hello')
When the decorator is used against a method of a class, a view is registered
for the *class*, so the class constructor must accept an argument list in one
of two forms: either a single argument, ``request``, or two arguments,
``context, request``.
The method which is decorated must return a :term:`response`.
Using the decorator against a particular method of a class is equivalent to
using the ``attr`` parameter in a decorator attached to the class itself. For
example, the above registration implied by the decorator being used against the
``amethod`` method could be written equivalently as follows:
.. code-block:: python
:linenos:
from pyramid.response import Response
from pyramid.view import view_config
@view_config(attr='amethod', route_name='hello')
class MyView(object):
def __init__(self, request):
self.request = request
def amethod(self):
return Response('hello')
.. index::
single: add_view
.. _mapping_views_using_imperative_config_section:
Adding View Configuration Using :meth:`~pyramid.config.Configurator.add_view`
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The :meth:`pyramid.config.Configurator.add_view` method within
:ref:`configuration_module` is used to configure a view "imperatively" (without
a :class:`~pyramid.view.view_config` decorator). The arguments to this method
are very similar to the arguments that you provide to the
:class:`~pyramid.view.view_config` decorator. For example:
.. code-block:: python
:linenos:
from pyramid.response import Response
def hello_world(request):
return Response('hello!')
# config is assumed to be an instance of the
# pyramid.config.Configurator class
config.add_view(hello_world, route_name='hello')
The first argument, a :term:`view callable`, is the only required argument. It
must either be a Python object which is the view itself or a :term:`dotted
Python name` to such an object. In the above example, the ``view callable`` is
the ``hello_world`` function.
When you use only :meth:`~pyramid.config.Configurator.add_view` to add view
configurations, you don't need to issue a :term:`scan` in order for the view
configuration to take effect.
.. index::
single: view_defaults class decorator
.. _view_defaults:
``@view_defaults`` Class Decorator
----------------------------------
.. versionadded:: 1.3
If you use a class as a view, you can use the
:class:`pyramid.view.view_defaults` class decorator on the class to provide
defaults to the view configuration information used by every ``@view_config``
decorator that decorates a method of that class.
For instance, if you've got a class that has methods that represent "REST
actions", all of which are mapped to the same route but different request
methods, instead of this:
.. code-block:: python
:linenos:
from pyramid.view import view_config
from pyramid.response import Response
class RESTView(object):
def __init__(self, request):
self.request = request
@view_config(route_name='rest', request_method='GET')
def get(self):
return Response('get')
@view_config(route_name='rest', request_method='POST')
def post(self):
return Response('post')
@view_config(route_name='rest', request_method='DELETE')
def delete(self):
return Response('delete')
You can do this:
.. code-block:: python
:linenos:
from pyramid.view import view_defaults
from pyramid.view import view_config
from pyramid.response import Response
@view_defaults(route_name='rest')
class RESTView(object):
def __init__(self, request):
self.request = request
@view_config(request_method='GET')
def get(self):
return Response('get')
@view_config(request_method='POST')
def post(self):
return Response('post')
@view_config(request_method='DELETE')
def delete(self):
return Response('delete')
In the above example, we were able to take the ``route_name='rest'`` argument
out of the call to each individual ``@view_config`` statement because we used a
``@view_defaults`` class decorator to provide the argument as a default to each
view method it possessed.
Arguments passed to ``@view_config`` will override any default passed to
``@view_defaults``.
The ``view_defaults`` class decorator can also provide defaults to the
:meth:`pyramid.config.Configurator.add_view` directive when a decorated class
is passed to that directive as its ``view`` argument. For example, instead of
this:
.. code-block:: python
:linenos:
from pyramid.response import Response
from pyramid.config import Configurator
class RESTView(object):
def __init__(self, request):
self.request = request
def get(self):
return Response('get')
def post(self):
return Response('post')
def delete(self):
return Response('delete')
def main(global_config, **settings):
config = Configurator()
config.add_route('rest', '/rest')
config.add_view(
RESTView, route_name='rest', attr='get', request_method='GET')
config.add_view(
RESTView, route_name='rest', attr='post', request_method='POST')
config.add_view(
RESTView, route_name='rest', attr='delete', request_method='DELETE')
return config.make_wsgi_app()
To reduce the amount of repetition in the ``config.add_view`` statements, we
can move the ``route_name='rest'`` argument to a ``@view_defaults`` class
decorator on the ``RESTView`` class:
.. code-block:: python
:linenos:
from pyramid.view import view_defaults
from pyramid.response import Response
from pyramid.config import Configurator
@view_defaults(route_name='rest')
class RESTView(object):
def __init__(self, request):
self.request = request
def get(self):
return Response('get')
def post(self):
return Response('post')
def delete(self):
return Response('delete')
def main(global_config, **settings):
config = Configurator()
config.add_route('rest', '/rest')
config.add_view(RESTView, attr='get', request_method='GET')
config.add_view(RESTView, attr='post', request_method='POST')
config.add_view(RESTView, attr='delete', request_method='DELETE')
return config.make_wsgi_app()
:class:`pyramid.view.view_defaults` accepts the same set of arguments that
:class:`pyramid.view.view_config` does, and they have the same meaning. Each
argument passed to ``view_defaults`` provides a default for the view
configurations of methods of the class it's decorating.
Normal Python inheritance rules apply to defaults added via ``view_defaults``.
For example:
.. code-block:: python
:linenos:
@view_defaults(route_name='rest')
class Foo(object):
pass
class Bar(Foo):
pass
The ``Bar`` class above will inherit its view defaults from the arguments
passed to the ``view_defaults`` decorator of the ``Foo`` class. To prevent
this from happening, use a ``view_defaults`` decorator without any arguments on
the subclass:
.. code-block:: python
:linenos:
@view_defaults(route_name='rest')
class Foo(object):
pass
@view_defaults()
class Bar(Foo):
pass
The ``view_defaults`` decorator only works as a class decorator; using it
against a function or a method will produce nonsensical results.
.. index::
single: view security
pair: security; view
.. _view_security_section:
Configuring View Security
~~~~~~~~~~~~~~~~~~~~~~~~~
If an :term:`authorization policy` is active, any :term:`permission` attached
to a :term:`view configuration` found during view lookup will be verified. This
will ensure that the currently authenticated user possesses that permission
against the :term:`context` resource before the view function is actually
called. Here's an example of specifying a permission in a view configuration
using :meth:`~pyramid.config.Configurator.add_view`:
.. code-block:: python
:linenos:
# config is an instance of pyramid.config.Configurator
config.add_route('add', '/add.html', factory='mypackage.Blog')
config.add_view('myproject.views.add_entry', route_name='add',
permission='add')
When an :term:`authorization policy` is enabled, this view will be protected
with the ``add`` permission. The view will *not be called* if the user does
not possess the ``add`` permission relative to the current :term:`context`.
Instead the :term:`forbidden view` result will be returned to the client as per
:ref:`protecting_views`.
.. index::
single: debugging not found errors
single: not found error (debugging)
.. _debug_notfound_section:
:exc:`~pyramid.exceptions.NotFound` Errors
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
It's useful to be able to debug :exc:`~pyramid.exceptions.NotFound` error
responses when they occur unexpectedly due to an application registry
misconfiguration. To debug these errors, use the ``PYRAMID_DEBUG_NOTFOUND``
environment variable or the ``pyramid.debug_notfound`` configuration file
setting. Details of why a view was not found will be printed to ``stderr``,
and the browser representation of the error will include the same information.
See :ref:`environment_chapter` for more information about how, and where to set
these values.
.. index::
single: HTTP caching
.. _influencing_http_caching:
Influencing HTTP Caching
------------------------
.. versionadded:: 1.1
When a non-``None`` ``http_cache`` argument is passed to a view configuration,
Pyramid will set ``Expires`` and ``Cache-Control`` response headers in the
resulting response, causing browsers to cache the response data for some time.
See ``http_cache`` in :ref:`nonpredicate_view_args` for the allowable values
and what they mean.
Sometimes it's undesirable to have these headers set as the result of returning
a response from a view, even though you'd like to decorate the view with a view
configuration decorator that has ``http_cache``. Perhaps there's an
alternative branch in your view code that returns a response that should never
be cacheable, while the "normal" branch returns something that should always be
cacheable. If this is the case, set the ``prevent_auto`` attribute of the
``response.cache_control`` object to a non-``False`` value. For example, the
below view callable is configured with a ``@view_config`` decorator that
indicates any response from the view should be cached for 3600 seconds.
However, the view itself prevents caching from taking place unless there's a
``should_cache`` GET or POST variable:
.. code-block:: python
from pyramid.view import view_config
@view_config(http_cache=3600)
def view(request):
response = Response()
if 'should_cache' not in request.params:
response.cache_control.prevent_auto = True
return response
Note that the ``http_cache`` machinery will overwrite or add to caching headers
you set within the view itself, unless you use ``prevent_auto``.
You can also turn off the effect of ``http_cache`` entirely for the duration of
a Pyramid application lifetime. To do so, set the
``PYRAMID_PREVENT_HTTP_CACHE`` environment variable or the
``pyramid.prevent_http_cache`` configuration value setting to a true value. For
more information, see :ref:`preventing_http_caching`.
Note that setting ``pyramid.prevent_http_cache`` will have no effect on caching
headers that your application code itself sets. It will only prevent caching
headers that would have been set by the Pyramid HTTP caching machinery invoked
as the result of the ``http_cache`` argument to view configuration.
.. index::
pair: view configuration; debugging
.. _debugging_view_configuration:
Debugging View Configuration
----------------------------
See :ref:`displaying_matching_views` for information about how to display
each of the view callables that might match for a given URL. This can be an
effective way to figure out why a particular view callable is being called
instead of the one you'd like to be called.
|