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
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
|
.. index::
single: URL dispatch
.. _urldispatch_chapter:
URL Dispatch
============
:term:`URL dispatch` provides a simple way to map URLs to :term:`view`
code using a simple pattern matching language. An ordered set of
patterns is checked one-by-one. If one of the patterns matches the path
information associated with a request, a particular :term:`view
callable` is invoked.
:term:`URL dispatch` is one of two ways to perform :term:`resource
location` in :app:`Pyramid`; the other way is using :term:`traversal`.
If no route is matched using :term:`URL dispatch`, :app:`Pyramid` falls
back to :term:`traversal` to handle the :term:`request`.
It is the responsibility of the :term:`resource location` subsystem
(i.e., :term:`URL dispatch` or :term:`traversal`) to find the resource
object that is the :term:`context` of the :term:`request`. Once the
:term:`context` is determined, :term:`view lookup` is then responsible
for finding and invoking a :term:`view callable`. A view callable is a
specific bit of code, defined in your application, that receives the
:term:`request` and returns a :term:`response` object.
Where appropriate, we will describe how view lookup interacts with
:term:`resource location`. The :ref:`view_config_chapter` chapter describes
the details of :term:`view lookup`.
High-Level Operational Overview
-------------------------------
If route configuration is present in an application, the :app:`Pyramid`
:term:`Router` checks every incoming request against an ordered set of URL
matching patterns present in a *route map*.
If any route pattern matches the information in the :term:`request`,
:app:`Pyramid` will invoke :term:`view lookup` using a :term:`context`
resource generated by the route match.
However, if no route pattern matches the information in the :term:`request`
provided to :app:`Pyramid`, it will fail over to using :term:`traversal` to
perform resource location and view lookup.
Technically, URL dispatch is a :term:`resource location` mechanism (it finds
a context object). But ironically, using URL dispatch (instead of
:term:`traversal`) allows you to avoid thinking about your application in
terms of "resources" entirely, because it allows you to directly map a
:term:`view callable` to a route.
Route Configuration
-------------------
:term:`Route configuration` is the act of adding a new :term:`route` to an
application. A route has a *pattern*, representing a pattern meant to match
against the ``PATH_INFO`` portion of a URL (the portion following the scheme
and port, e.g. ``/foo/bar`` in the URL ``http://localhost:8080/foo/bar``),
and a *route name*, which is used by developers within a :app:`Pyramid`
application to uniquely identify a particular route when generating a URL.
It also optionally has a ``factory``, a set of :term:`route predicate`
parameters, and a set of :term:`view` parameters.
.. index::
single: add_route
Configuring a Route via The ``add_route`` Configurator Method
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The :meth:`pyramid.config.Configurator.add_route` method adds a single
:term:`route configuration` to the :term:`application registry`. Here's an
example:
.. ignore-next-block
.. code-block:: python
# "config" below is presumed to be an instance of the
# pyramid.config.Configurator class; "myview" is assumed
# to be a "view callable" function
from views import myview
config.add_route('myroute', '/prefix/{one}/{two}', view=myview)
.. versionchanged:: 1.0a4
Prior to 1.0a4, routes allow for a marker starting with a ``:``, for
example ``/prefix/:one/:two``. This style is now deprecated
in favor or ``{}`` usage which allows for additional functionality.
.. index::
single: route configuration; view callable
Route Configuration That Names a View Callable
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
When a route configuration declaration names a ``view`` attribute, the value
of the attribute will reference a :term:`view callable`. This view callable
will be invoked when the route matches. A view callable, as described in
:ref:`view_chapter`, is developer-supplied code that "does stuff" as the
result of a request. For more information about how to create view
callables, see :ref:`views_chapter`.
Here's an example route configuration that references a view callable:
.. code-block:: python
:linenos:
# "config" below is presumed to be an instance of the
# pyramid.config.Configurator class; "myview" is assumed
# to be a "view callable" function
from myproject.views import myview
config.add_route('myroute', '/prefix/{one}/{two}', view=myview)
You can also pass a :term:`dotted Python name` as the ``view`` argument
rather than an actual callable:
.. code-block:: python
:linenos:
# "config" below is presumed to be an instance of the
# pyramid.config.Configurator class; "myview" is assumed
# to be a "view callable" function
config.add_route('myroute', '/prefix/{one}/{two}',
view='myproject.views.myview')
When a route configuration names a ``view`` attribute, the :term:`view
callable` named as that ``view`` attribute will always be found and invoked
when the associated route pattern matches during a request.
Route View Callable Registration and Lookup Details
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
The purpose of making it possible to specify a view callable within a route
configuration is to prevent developers from needing to deeply understand the
details of :term:`resource location` and :term:`view lookup`. When a route
names a view callable as a ``view`` argument, and a request enters the system
which matches the pattern of the route, the result is simple: the view
callable associated with the route is invoked with the request that caused
the invocation.
For most usage, you needn't understand more than this; how it works is an
implementation detail. In the interest of completeness, however, we'll
explain how it *does* work in the this section. You can skip it if you're
uninterested.
When a ``view`` attribute is attached to a route configuration,
:app:`Pyramid` ensures that a :term:`view configuration` is registered that
will always be found when the route pattern is matched during a request. To
do so:
- A special route-specific :term:`interface` is created at startup time for
each route configuration declaration.
- When a route configuration declaration mentions a ``view`` attribute, a
:term:`view configuration` is registered at startup time. This view
configuration uses the route-specific interface as a :term:`request` type.
- At runtime, when a request causes any route to match, the :term:`request`
object is decorated with the route-specific interface.
- The fact that the request is decorated with a route-specific interface
causes the view lookup machinery to always use the view callable registered
using that interface by the route configuration to service requests that
match the route pattern.
In this way, we supply a shortcut to the developer. Under the hood, the
:term:`resource location` and :term:`view lookup` subsystems provided by
:app:`Pyramid` are still being utilized, but in a way which does not require
a developer to understand either of them in detail. It also means that we
can allow a developer to combine :term:`URL dispatch` and :term:`traversal`
in various exceptional cases as documented in :ref:`hybrid_chapter`.
.. index::
single: route path pattern syntax
.. _route_pattern_syntax:
Route Pattern Syntax
~~~~~~~~~~~~~~~~~~~~
The syntax of the pattern matching language used by :app:`Pyramid` URL
dispatch in the *pattern* argument is straightforward; it is close to that of
the :term:`Routes` system used by :term:`Pylons`.
The *pattern* used in route configuration may start with a slash character.
If the pattern does not start with a slash character, an implicit slash will
be prepended to it at matching time. For example, the following patterns are
equivalent:
.. code-block:: text
{foo}/bar/baz
and:
.. code-block:: text
/{foo}/bar/baz
A pattern segment (an individual item between ``/`` characters in the
pattern) may either be a literal string (e.g. ``foo``) *or* it may be a
replacement marker (e.g. ``{foo}``) or a certain combination of both. A
replacement marker does not need to be preceded by a ``/`` character.
A replacement marker is in the format ``{name}``, where this means "accept
any characters up to the next non-alphanumeric character and use this as the
``name`` matchdict value." For example, the following pattern defines one
literal segment ("foo") and two dynamic replacement markers ("baz", and
"bar"):
.. code-block:: text
foo/{baz}/{bar}
The above pattern will match these URLs, generating the following matchdicts:
.. code-block:: text
foo/1/2 -> {'baz':u'1', 'bar':u'2'}
foo/abc/def -> {'baz':u'abc', 'bar':u'def'}
It will not match the following patterns however:
.. code-block:: text
foo/1/2/ -> No match (trailing slash)
bar/abc/def -> First segment literal mismatch
The match for a segment replacement marker in a segment will be done only up
to the first non-alphanumeric character in the segment in the pattern. So,
for instance, if this route pattern was used:
.. code-block:: text
foo/{name}.html
The literal path ``/foo/biz.html`` will match the above route pattern, and
the match result will be ``{'name':u'biz'}``. However, the literal path
``/foo/biz`` will not match, because it does not contain a literal ``.html``
at the end of the segment represented by ``{name}.html`` (it only contains
``biz``, not ``biz.html``).
To capture both segments, two replacement markers can be used:
.. code-block:: text
foo/{name}.{ext}
The literal path ``/foo/biz.html`` will match the above route pattern, and
the match result will be ``{'name': 'biz', 'ext': 'html'}``. This occurs
because the replacement marker ``{name}`` has a literal part of ``.``
(period) between the other replacement marker ``{ext}``.
It is possible to use two replacement markers without any literal characters
between them, for instance ``/{foo}{bar}``. However, this would be a
nonsensical pattern without specifying a custom regular expression to
restrict what each marker captures.
Segments must contain at least one character in order to match a segment
replacement marker. For example, for the URL ``/abc/``:
- ``/abc/{foo}`` will not match.
- ``/{foo}/`` will match.
Note that values representing path segments matched with a ``{segment}``
match will be url-unquoted and decoded from UTF-8 into Unicode within the
matchdict. So for instance, the following pattern:
.. code-block:: text
foo/{bar}
When matching the following URL:
.. code-block:: text
foo/La%20Pe%C3%B1a
The matchdict will look like so (the value is URL-decoded / UTF-8 decoded):
.. code-block:: text
{'bar':u'La Pe\xf1a'}
If the pattern has a ``*`` in it, the name which follows it is considered a
"remainder match". A remainder match *must* come at the end of the pattern.
Unlike segment replacement markers, it does not need to be preceded by a
slash. For example:
.. code-block:: text
foo/{baz}/{bar}*fizzle
The above pattern will match these URLs, generating the following matchdicts:
.. code-block:: text
foo/1/2/ -> {'baz':'1', 'bar':'2', 'fizzle':()}
foo/abc/def/a/b/c -> {'baz':'abc', 'bar':'def', 'fizzle':('a', 'b', 'c')}
Note that when a ``*stararg`` remainder match is matched, the value put into
the matchdict is turned into a tuple of path segments representing the
remainder of the path. These path segments are url-unquoted and decoded from
UTF-8 into Unicode. For example, for the following pattern:
.. code-block:: text
foo/*fizzle
When matching the following path:
.. code-block:: text
/foo/La%20Pe%C3%B1a/a/b/c
Will generate the following matchdict:
.. code-block:: text
{'fizzle':(u'La Pe\xf1a', u'a', u'b', u'c')}
By default, the ``*stararg`` will parse the remainder sections into a tuple
split by segment. Changing the regular expression used to match a marker can
also capture the remainder of the URL, for example:
.. code-block:: text
foo/{baz}/{bar}{fizzle:.*}
The above pattern will match these URLs, generating the following matchdicts:
.. code-block:: text
foo/1/2/ -> {'baz':'1', 'bar':'2', 'fizzle':()}
foo/abc/def/a/b/c -> {'baz':'abc', 'bar':'def', 'fizzle': 'a/b/c')}
This occurs because the default regular expression for a marker is ``[^/]+``
which will match everything up to the first ``/``, while ``{fizzle:.*}`` will
result in a regular expression match of ``.*`` capturing the remainder into a
single value.
.. index::
single: route ordering
Route Declaration Ordering
~~~~~~~~~~~~~~~~~~~~~~~~~~
Route configuration declarations are evaluated in a specific order when a
request enters the system. As a result, the order of route configuration
declarations is very important.
The order that routes declarations are evaluated is the order in which they
are added to the application at startup time. This is unlike
:term:`traversal`, which depends on emergent behavior which happens as a
result of traversing a resource tree.
For routes added via the :mod:`pyramid.config.Configurator.add_route` method,
the order that routes are evaluated is the order in which they are added to
the configuration imperatively.
For example, route configuration statements with the following patterns might
be added in the following order:
.. code-block:: text
members/{def}
members/abc
In such a configuration, the ``members/abc`` pattern would *never* be
matched. This is because the match ordering will always match
``members/{def}`` first; the route configuration with ``members/abc`` will
never be evaluated.
.. index::
single: route factory
.. _route_factories:
Route Factories
~~~~~~~~~~~~~~~
A "route" configuration declaration can mention a "factory". When that route
matches a request, and a factory is attached to a route, the :term:`root
factory` passed at startup time to the :term:`Configurator` is ignored;
instead the factory associated with the route is used to generate a
:term:`root` object. This object will usually be used as the :term:`context`
resource of the view callable ultimately found via :term:`view lookup`.
.. code-block:: python
:linenos:
config.add_route('abc', '/abc', view='myproject.views.theview',
factory='myproject.resources.root_factory')
The factory can either be a Python object or a :term:`dotted Python name` (a
string) which points to such a Python object, as it is above.
In this way, each route can use a different factory, making it possible to
supply a different :term:`context` resource object to the view related to
each particular route.
Supplying a different resource factory each route is useful when you're
trying to use a :app:`Pyramid` :term:`authorization policy` to provide
declarative, "context sensitive" security checks; each resource can maintain
a separate :term:`ACL`, as documented in
:ref:`using_security_with_urldispatch`. It is also useful when you wish to
combine URL dispatch with :term:`traversal` as documented within
:ref:`hybrid_chapter`.
Route Configuration Arguments
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Route configuration ``add_route`` statements may specify a large number of
arguments.
Many of these arguments are :term:`route predicate` arguments. A route
predicate argument specifies that some aspect of the request must be true for
the associated route to be considered a match during the route matching
process.
Other arguments are view configuration related arguments. These only have an
effect when the route configuration names a ``view``.
Other arguments are ``name`` and ``factory``. These arguments represent
neither predicates nor view configuration information.
**Non-Predicate Arguments**
``name``
The name of the route, e.g. ``myroute``. This attribute is required. It
must be unique among all defined routes in a given application.
``factory``
A Python object (often a function or a class) or a :term:`dotted Python
name` to such an object that will generate a :app:`Pyramid` resource object
as the :term:`root` when this route matches. For example,
``mypackage.resources.MyFactoryClass``. If this argument is not specified,
the traversal root factory will be used.
``traverse``
If you would like to cause the :term:`context` resource to be something
other than the :term:`root` resource object when this route matches, you
can spell a traversal pattern as the ``traverse`` argument. This traversal
pattern will be used as the traversal path: traversal will begin at the
root object implied by this route (either the global root, or the object
returned by the ``factory`` associated with this route).
The syntax of the ``traverse`` argument is the same as it is for
``pattern``. For example, if the ``pattern`` provided is
``articles/{article}/edit``, and the ``traverse`` argument provided is
``/{article}``, when a request comes in that causes the route to match in
such a way that the ``article`` match value is '1' (when the request URI is
``/articles/1/edit``), the traversal path will be generated as ``/1``.
This means that the root object's ``__getitem__`` will be called with the
name ``1`` during the traversal phase. If the ``1`` object exists, it will
become the :term:`context` resource of the request.
:ref:`traversal_chapter` has more information about traversal.
If the traversal path contains segment marker names which are not present
in the ``pattern`` argument, a runtime error will occur. The ``traverse``
pattern should not contain segment markers that do not exist in the
``pattern``.
A similar combining of routing and traversal is available when a route is
matched which contains a ``*traverse`` remainder marker in its pattern (see
:ref:`using_traverse_in_a_route_pattern`). The ``traverse`` argument
allows you to associate route patterns with an arbitrary traversal path
without using a a ``*traverse`` remainder marker; instead you can use other
match information.
Note that the ``traverse`` argument is ignored when attached to a route
that has a ``*traverse`` remainder marker in its pattern.
**Predicate Arguments**
``pattern``
The path of the route e.g. ``ideas/{idea}``. This argument is required.
See :ref:`route_path_pattern_syntax` for information about the syntax of
route paths. If the path doesn't match the current URL, route matching
continues.
.. note:: In earlier releases of this framework, this argument existed
as ``path``. ``path`` continues to work as an alias for
``pattern``.
``xhr``
This value should be either ``True`` or ``False``. If this value is
specified and is ``True``, the :term:`request` must possess an
``HTTP_X_REQUESTED_WITH`` (aka ``X-Requested-With``) header for this route
to match. This is useful for detecting AJAX requests issued from jQuery,
Prototype and other Javascript libraries. If this predicate returns
``False``, route matching continues.
``request_method``
A string representing an HTTP method name, e.g. ``GET``, ``POST``,
``HEAD``, ``DELETE``, ``PUT``. If this argument is not specified, this
route will match if the request has *any* request method. If this
predicate returns ``False``, route matching continues.
``path_info``
This value represents a regular expression pattern that will be tested
against the ``PATH_INFO`` WSGI environment variable. If the regex matches,
this predicate will return ``True``. If this predicate returns ``False``,
route matching continues.
``request_param``
This value can be any string. A view declaration with this argument
ensures that the associated route will only match when the 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 the value
supplied as the argument has a ``=`` sign in it,
e.g. ``request_params="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 route to "match" the current
request. If this predicate returns ``False``, route matching continues.
``header``
This argument represents an HTTP header name or a header name/value pair.
If the argument contains a ``:`` (colon), it will be considered a
name/value pair (e.g. ``User-Agent:Mozilla/.*`` or ``Host:localhost``). If
the value contains a colon, the value portion should be a regular
expression. If the value does not contain a colon, the entire value will
be considered to be the header name (e.g. ``If-Modified-Since``). If the
value evaluates to a header name only without a value, the header specified
by the name must be present in the request for this predicate to be true.
If the value evaluates to a header name/value pair, the header specified by
the name must be present in the request *and* the regular expression
specified as the value must match the header value. 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 this predicate returns ``False``, route
matching continues.
``accept``
This value 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 this predicate returns ``False``, route matching continues.
``custom_predicates``
This value should be a sequence of references to custom predicate
callables. Use custom predicates when no set of predefined predicates does
what you need. Custom predicates can be combined with predefined
predicates as necessary. Each custom predicate callable should accept two
arguments: ``info`` 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 route will
be considered viable for a given request. If any custom predicate returns
``False``, route matching continues. See :ref:`custom_route_predicates`
for more information.
**View-Related Arguments**
``view``
A Python object or a :term:`dotted Python name` to such an object that will
be used as a view callable when this route
matches. e.g. ``mypackage.views.my_view``.
``view_context``
A class or an :term:`interface` (or a :term:`dotted Python name` to such an
object) that the :term:`context` resource should possess for the view named
by the route to be used. If this attribute is not specified, the default
(``None``) will be used.
If the ``view`` argument is not provided, this argument has no effect.
This attribute can also be spelled as ``for_`` or ``view_for``.
``view_permission``
The permission name required to invoke the view associated with this route.
e.g. ``edit``. (see :ref:`using_security_with_urldispatch` for more
information about permissions).
If the ``view`` attribute is not provided, this argument has no effect.
This argument can also be spelled as ``permission``.
``view_renderer``
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``). If the
renderer value is a single term (does not contain a dot ``.``), the
specified term 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 term 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. The renderer implementation will be
used to construct a response from the view return value. See
:ref:`views_which_use_a_renderer` for more information.
If the ``view`` argument is not provided, this argument has no effect.
This argument can also be spelled as ``renderer``.
``view_attr``
The view machinery defaults to using the ``__call__`` method of the view
callable (or the function itself, if the view callable is a function) to
obtain a response dictionary. 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' ``__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 the ``view`` argument is not provided, this argument has no
effect.
``use_global_views``
When a request matches this route, and view lookup cannot find a view which
has a 'route_name' predicate argument that matches the route, try to fall
back to using a view that otherwise matches the context and request.
.. _custom_route_predicates:
Custom Route Predicates
~~~~~~~~~~~~~~~~~~~~~~~
Each of the predicate callables fed to the ``custom_predicates`` argument of
:meth:`pyramid.config.Configurator.add_route` must be a callable accepting
two arguments. The first argument passed to a custom predicate is a
dictionary conventionally named ``info``. The second argument is the current
:term:`request` object.
The ``info`` dictionary has a number of contained values: ``match`` is a
dictionary: it represents the arguments matched in the URL by the route.
``route`` is an object representing the route which was matched (see
:class:`pyramid.interfaces.IRoute` for the API of such a route object).
``info['match']`` is useful when predicates need access to the route match.
For example:
.. code-block:: python
:linenos:
def any_of(segment_name, *allowed):
def predicate(info, request):
if info['match'][segment_name] in allowed:
return True
return predicate
num_one_two_or_three = any_of('num', 'one', 'two', 'three')
config.add_route('num', '/{num}',
custom_predicates=(num_one_two_or_three,))
The above ``any_of`` function generates a predicate which ensures that the
match value named ``segment_name`` is in the set of allowable values
represented by ``allowed``. We use this ``any_of`` function to generate a
predicate function named ``num_one_two_or_three``, which ensures that the
``num`` segment is one of the values ``one``, ``two``, or ``three`` , and use
the result as a custom predicate by feeding it inside a tuple to the
``custom_predicates`` argument to
:meth:`pyramid.config.Configurator.add_route`.
A custom route predicate may also *modify* the ``match`` dictionary. For
instance, a predicate might do some type conversion of values:
.. code-block:: python
:linenos:
def integers(*segment_names):
def predicate(info, request):
match = info['match']
for segment_name in segment_names:
try:
match[segment_name] = int(match[segment_name])
except (TypeError, ValueError):
pass
return True
return predicate
ymd_to_int = integers('year', 'month', 'day')
config.add_route('num', '/{year}/{month}/{day}',
custom_predicates=(ymd_to_int,))
Note that a conversion predicate is still a predicate so it must return
``True`` or ``False``; a predicate that does *only* conversion, such as the
one we demonstrate above should unconditionally return ``True``.
To avoid the try/except uncertainty, the route pattern can contain regular
expressions specifying requirements for that marker. For instance:
.. code-block:: python
:linenos:
def integers(*segment_names):
def predicate(info, request):
match = info['match']
for segment_name in segment_names:
match[segment_name] = int(match[segment_name])
return True
return predicate
ymd_to_int = integers('year', 'month', 'day')
config.add_route('num', '/{year:\d+}/{month:\d+}/{day:\d+}',
custom_predicates=(ymd_to_int,))
Now the try/except is no longer needed because the route will not match at
all unless these markers match ``\d+`` which requires them to be valid digits
for an ``int`` type conversion.
The ``match`` dictionary passed within ``info`` to each predicate attached to
a route will be the same dictionary. Therefore, when registering a custom
predicate which modifies the ``match`` dict, the code registering the
predicate should usually arrange for the predicate to be the *last* custom
predicate in the custom predicate list. Otherwise, custom predicates which
fire subsequent to the predicate which performs the ``match`` modification
will receive the *modified* match dictionary.
.. warning::
It is a poor idea to rely on ordering of custom predicates to build a
conversion pipeline, where one predicate depends on the side effect of
another. For instance, it's a poor idea to register two custom
predicates, one which handles conversion of a value to an int, the next
which handles conversion of that integer to some custom object. Just do
all that in a single custom predicate.
The ``route`` object in the ``info`` dict is an object that has two useful
attributes: ``name`` and ``pattern``. The ``name`` attribute is the route
name. The ``pattern`` attribute is the route pattern. An example of using
the route in a set of route predicates:
.. code-block:: python
:linenos:
def twenty_ten(info, request):
if info['route'].name in ('ymd', 'ym', 'y'):
return info['match']['year'] == '2010'
config.add_route('y', '/{year}', custom_predicates=(twenty_ten,))
config.add_route('ym', '/{year}/{month}', custom_predicates=(twenty_ten,))
config.add_route('ymd', '/{year}/{month}/{day}',
custom_predicates=(twenty_ten,))
The above predicate, when added to a number of route configurations ensures
that the year match argument is '2010' if and only if the route name is
'ymd', 'ym', or 'y'.
See also :class:`pyramid.interfaces.IRoute` for more API documentation about
route objects.
Route Matching
--------------
The main purpose of route configuration is to match (or not match) the
``PATH_INFO`` present in the WSGI environment provided during a request
against a URL path pattern.
The way that :app:`Pyramid` does this is very simple. When a request enters
the system, for each route configuration declaration present in the system,
:app:`Pyramid` checks the ``PATH_INFO`` against the pattern declared.
If any route matches, the route matching process stops. The :term:`request`
is decorated with a special :term:`interface` which describes it as a "route
request", the :term:`context` resource is generated, and the context and the
resulting request are handed off to :term:`view lookup`. During view lookup,
if any ``view`` argument was provided within the matched route configuration,
the :term:`view callable` it points to is called.
When a route configuration is declared, it may contain :term:`route
predicate` arguments. All route predicates associated with a route
declaration must be ``True`` for the route configuration to be used for a
given request.
If any predicate in the set of :term:`route predicate` arguments provided to
a route configuration returns ``False``, that route is skipped and route
matching continues through the ordered set of routes.
If no route matches after all route patterns are exhausted, :app:`Pyramid`
falls back to :term:`traversal` to do :term:`resource location` and
:term:`view lookup`.
.. index::
single: matchdict
.. _matchdict:
The Matchdict
~~~~~~~~~~~~~
When the URL pattern associated with a particular route configuration is
matched by a request, a dictionary named ``matchdict`` is added as an
attribute of the :term:`request` object. Thus, ``request.matchdict`` will
contain the values that match replacement patterns in the ``pattern``
element. The keys in a matchdict will be strings. The values will be
Unicode objects.
.. note::
If no route URL pattern matches, the ``matchdict`` object attached to the
request will be ``None``.
.. index::
single: matched_route
.. _matched_route:
The Matched Route
~~~~~~~~~~~~~~~~~
When the URL pattern associated with a particular route configuration is
matched by a request, an object named ``matched_route`` is added as an
attribute of the :term:`request` object. Thus, ``request.matched_route``
will be an object implementing the :class:`pyramid.interfaces.IRoute`
interface which matched the request. The most useful attribute of the route
object is ``name``, which is the name of the route that matched.
.. note::
If no route URL pattern matches, the ``matched_route`` object attached to
the request will be ``None``.
Routing Examples
----------------
Let's check out some examples of how route configuration statements might be
commonly declared, and what will happen if they are matched by the
information present in a request.
.. _urldispatch_example1:
Example 1
~~~~~~~~~
The simplest route declaration which configures a route match to *directly*
result in a particular view callable being invoked:
.. code-block:: python
:linenos:
config.add_route('idea', 'site/{id}', view='mypackage.views.site_view')
When a route configuration with a ``view`` attribute is added to the system,
and an incoming request matches the *pattern* of the route configuration, the
:term:`view callable` named as the ``view`` attribute of the route
configuration will be invoked.
In the case of the above example, when the URL of a request matches
``/site/{id}``, the view callable at the Python dotted path name
``mypackage.views.site_view`` will be called with the request. In other
words, we've associated a view callable directly with a route pattern.
When the ``/site/{id}`` route pattern matches during a request, the
``site_view`` view callable is invoked with that request as its sole
argument. When this route matches, a ``matchdict`` will be generated and
attached to the request as ``request.matchdict``. If the specific URL
matched is ``/site/1``, the ``matchdict`` will be a dictionary with a single
key, ``id``; the value will be the string ``'1'``, ex.: ``{'id':'1'}``.
The ``mypackage.views`` module referred to above might look like so:
.. code-block:: python
:linenos:
from pyramid.response import Response
def site_view(request):
return Response(request.matchdict['id'])
The view has access to the matchdict directly via the request, and can access
variables within it that match keys present as a result of the route pattern.
See :ref:`views_chapter`, and :ref:`view_config_chapter` for more
information about views.
Example 2
~~~~~~~~~
Below is an example of a more complicated set of route statements you might
add to your application:
.. code-block:: python
:linenos:
config.add_route('idea', 'ideas/{idea}', view='mypackage.views.idea_view')
config.add_route('user', 'users/{user}', view='mypackage.views.user_view')
config.add_route('tag', 'tags/{tags}', view='mypackage.views.tag_view')
The above configuration will allow :app:`Pyramid` to service URLs in these
forms:
.. code-block:: text
/ideas/{idea}
/users/{user}
/tags/{tag}
- When a URL matches the pattern ``/ideas/{idea}``, the view callable
available at the dotted Python pathname ``mypackage.views.idea_view`` will
be called. For the specific URL ``/ideas/1``, the ``matchdict`` generated
and attached to the :term:`request` will consist of ``{'idea':'1'}``.
- When a URL matches the pattern ``/users/{user}``, the view callable
available at the dotted Python pathname ``mypackage.views.user_view`` will
be called. For the specific URL ``/users/1``, the ``matchdict`` generated
and attached to the :term:`request` will consist of ``{'user':'1'}``.
- When a URL matches the pattern ``/tags/{tag}``, the view callable available
at the dotted Python pathname ``mypackage.views.tag_view`` will be called.
For the specific URL ``/tags/1``, the ``matchdict`` generated and attached
to the :term:`request` will consist of ``{'tag':'1'}``.
In this example we've again associated each of our routes with a :term:`view
callable` directly. In all cases, the request, which will have a
``matchdict`` attribute detailing the information found in the URL by the
process will be passed to the view callable.
Example 3
~~~~~~~~~
The :term:`context` resource object passed in to a view found as the result
of URL dispatch will, by default, be an instance of the object returned by
the :term:`root factory` configured at startup time (the ``root_factory``
argument to the :term:`Configurator` used to configure the application).
You can override this behavior by passing in a ``factory`` argument to the
:meth:`pyramid.config.Configurator.add_route` method for a particular route.
The ``factory`` should be a callable that accepts a :term:`request` and
returns an instance of a class that will be the context resource used by the
view.
An example of using a route with a factory:
.. code-block:: python
:linenos:
config.add_route('idea', 'ideas/{idea}',
view='myproject.views.idea_view',
factory='myproject.resources.Idea')
The above route will manufacture an ``Idea`` resource as a :term:`context`,
assuming that ``mypackage.resources.Idea`` resolves to a class that accepts a
request in its ``__init__``. For example:
.. code-block:: python
:linenos:
class Idea(object):
def __init__(self, request):
pass
In a more complicated application, this root factory might be a class
representing a :term:`SQLAlchemy` model.
Example 4
~~~~~~~~~
It is possible to create a route declaration without a ``view`` attribute,
but associate the route with a :term:`view callable` using a ``view``
declaration.
.. code-block:: python
:linenos:
config.add_route('idea', 'site/{id}')
config.add_view(route_name='idea', view='mypackage.views.site_view')
This set of configuration parameters creates a configuration completely
equivalent to this example provided in :ref:`urldispatch_example1`:
.. code-block:: python
:linenos:
config.add_route('idea', 'site/{id}', view='mypackage.views.site_view')
In fact, the spelling which names a ``view`` attribute is just syntactic
sugar for the more verbose spelling which contains separate view and route
registrations.
More uses for this style of associating views with routes are explored in
:ref:`hybrid_chapter`.
.. index::
single: matching the root URL
single: root url (matching)
Matching the Root URL
---------------------
It's not entirely obvious how to use a route pattern to match the root URL
("/"). To do so, give the empty string as a pattern in a call to
:meth:`pyramid.config.Configurator.add_route`:
.. code-block:: python
:linenos:
config.add_route('root', '', view='mypackage.views.root_view')
Or provide the literal string ``/`` as the pattern:
.. code-block:: python
:linenos:
config.add_route('root', '/', view='mypackage.views.root_view')
.. index::
single: generating route URLs
single: route URLs
Generating Route URLs
---------------------
Use the :func:`pyramid.url.route_url` function to generate URLs based on
route patterns. For example, if you've configured a route with the ``name``
"foo" and the ``pattern`` "{a}/{b}/{c}", you might do this.
.. ignore-next-block
.. code-block:: python
:linenos:
from pyramid.url import route_url
url = route_url('foo', request, a='1', b='2', c='3')
This would return something like the string ``http://example.com/1/2/3`` (at
least if the current protocol and hostname implied ``http:/example.com``).
See the :func:`pyramid.url.route_url` API documentation for more information.
.. index::
single: redirecting to slash-appended routes
.. _redirecting_to_slash_appended_routes:
Redirecting to Slash-Appended Routes
------------------------------------
For behavior like Django's ``APPEND_SLASH=True``, use the
:func:`~pyramid.view.append_slash_notfound_view` view as the :term:`Not Found
view` in your application. Defining this view as the :term:`Not Found view`
is a way to automatically redirect requests where the URL lacks a trailing
slash, but requires one to match the proper route. When configured, along
with at least one other route in your application, this view will be invoked
if the value of ``PATH_INFO`` does not already end in a slash, and if the
value of ``PATH_INFO`` *plus* a slash matches any route's pattern. In this
case it does an HTTP redirect to the slash-appended ``PATH_INFO``.
Let's use an example, because this behavior is a bit magical. If the
``append_slash_notfound_view`` is configured in your application and your
route configuration looks like so:
.. code-block:: python
:linenos:
config.add_route('noslash', 'no_slash', view='myproject.views.no_slash')
config.add_route('hasslash', 'has_slash/', view='myproject.views.has_slash')
If a request enters the application with the ``PATH_INFO`` value of
``/has_slash/``, the second route will match. If a request enters the
application with the ``PATH_INFO`` value of ``/has_slash``, a route *will* be
found by the slash-appending not found view. An HTTP redirect to
``/has_slash/`` will be returned to the user's browser.
If a request enters the application with the ``PATH_INFO`` value of
``/no_slash``, the first route will match. However, if a request enters the
application with the ``PATH_INFO`` value of ``/no_slash/``, *no* route will
match, and the slash-appending not found view will *not* find a matching
route with an appended slash.
.. warning::
You **should not** rely on this mechanism to redirect ``POST`` requests.
The redirect of the slash-appending not found view will turn a ``POST``
request into a ``GET``, losing any ``POST`` data in the original
request.
To configure the slash-appending not found view in your application, change
the application's startup configuration, adding the following stanza:
.. code-block:: python
:linenos:
config.add_view(context='pyramid.exceptions.NotFound',
view='pyramid.view.append_slash_notfound_view')
See :ref:`view_module` and :ref:`changing_the_notfound_view` for more
information about the slash-appending not found view and for a more general
description of how to configure a not found view.
Custom Not Found View With Slash Appended Routes
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
There can only be one :term:`Not Found view` in any :app:`Pyramid`
application. Even if you use :func:`~pyramid.view.append_slash_notfound_view`
as the Not Found view, :app:`Pyramid` still must generate a ``404 Not Found``
response when it cannot redirect to a slash-appended URL; this not found
response will be visible to site users.
If you don't care what this 404 response looks like, and only you need
redirections to slash-appended route URLs, you may use the
:func:`~pyramid.view.append_slash_notfound_view` object as the Not Found view
as described above. However, if you wish to use a *custom* notfound view
callable when a URL cannot be redirected to a slash-appended URL, you may
wish to use an instance of the
:class:`~pyramid.view.AppendSlashNotFoundViewFactory` class as the Not Found
view, supplying a :term:`view callable` to be used as the custom notfound
view as the first argument to its constructor. For instance:
.. code-block:: python
:linenos:
from pyramid.exceptions import NotFound
from pyramid.view import AppendSlashNotFoundViewFactory
def notfound_view(context, request):
return HTTPNotFound('It aint there, stop trying!')
custom_append_slash = AppendSlashNotFoundViewFactory(notfound_view)
config.add_view(custom_append_slash, context=NotFound)
The ``notfound_view`` supplied must adhere to the two-argument view callable
calling convention of ``(context, request)`` (``context`` will be the
exception object).
.. _cleaning_up_after_a_request:
Cleaning Up After a Request
---------------------------
Sometimes it's required that some cleanup be performed at the end of a
request when a database connection is involved. When :term:`traversal` is
used, this cleanup is often done as a side effect of the traversal
:term:`root factory`. Often the root factory will insert an object into the
WSGI environment that performs some cleanup when its ``__del__`` method is
called. When URL dispatch is used, however, no special root factory is
required, so sometimes that option is not open to you.
Instead of putting this cleanup logic in the root factory, however, you can
cause a subscriber to be fired when a new request is detected; the subscriber
can do this work.
For example, let's say you have a ``mypackage`` :app:`Pyramid` application
package that uses SQLAlchemy, and you'd like the current SQLAlchemy database
session to be removed after each request. Put the following in the
``mypackage.__init__`` module:
.. ignore-next-block
.. code-block:: python
:linenos:
from mypackage.sql import DBSession
class Cleanup:
def __init__(self, cleaner):
self.cleaner = cleaner
def __del__(self):
self.cleaner()
def handle_teardown(event):
environ = event.request.environ
environ['mypackage.sqlcleaner'] = Cleanup(DBSession.remove)
Then add an event subscriber in your startup configuration:
.. code-block:: python
:linenos:
config.add_subscriber('mypackage.handle_teardown',
'pyramid.events.NewRequest')
Registering a handle_teardown subscriber will cause the DBSession to be
removed whenever the WSGI environment is destroyed (usually at the end of
every request).
.. note:: This is only an example. In particular, it is not necessary
to cause ``DBSession.remove`` to be called as the result of an
event listener in an application generated from any
:app:`Pyramid` paster template, because these all use the
``repoze.tm2`` middleware. The cleanup done by
``DBSession.remove`` is unnecessary when ``repoze.tm2`` middleware
is in the WSGI pipeline.
.. index::
pair: URL dispatch; security
.. _using_security_with_urldispatch:
Using :app:`Pyramid` Security With URL Dispatch
--------------------------------------------------
:app:`Pyramid` provides its own security framework which consults an
:term:`authorization policy` before allowing any application code to be
called. This framework operates in terms of an access control list, which is
stored as an ``__acl__`` attribute of a resource object. A common thing to
want to do is to attach an ``__acl__`` to the resource object dynamically for
declarative security purposes. You can use the ``factory`` argument that
points at a factory which attaches a custom ``__acl__`` to an object at its
creation time.
Such a ``factory`` might look like so:
.. code-block:: python
:linenos:
class Article(object):
def __init__(self, request):
matchdict = request.matchdict
article = matchdict.get('article', None)
if article == '1':
self.__acl__ = [ (Allow, 'editor', 'view') ]
If the route ``archives/{article}`` is matched, and the article number is
``1``, :app:`Pyramid` will generate an ``Article`` :term:`context` resource
with an ACL on it that allows the ``editor`` principal the ``view``
permission. Obviously you can do more generic things than inspect the routes
match dict to see if the ``article`` argument matches a particular string;
our sample ``Article`` factory class is not very ambitious.
.. note:: See :ref:`security_chapter` for more information about
:app:`Pyramid` security and ACLs.
.. _debug_routematch_section:
Debugging Route Matching
------------------------
It's useful to be able to take a peek under the hood when requests that enter
your application arent matching your routes as you expect them to. To debug
route matching, use the ``PYRAMID_DEBUG_ROUTEMATCH`` environment variable or the
``debug_routematch`` configuration file setting (set either to ``true``).
Details of the route matching decision for a particular request to the
:app:`Pyramid` application will be printed to the ``stderr`` of the console
which you started the application from. For example:
.. code-block:: text
:linenos:
[chrism@thinko pylonsbasic]$ PYRAMID_DEBUG_ROUTEMATCH=true \
bin/paster serve development.ini
Starting server in PID 13586.
serving on 0.0.0.0:6543 view at http://127.0.0.1:6543
2010-12-16 14:45:19,956 no route matched for url \
http://localhost:6543/wontmatch
2010-12-16 14:45:20,010 no route matched for url \
http://localhost:6543/favicon.ico
2010-12-16 14:41:52,084 route matched for url \
http://localhost:6543/static/logo.png; \
route_name: 'static/', ....
See :ref:`environment_chapter` for more information about how, and where to
set these values.
.. index::
pair: routes; printing
single: paster proutes
Displaying All Application Routes
---------------------------------
You can use the ``paster proutes`` command in a terminal window to print a
summary of routes related to your application. Much like the ``paster
pshell`` command (see :ref:`interactive shell`), the ``paster proutes``
command accepts two arguments. The first argument to ``proutes`` is the path
to your application's ``.ini`` file. The second is the ``app`` section name
inside the ``.ini`` file which points to your application.
For example:
.. code-block:: text
:linenos:
[chrism@thinko MyProject]$ ../bin/paster proutes development.ini MyProject
Name Pattern View
---- ------- ----
home / <function my_view>
home2 / <function my_view>
another /another None
static/ static/*subpath <static_view object>
catchall /*subpath <function static_view>
``paster proutes`` generates a table. The table has three columns: a Name
name column, a Pattern column, and a View column. The items listed in the
Name column are route names, the items listen in the Pattern column are route
patterns, and the items listed in the View column are representations of the
view callable that will be invoked when a request matches the associated
route pattern. The view column may show ``None`` if no associated view
callable could be found. If no routes are configured within your
application, nothing will be printed to the console when ``paster proutes``
is executed.
References
----------
A tutorial showing how :term:`URL dispatch` can be used to create a
:app:`Pyramid` application exists in :ref:`bfg_sql_wiki_tutorial`.
|