| | |
| | | |
| | | Speed |
| | | :app:`Pyramid` is designed to provide noticeably fast execution for common |
| | | tasks such as templating and simple response generation. Although “hardware |
| | | tasks such as templating and simple response generation. Although "hardware |
| | | is cheap", the limits of this approach become painfully evident when one |
| | | finds him or herself responsible for managing a great many machines. |
| | | |
| | | Reliability |
| | | :app:`Pyramid` is developed conservatively and tested exhaustively. Where |
| | | Pyramid source code is concerned, our motto is: "If it ain’t tested, it’s |
| | | broke". Every release of Pyramid has 100% statement coverage via unit |
| | | tests. |
| | | broke". |
| | | |
| | | Openness |
| | | As with Python, the Pyramid software is distributed under a `permissive |
| | | open source license <http://repoze.org/license.html>`_. |
| | | |
| | | What Makes Pyramid Unique |
| | | ------------------------- |
| | | |
| | | Understandably, people don't usually want to hear about squishy engineering |
| | | principles, they want to hear about concrete stuff that solves their |
| | | problems. With that in mind, what would make someone want to use Pyramid |
| | | instead of the dozens-of-odd other web frameworks available today? What |
| | | makes Pyramid unique? |
| | | |
| | | This is a hard question to answer, because there are lots of excellent |
| | | choices, and it's actually quite hard to make a wrong choice, particularly in |
| | | the Python web framework market. But one reasonable answer is this: you can |
| | | write very small applications in Pyramid without needing to know a lot. |
| | | "What?", you say, "that can't possibly be a unique feature, lots of other web |
| | | frameworks let you do that!" Well, you're right. But unlike many other |
| | | systems, you can also write very large applications in Pyramid if you learn a |
| | | little more about it. Pyramid will allow you to become productive quickly, |
| | | and will grow with you; it won't hold you back when your application is small |
| | | and it won't get in your way when your application becomes large. "Well |
| | | that's fine," you say, "lots of other frameworks let me write large apps |
| | | too." Absolutely. But other Python web frameworks don't seamlessly let you |
| | | do both. They seem to fall into two non-overlapping categories: frameworks |
| | | for "small apps" and frameworks for "big apps". The "small app" frameworks |
| | | typically sacrifice "big app" features, and vice versa. |
| | | |
| | | We don't think it's a universally reasonable suggestion to write "small apps" |
| | | in a "small framework" and "big apps" in a "big framework". You can't really |
| | | know what size every application will eventually grow to. We don't really |
| | | want to have to rewrite a previously small application in another framework |
| | | when it gets "too big". We believe the current binary distinction between |
| | | "small" and "large" frameworks is just false; one framework should be able to |
| | | be good at both if it's well-designed. Pyramid is such a framework. |
| | | |
| | | To this end, Pyramid provides a set of features, that, combined, are unique |
| | | amongst Python web frameworks. Lots of other frameworks contain some |
| | | combination of these features; Pyramid of course actually stole many of them |
| | | from those other frameworks. But Pyramid is the only one that has all of |
| | | them in one place, documented appropriately, and useful ala-carte without |
| | | necessarily paying for the entire banquet. These are detailed below. |
| | | |
| | | Single-File Applications |
| | | ~~~~~~~~~~~~~~~~~~~~~~~~ |
| | | |
| | | You can write a Pyramid application that lives entirely in one Python file, |
| | | not unlike existing Python microframeworks. This is beneficial for "one off" |
| | | prototyping, bug reproduction, and very small applications. These |
| | | applications are easy to understand because all the information about the |
| | | application lives in a single place, and you can deploy them without needing |
| | | to understand much about Python distributions and packaging. Pyramid isn't |
| | | really marketed as a "microframework", but it allows you to do almost |
| | | everything that frameworks that are marketed as "micro" offer in very similar |
| | | ways. |
| | | |
| | | Example: :ref:`firstapp_chapter`. |
| | | |
| | | Decorator-Based Configuration |
| | | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| | | |
| | | If you like the idea of framework configuration statements living next to the |
| | | code it configures, so you don't have to constantly switch between files to |
| | | refer to framework configuration when adding new code, you can use Pyramid |
| | | decorators to localize the configuration. For example:: |
| | | |
| | | @view_config(route_name='fred') |
| | | def fred_view(request): |
| | | return Response('fred') |
| | | |
| | | However, unlike other systems (various "microframeworks" come to mind), using |
| | | decorators for configuration does not make your application difficult, |
| | | extend, test or reuse. The ``view_config`` decorator, for example, does not |
| | | actually *change* the input or output of the function it decorates, so |
| | | testing it is a "WYSIWYG" operation; you don't need to understand the |
| | | framework to test your own code, you just behave as if the decorator is not |
| | | there. You can also instruct Pyramid to ignore some decorators, or use |
| | | completely imperative configuration instead of decorators to add views. |
| | | Pyramid decorators are inert instead of eager: you detect and activate them |
| | | with a ``scan``. They're basically just markers. |
| | | |
| | | Example: :ref:`mapping_views_using_a_decorator_section`. |
| | | |
| | | URL Generation |
| | | ~~~~~~~~~~~~~~ |
| | | |
| | | Pyramid is capable of generating URLs for resources, routes, and static |
| | | assets. Its URL generation APIs are easy to use and flexible. If you use |
| | | Pyramid's various APIs for generating URLs, you can change your configuration |
| | | around arbitrarily without fear of breaking a link on one of your web pages. |
| | | |
| | | Example: :ref:`generating_route_urls`. |
| | | |
| | | Static file serving |
| | | ~~~~~~~~~~~~~~~~~~~ |
| | | |
| | | Pyramid is perfectly willing to serve static files itself. It won't make you |
| | | use some external web server to do that. You can even serve more than one |
| | | set of static files in a single Pyramid web application (e.g. ``/static`` and |
| | | ``/static2``). You can also, optionally, place your files on an external web |
| | | server and ask Pyramid to help you generate URLs to those files, so you can |
| | | use Pyramid's internal fileserving while doing development, and a faster |
| | | static file server in production without changing any code. |
| | | |
| | | Example: :ref:`static_assets_section`. |
| | | |
| | | Debug Toolbar |
| | | ~~~~~~~~~~~~~ |
| | | |
| | | Pyramid's debug toolbar comes activated when you use a Pyramid scaffold to |
| | | render a project. This toolbar overlays your application in the browser, and |
| | | allows you access to framework data such as the routes configured, the last |
| | | renderings performed, the current set of packages installed, SQLAlchemy |
| | | queries run, logging data, and various other facts. When an exception |
| | | occurs, you can use its interactive debugger to poke around right in your |
| | | browser to try to determine the cause of the exception. It's handy. |
| | | |
| | | Example: :ref:`debug_toolbar`. |
| | | |
| | | Debugging settings |
| | | ~~~~~~~~~~~~~~~~~~ |
| | | |
| | | Pyramid has debugging settings that allow you to print Pyramid runtime |
| | | information to the console when things aren't behaving as you're expecting. |
| | | For example, you can turn on "debug_notfound", which prints an informative |
| | | message to the console every time a URL does not match any view. You can |
| | | turn on "debug_authorization", which lets you know why a view execution was |
| | | allowed or denied by printing a message to the console. These features are |
| | | useful for those WTF moments. |
| | | |
| | | There are also a number of ``paster`` commands that allow you to introspect |
| | | the configuration of your system: ``paster proutes`` shows all configured |
| | | routes for an application in the order they'll be evaluated for matching; |
| | | ``paster pviews`` shows all configured views for any given URL. These are |
| | | also WTF-crushers in some circumstances. |
| | | |
| | | Example: :ref:`debug_authorization_section` and :ref:`command_line_chapter`. |
| | | |
| | | Class-Based and Function-Based Views |
| | | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| | | |
| | | Pyramid has a structured, unified conception of views. Views can be |
| | | functions, methods of classes, or even instances. When you add a new view, |
| | | you can choose to make it a function or a method of a class; in either case, |
| | | Pyramid treats it largely the same way. You can change your mind later, and |
| | | move code between methods of classes and functions. A collection of similar |
| | | view callables can be attached to a single class as methods, if that floats |
| | | your boat, and they can share initialization code as necessary. All kinds of |
| | | views are easy to understand and use and operate similarly. There is no |
| | | phony distinction between them; they can be used for the same purposes. |
| | | |
| | | Example: :ref:`view_config_placement`. |
| | | |
| | | Event system |
| | | ~~~~~~~~~~~~ |
| | | |
| | | Pyramid emits *events* during its request processing lifecycle. You can |
| | | subscribe any number of listeners to these events. For example, to be |
| | | notified of a new request, you can subscribe to the ``NewRequest`` event. To |
| | | be notified that a template is about to be rendered, you can subscribe to the |
| | | ``BeforeRender`` event, and so forth. Using an event publishing system as a |
| | | framework notification feature instead of hardcoded hook points tends to make |
| | | systems based on that framework less brittle. You can also use Pyramid's |
| | | event system to send your *own* events. For example, if you'd like to create |
| | | a system that is itself a framework, and may want to notify subscribers that |
| | | a document has just been indexed, you can create your own event type |
| | | (``DocumentIndexed`` perhaps) and send the event via Pyramid. Users of this |
| | | framework can then subscribe to your event like they'd subscribe to the |
| | | events that are normally sent by Pyramid itself. |
| | | |
| | | Example: :ref:`events_chapter` and :ref:`event_types`. |
| | | |
| | | Extensible templating |
| | | ~~~~~~~~~~~~~~~~~~~~~ |
| | | |
| | | Pyramid has a structured API that allows for pluggability of "renderers". |
| | | Templating systems such as Mako, Genshi, Chameleon, and Jinja2 can be treated |
| | | as renderers. Renderer bindings for all of these templating systems already |
| | | exist for use in Pyramid. But if you'd rather use another, it's not a big |
| | | deal. Just copy the code from an existing renderer package, and plug in your |
| | | own. You'll then be able to use your templating system from within Pyramid |
| | | just as you'd use one of the "built-in" templating systems. |
| | | |
| | | Example: :ref:`templates_used_directly`. |
| | | |
| | | Speed |
| | | ~~~~~ |
| | | |
| | | The Pyramid core is, as far as we can tell, at least marginally faster than |
| | | any other existing Python web framework. It has been engineered from the |
| | | ground up for speed. It only does as much work as absolutely necessary when |
| | | you ask it to get a job done. Extraneous function calls and suboptimal |
| | | algorithms in its core codepaths are avoided religiously. It is feasible to |
| | | get, for example, between 3500 and 4000 requests per second from a simple |
| | | Pyramid view on commodity dual-core laptop hardware and an appropriate WSGI |
| | | server (mod_wsgi or gunicorn). In any case, performance statstics are |
| | | largely useless without requirements and goals, but if you need speed, |
| | | Pyramid will almost certainly never be your application's bottleneck; at |
| | | least no more than Python will be a bottleneck. |
| | | |
| | | Example: http://blog.curiasolutions.com/the-great-web-framework-shootout/ |
| | | |
| | | Sessions |
| | | ~~~~~~~~ |
| | | |
| | | Pyramid has built-in HTTP sessioning. This allows you to associate data with |
| | | otherwise anonymous users between requests. Lots of systems do this. But |
| | | Pyramid also allows you to plug in your own sessioning system by creating |
| | | some code that adheres to a documented interface. Currently there is a |
| | | binding package for the Beaker sessioning system that does exactly this. But |
| | | if you have a specialized need (perhaps you want to store your session data |
| | | in MongoDB), you can. You can even switch between implementations without |
| | | changing your application code. |
| | | |
| | | Example: :ref:`sessions_chapter`. |
| | | |
| | | No singletons |
| | | ~~~~~~~~~~~~~ |
| | | |
| | | Pyramid is written in such a way that it has exactly zero "singleton" data |
| | | structures. Or, put another way, Pyramid constructs no "mutable globals". |
| | | Or put even a different way, an import of a Pyramid application needn't have |
| | | any "import time side effects". This is esoteric-sounding, but if you've |
| | | ever tried to cope with parameterizing a Django "settings.py" file for |
| | | multiple installations of the same application, or if you've ever needed to |
| | | monkey-patch some framework fixture so that it behaves properly for your use |
| | | case, or if you've ever wanted to deploy your system using an asynchronous |
| | | server, you'll end up appreciating this feature. It just won't be a problem. |
| | | You can even run multiple copies of a similar but not identically configured |
| | | Pyramid application within the same Python process. This is good for shared |
| | | hosting environments, where RAM is at a premium. |
| | | |
| | | View Predicates and Many Views Per Route |
| | | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| | | |
| | | Unlike many other systems, Pyramid allows you to associate more than one view |
| | | per route. For example, you can create a route with the pattern ``/items`` |
| | | and when the route is matched, you can shuffle off the request to one view if |
| | | the request method is GET, another view if the request method is POST, etc. |
| | | A system known as "view predicates" allows for this. Request method matching |
| | | is the very most basic thing you can do with a view predicate. You can also |
| | | associate views with other request parameters such as the elements in the |
| | | query string, the Accept header, whether the request is an XHR request or |
| | | not, and lots of other things. This feature allows you to keep your |
| | | individual views "clean"; they won't need much conditional logic, so they'll |
| | | be easier to test. |
| | | |
| | | Example: :ref:`view_configuration_parameters`. |
| | | |
| | | Exception views |
| | | ~~~~~~~~~~~~~~~ |
| | | |
| | | Exceptions happen. Rather than deal with exceptions that might present |
| | | themselves to a user in production in an ad-hoc way, Pyramid allows you to |
| | | register *exception views*. Exception views are like regular Pyramid views, |
| | | but they're only invoked when an exception "bubbles up" to Pyramid itself. |
| | | For example, you might register an exception view for the ``Exception`` |
| | | exception, which will catch *all* exceptions, and present a pretty "whoops, |
| | | this is embarrassing" page. Or you might choose to register an exception |
| | | view for only specific kinds of application-specific exceptions, such as an |
| | | exception that happens when a file is not found, or an exception that happens |
| | | when action cannot be performed because the user doesn't have permission to |
| | | do something. In the former case, you can show a pretty "Not Found" page; in |
| | | the latter case you might show a login form. |
| | | |
| | | Example: :ref:`exception_views`. |
| | | |
| | | Asset specifications |
| | | ~~~~~~~~~~~~~~~~~~~~ |
| | | |
| | | Asset specifications are strings that contain both a Python package name and |
| | | a file or directory name, e.g. ``MyPackage:static/index.html``. Use of these |
| | | specifications is omnipresent in Pyramid. You can refer to a template using |
| | | an asset specification, a translation directory, and other package-bound |
| | | static resources using one. This makes a system built on Pyramid extensible, |
| | | because you don't have to rely on globals ("the static directory") or lookup |
| | | schemes ("the ordered set of template directories") to address your files. |
| | | You can move files around as necessary, and include other packages that may |
| | | not share your system's templates or static files without encountering |
| | | conflicts. |
| | | |
| | | Because asset specifications are used heavily in Pyramid, we've also provided |
| | | a way to allow users to override assets. Say you love a system that someone |
| | | else has created with Pyramid but you just need to change "that one template" |
| | | to make it all better. No need to fork the application. Just override the |
| | | asset specification for that template with your own inside a wrapper, and |
| | | you're good to go. |
| | | |
| | | Example: :ref:`asset_specifications`. |
| | | |
| | | Transaction management |
| | | ~~~~~~~~~~~~~~~~~~~~~~ |
| | | |
| | | Pyramid's :term:`scaffold` system renders projects that include a |
| | | *transaction management* system, also stolen from Zope. When you use this |
| | | transaction management system, you cease being responsible for committing |
| | | your data anymore. Instead, Pyramid takes care of committing: it commits at |
| | | the end of a request or aborts if there's an exception. Why is that a good |
| | | thing? Transaction boundaries are awfully hard to get right. If you add a |
| | | ``session.commit`` call in your application logic, and your code goes on to |
| | | do other important things after that commit, and error happens in the later |
| | | code, sometimes, you're kind of screwed. Some data will have been written to |
| | | the database that probably should not have. Having a centralized commit |
| | | point saves you from needing to think about this. Also, Pyramid's |
| | | transaction management system allows you to synchronize commits between |
| | | multiple databases, and allows you to do things like conditionally send email |
| | | if a transaction commits, but otherwise keep quiet. |
| | | |
| | | Example: :ref:`bfg_sql_wiki_tutorial` (note the lack of commit statements |
| | | anywhere in application code). |
| | | |
| | | Configuration conflict detection |
| | | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| | | |
| | | When a system is small, it's reasonably easy to keep it in all in your head. |
| | | But when systems grow large, you may have hundreds or thousands of |
| | | configuration statements which add a view, add a route, and so forth. |
| | | Pyramid's configuration system keeps track of your configuration statements, |
| | | and if you accidentally add two that are identical, or Pyramid can't make |
| | | sense out of what it would mean to have both statements active at the same |
| | | time, it will complain loudly at startup time. It's not dumb though: it will |
| | | automatically resolve conflicting configuration statements on its own if you |
| | | use the configuration ``include`` system: "more local" statements are |
| | | preferred over "less local" ones. This allows you to intelligently factor |
| | | large systems into smaller ones. |
| | | |
| | | Example: :ref:`conflict_detection`. |
| | | |
| | | Configuration extensibility |
| | | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| | | |
| | | Unlike other systems, Pyramid provides a structured ``include`` mechanism |
| | | that allows you compose applications from multiple Python packages. All the |
| | | configuration statements that can be performed in your "main" Pyramid |
| | | application can also be performed by included packages (including the |
| | | addition of views, routes, subscribers, and even authentication and |
| | | authorization policies). You can even extend or override an existing |
| | | application by including another application's configuration in your own, and |
| | | overriding or adding new views and routes to it. This has the potential to |
| | | allow you to compose a big application out of many other smaller ones. For |
| | | example, if you want to reuse an existing application that already has a |
| | | bunch of routes, you can just use the ``include`` statement with a |
| | | ``route_prefix``; the new application will live within your application at a |
| | | URL prefix. It's not a big deal, and requires little up-front engineering |
| | | effort. |
| | | |
| | | Example: :ref:`building_an_extensible_app`. |
| | | |
| | | Flexible authentication and authorization |
| | | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| | | |
| | | Pyramid includes a flexible, pluggable authentication and authorization |
| | | system. No matter where your user data is stored, or what scheme you'd like |
| | | to use to permit your users to access your data, you can use a predefined |
| | | Pyramid plugpoint to plug in your custom authentication and authorization |
| | | code. If you want to change these schemes later, you can just change it in |
| | | one place rather than everywhere in your code. It also ships with prebuilt |
| | | well-tested authentication and authorization schemes out of the box. But |
| | | what if you don't want to use Pyramid's built-in system? You don't have to. |
| | | You can just write your own bespoke security code as you would in any other |
| | | system. |
| | | |
| | | Example: :ref:`enabling_authorization_policy`. |
| | | |
| | | Built-in Internationalization |
| | | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| | | |
| | | Pyramid ships with internalization-related features in its core: |
| | | localization, pluralization, and creating message catalogs from source files |
| | | and templates. Pyramid allows for a plurality of message catalog via the use |
| | | of translation domains: you can create a system that has its own translations |
| | | without conflict with other translations in other domains. |
| | | |
| | | Example: :ref:`i18n_chapter`. |
| | | |
| | | Traversal |
| | | ~~~~~~~~~ |
| | | |
| | | :term:`Traversal` is a concept stolen from :term:`Zope`. It allows you to |
| | | create a tree of resources, each of which can be addressed by one or more |
| | | URLs. Each of those resources can have one or more *views* associated with |
| | | it. Iif your data isn't naturally treelike (or you're unwilling to create a |
| | | treelike representation of your data), you aren't going to find traversal |
| | | very useful. However, traversal is absolutely fantastic for sites that need |
| | | to be arbitrarily extensible: it's a lot easier to add a node to a tree than |
| | | it is to shoehorn a route into an ordered list of other routes, or to create |
| | | another entire instance of an application to service a department and glue |
| | | code to allow disparate apps to share data. It's a great fit for sites that |
| | | naturally lend themselves to changing departmental hierarchies, such as CMS |
| | | systems and document management systems. Traversal also lends itself well to |
| | | systems that require very granular security ("Bob can edit *this* document" |
| | | as opposed to "Bob can edit documents"). |
| | | |
| | | Example: :ref:`much_ado_about_traversal_chapter`. |
| | | |
| | | HTTP Caching |
| | | ~~~~~~~~~~~~ |
| | | |
| | | Pyramid provides an easy way to associate views with HTTP caching policies. |
| | | You can just tell Pyramid to configure your view with an ``http_cache`` |
| | | statement, and it will take care of the rest:: |
| | | |
| | | @view_config(http_cache=3600) # 60 minutes |
| | | def myview(request): .... |
| | | |
| | | Pyramid will add appropriate ``Cache-Control`` and ``Expires`` headers to |
| | | responses generated when this view is invoked. |
| | | |
| | | See the :meth:`pyramid.config.Configurator.add_view` statement's |
| | | ``http_cache`` documentation for more information. |
| | | |
| | | Tweens |
| | | ~~~~~~ |
| | | |
| | | Pyramid has a sort of internal WSGI-middleware-ish pipeline that can be |
| | | hooked by arbitrary add-ons named "tweens". The debug toolbar is a "tween", |
| | | and the ``pyramid_tm`` transaction manager is also. Tweens are more useful |
| | | than WSGI middleware in some circumstances because they run in the context of |
| | | Pyramid itself, meaning you have access to templates and other renderers, a |
| | | "real" request object, and other niceties. |
| | | |
| | | Example: :ref:`registering_tweens`. |
| | | |
| | | Testing |
| | | ~~~~~~~ |
| | | |
| | | Every release of Pyramid has 100% statement coverage via unit and integration |
| | | tests, as measured by the ``coverage`` tool available on PyPI. It also has |
| | | greater than 95% decision/condition coverage as measured by the |
| | | ``instrumental`` tool available on PyPI. It is automatically tested by the |
| | | Jenkins tool on Python 2.5, Python 2.6, Python 2.7, Jython and PyPy after |
| | | each commit to its GitHub repository. Official Pyramid add-ons are held to a |
| | | similar testing standard. We still find bugs in Pyramid and its official |
| | | add-ons, but we find a lot fewer of them than do the owners of comparable |
| | | projects that don't test so exhaustively. |
| | | |
| | | Example: http://jenkins.pylonsproject.org/ |
| | | |
| | | Support |
| | | ~~~~~~~ |
| | | |
| | | It's our goal that no Pyramid question go unanswered. Whether you ask a |
| | | question on IRC, on the Pylons-discuss maillist, or on StackOverflow, you're |
| | | likely to get a reasonaly prompt response. We don't tolerate "tech trolls" |
| | | or other people who seem to get their rocks off by berating fellow users in |
| | | our various offical support channels. We try to keep it well-lit and |
| | | new-user-friendly. |
| | | |
| | | Example: Visit irc://freenode.net#pyramid (the ``#pyramid`` channel on |
| | | irc.freenode.net in an IRC client) or the pylons-discuss maillist at |
| | | http://groups.google.com/group/pylons-discuss/ . |
| | | |
| | | Documentation |
| | | ~~~~~~~~~~~~~ |
| | | |
| | | It's a constant struggle, but we try to maintain a balance between |
| | | completeness and new-user-friendliness in the official narrative Pyramid |
| | | documentation (concrete suggestions for improvement are always appreciated, |
| | | by the way). We also maintain a "cookbook" of recipes, which are usually |
| | | demonstrations of common integration scenarios, too specific to add to the |
| | | official narrative docs. In any case, the Pyramid documentation is |
| | | comprehensive. |
| | | |
| | | Example: The rest of this documentation. |
| | | |
| | | .. index:: |
| | | single: Pylons Project |
| | | |