| | |
| | | |
| | | As we saw in :ref:`firstapp_chapter`, it's possible to create a :app:`Pyramid` |
| | | application completely manually. However, it's usually more convenient to use |
| | | a :term:`scaffold` to generate a basic :app:`Pyramid` :term:`project`. |
| | | our :term:`cookiecutter` to generate a basic :app:`Pyramid` :term:`project`. |
| | | |
| | | A project is a directory that contains at least one Python :term:`package`. |
| | | You'll use a scaffold to create a project, and you'll create your application |
| | | logic within a package that lives inside the project. Even if your application |
| | | is extremely simple, it is useful to place code that drives the application |
| | | within a package, because (1) a package is more easily extended with new code, |
| | | and (2) an application that lives inside a package can also be distributed more |
| | | easily than one which does not live within a package. |
| | | You'll use the :app:`Pyramid` cookiecutter to create a project, and you'll |
| | | create your application logic within a package that lives inside the project. |
| | | Even if your application is extremely simple, it is useful to place code that |
| | | drives the application within a package, because (1) a package is more easily |
| | | extended with new code, and (2) an application that lives inside a package can |
| | | also be distributed more easily than one which does not live within a package. |
| | | |
| | | :app:`Pyramid` comes with a variety of scaffolds that you can use to generate a |
| | | project. Each scaffold makes different configuration assumptions about what |
| | | type of application you're trying to construct. |
| | | The Pylons Project provides a :app:`Pyramid` cookiecutter that you can use to |
| | | generate a project. Our cookiecutter allows several configuration options |
| | | to generate the type of application you're trying to construct. |
| | | |
| | | These scaffolds are rendered using the ``pcreate`` command that is installed as |
| | | part of Pyramid. |
| | | This cookiecutter is rendered using the ``cookiecutter`` command that you may install. |
| | | |
| | | .. seealso:: |
| | | |
| | | See also `Cookiecutter Installation <https://cookiecutter.readthedocs.io/en/latest/installation.html>`_. |
| | | |
| | | |
| | | .. index:: |
| | | single: scaffolds |
| | | single: starter scaffold |
| | | single: zodb scaffold |
| | | single: alchemy scaffold |
| | | single: cookiecutters |
| | | single: pyramid-cookiecutter-starter |
| | | |
| | | .. _additional_paster_scaffolds: |
| | | .. _additional_cookiecutters: |
| | | |
| | | Scaffolds Included with :app:`Pyramid` |
| | | -------------------------------------- |
| | | :app:`Pyramid` cookiecutters |
| | | ---------------------------- |
| | | |
| | | The convenience scaffolds included with :app:`Pyramid` differ from each other |
| | | on a number of axes: |
| | | The Pyramid cookiecutter released under the Pylons Project offers the following configuration options: |
| | | |
| | | - the persistence mechanism they offer (no persistence mechanism, :term:`ZODB`, |
| | | or :term:`SQLAlchemy`) |
| | | - templating libraries (:term:`Jinja2`, :term:`Chameleon`, or :term:`Mako`) |
| | | |
| | | - the mechanism they use to map URLs to code (:term:`traversal` or :term:`URL |
| | | dispatch`) |
| | | - the persistence mechanism (no persistence mechanism, :term:`SQLAlchemy` with SQLite, or :term:`ZODB`) |
| | | |
| | | The included scaffolds are these: |
| | | - the mechanism of mapping URLs to code (:term:`URL dispatch` or :term:`traversal`) |
| | | |
| | | ``starter`` |
| | | URL mapping via :term:`URL dispatch` and no persistence mechanism |
| | | * `pyramid-cookiecutter-starter <https://github.com/Pylons/pyramid-cookiecutter-starter>`_ |
| | | |
| | | All configuration options offer a choice of templating language. |
| | | |
| | | The configuration of mapping URLs to code (routing) depends on the backend option selected, with additional variations as follows. |
| | | |
| | | ``none`` |
| | | :term:`URL dispatch` for routing |
| | | |
| | | ``sqlalchemy`` |
| | | SQLite for persistent storage, :term:`SQLAlchemy` for an ORM, :term:`URL dispatch` for routing, and :term:`Alembic` for database migrations |
| | | |
| | | ``zodb`` |
| | | URL mapping via :term:`traversal` and persistence via :term:`ZODB` |
| | | |
| | | ``alchemy`` |
| | | URL mapping via :term:`URL dispatch` and persistence via :term:`SQLAlchemy` |
| | | :term:`ZODB` for persistent storage and :term:`traversal` for routing |
| | | |
| | | |
| | | .. index:: |
| | | single: creating a project |
| | | single: project |
| | | single: pcreate |
| | | single: cookiecutter |
| | | |
| | | .. _creating_a_project: |
| | | |
| | | Creating the Project |
| | | -------------------- |
| | | |
| | | .. seealso:: See also the output of :ref:`pcreate --help <pcreate_script>`. |
| | | |
| | | In :ref:`installing_chapter`, you created a virtual Python environment via the |
| | | ``venv`` command. To start a :app:`Pyramid` :term:`project`, use the |
| | | ``pcreate`` command installed within the virtual environment. We'll choose the |
| | | ``starter`` scaffold for this purpose. When we invoke ``pcreate``, it will |
| | | create a directory that represents our project. |
| | | ``venv`` command. We called the virtual environment directory |
| | | ``env`` and set an environment variable ``VENV`` to its path. |
| | | |
| | | In :ref:`installing_chapter` we called the virtual environment directory |
| | | ``env``. The following commands assume that our current working directory is |
| | | the ``env`` directory. |
| | | We assume that you :ref:`previously installed cookiecutter <cookiecutters>`, following its installation instructions. |
| | | |
| | | The below example uses the ``pcreate`` command to create a project with the |
| | | ``starter`` scaffold. |
| | | When we invoke ``cookiecutter``, it will create a directory that represents our project. |
| | | |
| | | On UNIX: |
| | | We assume our current working directory is the value of ``VENV``. |
| | | |
| | | On all platforms, generate a project using cookiecutter. |
| | | |
| | | .. code-block:: bash |
| | | |
| | | $ $VENV/bin/pcreate -s starter MyProject |
| | | cookiecutter gh:Pylons/pyramid-cookiecutter-starter --checkout 1.10-branch |
| | | |
| | | Or on Windows: |
| | | If prompted for the first item, accept the default ``yes`` by hitting return. |
| | | |
| | | .. code-block:: text |
| | | |
| | | > %VENV%\Scripts\pcreate -s starter MyProject |
| | | You've cloned ~/.cookiecutters/pyramid-cookiecutter-starter before. |
| | | Is it okay to delete and re-clone it? [yes]: yes |
| | | project_name [Pyramid Scaffold]: myproject |
| | | repo_name [myproject]: myproject |
| | | Select template_language: |
| | | 1 - jinja2 |
| | | 2 - chameleon |
| | | 3 - mako |
| | | Choose from 1, 2, 3 [1]: 1 |
| | | Select backend: |
| | | 1 - none |
| | | 2 - sqlalchemy |
| | | 3 - zodb |
| | | Choose from 1, 2, 3 [1]: 1 |
| | | |
| | | As a result of invoking the ``pcreate`` command, a directory named |
| | | ``MyProject`` is created. That directory is a :term:`project` directory. The |
| | | We then run through the following commands. |
| | | |
| | | On Unix: |
| | | |
| | | .. code-block:: bash |
| | | |
| | | # Reset our environment variable for a new virtual environment. |
| | | export VENV=~/env/myproject/env |
| | | # Change directory into your newly created project. |
| | | cd myproject |
| | | # Create a new virtual environment... |
| | | python3 -m venv $VENV |
| | | # ...where we upgrade packaging tools. |
| | | env/bin/pip install --upgrade pip setuptools |
| | | |
| | | Or on Windows: |
| | | |
| | | .. code-block:: doscon |
| | | |
| | | # Reset our environment variable for a new virtual environment. |
| | | set VENV=c:\env\myproject\env |
| | | # Change directory into your newly created project. |
| | | cd myproject |
| | | # Create a new virtual environment... |
| | | python -m venv %VENV% |
| | | # ...where we upgrade packaging tools. |
| | | %VENV%\Scripts\pip install --upgrade pip setuptools |
| | | |
| | | As a result of invoking the ``cookiecutter`` command, a directory named |
| | | ``myproject`` is created. That directory is a :term:`project` directory. The |
| | | ``setup.py`` file in that directory can be used to distribute your application, |
| | | or install your application for deployment or development. |
| | | |
| | |
| | | number of debugging settings. You can use this file to put your application |
| | | into production. |
| | | |
| | | The ``MyProject`` project directory contains an additional subdirectory named |
| | | The ``myproject`` project directory contains an additional subdirectory named |
| | | ``myproject`` (note the case difference) representing a Python :term:`package` |
| | | which holds very simple :app:`Pyramid` sample code. This is where you'll edit |
| | | your application's Python code and templates. |
| | | |
| | | We created this project within an ``env`` virtual environment directory. |
| | | We created this project in a directory next to its virtual environment directory. |
| | | However, note that this is not mandatory. The project directory can go more or |
| | | less anywhere on your filesystem. You don't need to put it in a special "web |
| | | server" directory, and you don't need to put it within a virtual environment |
| | | server" directory. You could put it within a virtual environment |
| | | directory. The author uses Linux mainly, and tends to put project directories |
| | | which he creates within his ``~/projects`` directory. On Windows, it's a good |
| | | idea to put project directories within a directory that contains no space |
| | |
| | | |
| | | .. warning:: |
| | | |
| | | You'll need to avoid using ``pcreate`` to create a project with the same |
| | | You'll need to avoid using ``cookiecutter`` to create a project with the same |
| | | name as a Python standard library component. In particular, this means you |
| | | should avoid using the names ``site`` or ``test``, both of which conflict |
| | | with Python standard library packages. You should also avoid using the name |
| | |
| | | invoke the command ``pip install -e .``, which installs the project in |
| | | development mode (``-e`` is for "editable") into the current directory (``.``). |
| | | |
| | | The file named ``setup.py`` will be in the root of the pcreate-generated |
| | | The file named ``setup.py`` will be in the root of the cookiecutter-generated |
| | | project directory. The ``python`` you're invoking should be the one that lives |
| | | in the ``bin`` (or ``Scripts`` on Windows) directory of your virtual Python |
| | | environment. Your terminal's current working directory *must* be the newly |
| | | created project directory. |
| | | |
| | | On UNIX: |
| | | On Unix: |
| | | |
| | | .. code-block:: bash |
| | | |
| | | $ cd MyProject |
| | | $ $VENV/bin/pip install -e . |
| | | $VENV/bin/pip install -e . |
| | | |
| | | Or on Windows: |
| | | |
| | | .. code-block:: doscon |
| | | |
| | | > cd MyProject |
| | | > %VENV%\Scripts\pip install -e . |
| | | %VENV%\Scripts\pip install -e . |
| | | |
| | | Elided output from a run of this command on UNIX is shown below: |
| | | Elided output from a run of this command on Unix is shown below: |
| | | |
| | | .. code-block:: bash |
| | | |
| | | $ cd MyProject |
| | | $ $VENV/bin/pip install -e . |
| | | ... |
| | | Successfully installed Chameleon-2.24 Mako-1.0.4 MyProject \ |
| | | pyramid-chameleon-0.3 pyramid-debugtoolbar-2.4.2 pyramid-mako-1.0.2 |
| | | Running setup.py develop for myproject |
| | | Successfully installed Jinja2-2.8 Mako-1.0.6 MarkupSafe-0.23 \ |
| | | PasteDeploy-1.5.2 Pygments-2.1.3 WebOb-1.7.0 myproject pyramid-1.7.3 \ |
| | | pyramid-debugtoolbar-3.0.5 pyramid-jinja2-2.7 pyramid-mako-1.0.2 \ |
| | | repoze.lru-0.6 translationstring-1.3 venusian-1.0 waitress-1.0.1 \ |
| | | zope.deprecation-4.2.0 zope.interface-4.3.3 |
| | | |
| | | This will install a :term:`distribution` representing your project into the |
| | | virtual environment interpreter's library set so it can be found by ``import`` |
| | |
| | | To run unit tests for your application, you must first install the testing |
| | | dependencies. |
| | | |
| | | On UNIX: |
| | | On Unix: |
| | | |
| | | .. code-block:: bash |
| | | |
| | | $ $VENV/bin/pip install -e ".[testing]" |
| | | $VENV/bin/pip install -e ".[testing]" |
| | | |
| | | On Windows: |
| | | |
| | | .. code-block:: doscon |
| | | |
| | | > %VENV%\Scripts\pip install -e ".[testing]" |
| | | %VENV%\Scripts\pip install -e ".[testing]" |
| | | |
| | | Once the testing requirements are installed, then you can run the tests using |
| | | the ``py.test`` command that was just installed in the ``bin`` directory of |
| | | the ``pytest`` command that was just installed in the ``bin`` directory of |
| | | your virtual environment. |
| | | |
| | | On UNIX: |
| | | On Unix: |
| | | |
| | | .. code-block:: bash |
| | | |
| | | $ $VENV/bin/py.test -q |
| | | $VENV/bin/pytest -q |
| | | |
| | | On Windows: |
| | | |
| | | .. code-block:: doscon |
| | | |
| | | > %VENV%\Scripts\py.test -q |
| | | %VENV%\Scripts\pytest -q |
| | | |
| | | Here's sample output from a test run on UNIX: |
| | | Here's sample output from a test run on Unix: |
| | | |
| | | .. code-block:: bash |
| | | |
| | | $ $VENV/bin/py.test -q |
| | | .. |
| | | 2 passed in 0.47 seconds |
| | | $VENV/bin/pytest -q |
| | | .. |
| | | 2 passed in 0.47 seconds |
| | | |
| | | The tests themselves are found in the ``tests.py`` module in your ``pcreate`` |
| | | generated project. Within a project generated by the ``starter`` scaffold, |
| | | only two sample tests exist. Previous command is identical to: |
| | | |
| | | .. code-block:: bash |
| | | |
| | | $ $VENV/bin/py.test myproject/tests.py -q |
| | | The tests themselves are found in the ``tests.py`` module in your ``cookiecutter``-generated project. Within a project generated by the ``pyramid-cookiecutter-starter`` cookiecutter, only two sample tests exist. |
| | | |
| | | .. note:: |
| | | |
| | | The ``-q`` option is passed to the ``py.test`` command to limit the output |
| | | The ``-q`` option is passed to the ``pytest`` command to limit the output |
| | | to a stream of dots. If you don't pass ``-q``, you'll see verbose test |
| | | result output (which normally isn't very useful). |
| | | |
| | | Alternatively, if you'd like to see test coverage, pass the ``--cov`` option |
| | | to ``py.test``: |
| | | to ``pytest``: |
| | | |
| | | .. code-block:: bash |
| | | |
| | | $ $VENV/bin/py.test -q --cov |
| | | $VENV/bin/pytest --cov -q |
| | | |
| | | Cookiecutters include configuration defaults for ``pytest`` and test coverage. |
| | | These configuration files are ``pytest.ini`` and ``.coveragerc``, located at |
| | | the root of your package. Without these defaults, we would need to specify the |
| | | path to the module on which we want to run tests and coverage. |
| | | |
| | | .. code-block:: bash |
| | | |
| | | $VENV/bin/pytest --cov=myproject myproject/tests.py -q |
| | | |
| | | .. seealso:: See ``pytest``'s documentation for :ref:`pytest:usage` or invoke |
| | | ``pytest -h`` to see its full set of options. |
| | | |
| | | |
| | | .. index:: |
| | |
| | | represents using the ``pserve`` command against the generated configuration |
| | | file. In our case, this file is named ``development.ini``. |
| | | |
| | | On UNIX: |
| | | On Unix: |
| | | |
| | | .. code-block:: bash |
| | | |
| | | $ $VENV/bin/pserve development.ini |
| | | $VENV/bin/pserve development.ini |
| | | |
| | | On Windows: |
| | | |
| | | .. code-block:: text |
| | | .. code-block:: doscon |
| | | |
| | | > %VENV%\Scripts\pserve development.ini |
| | | %VENV%\Scripts\pserve development.ini |
| | | |
| | | Here's sample output from a run of ``pserve`` on UNIX: |
| | | Here's sample output from a run of ``pserve`` on Unix: |
| | | |
| | | .. code-block:: bash |
| | | |
| | | $ $VENV/bin/pserve development.ini |
| | | Starting server in PID 16208. |
| | | serving on http://127.0.0.1:6543 |
| | | $VENV/bin/pserve development.ini |
| | | Starting server in PID 77171. |
| | | Serving on http://localhost:6543 |
| | | Serving on http://localhost:6543 |
| | | |
| | | Access is restricted such that only a browser running on the same machine as |
| | | Pyramid will be able to access your Pyramid application. However, if you want |
| | | to open access to other machines on the same network, then edit the |
| | | ``development.ini`` file, and replace the ``host`` value in the |
| | | ``[server:main]`` section, changing it from ``127.0.0.1`` to ``0.0.0.0``. For |
| | | example: |
| | | ``development.ini`` file, and replace the ``listen`` value in the |
| | | ``[server:main]`` section, changing it from ``localhost:6543`` to ``*:6543`` |
| | | (this is equivalent to ``0.0.0.0:6543 [::]:6543``). For example: |
| | | |
| | | .. code-block:: ini |
| | | |
| | | [server:main] |
| | | use = egg:waitress#main |
| | | host = 0.0.0.0 |
| | | port = 6543 |
| | | [server:main] |
| | | use = egg:waitress#main |
| | | listen = *:6543 |
| | | |
| | | Now when you use ``pserve`` to start the application, it will respond to |
| | | requests on *all* IP addresses possessed by your system, not just requests to |
| | |
| | | be able to access the application via ``http://127.0.0.1:6543/`` as well as via |
| | | ``http://192.168.1.50:6543/``. However, *other people* on other computers on |
| | | the same network will also be able to visit your Pyramid application in their |
| | | browser by visiting ``http://192.168.1.50:6543/``. |
| | | browser by visiting ``http://192.168.1.50:6543/``. The same holds true if you use |
| | | IPv6. ``[::]`` means the same as ``0.0.0.0`` but for IPv6 protocol. |
| | | |
| | | You can change the port on which the server runs on by changing the same |
| | | portion of the ``development.ini`` file. For example, you can change the |
| | | ``port = 6543`` line in the ``development.ini`` file's ``[server:main]`` |
| | | section to ``port = 8080`` to run the server on port 8080 instead of port 6543. |
| | | ``listen = localhost:6543`` line in the ``development.ini`` file's ``[server:main]`` |
| | | section to ``listen = localhost:8080`` to run the server on port 8080 instead of port 6543. |
| | | |
| | | You can shut down a server started this way by pressing ``Ctrl-C`` (or |
| | | ``Ctrl-Break`` on Windows). |
| | | |
| | | The default server used to run your Pyramid application when a project is |
| | | created from a scaffold is named :term:`Waitress`. This server is what prints |
| | | the ``serving on...`` line when you run ``pserve``. It's a good idea to use |
| | | created from a cookiecutter is named :term:`Waitress`. This server is what prints |
| | | the ``Serving on...`` line when you run ``pserve``. It's a good idea to use |
| | | this server during development because it's very simple. It can also be used |
| | | for light production. Setting your application up under a different server is |
| | | not advised until you've done some development work under the default server, |
| | |
| | | makes development easier, as changes to Python code made within a |
| | | :app:`Pyramid` application is not put into effect until the server restarts. |
| | | |
| | | For example, on UNIX: |
| | | For example, on Unix: |
| | | |
| | | .. code-block:: text |
| | | |
| | | $ $VENV/bin/pserve development.ini --reload |
| | | Starting subprocess with file monitor |
| | | Starting server in PID 16601. |
| | | serving on http://127.0.0.1:6543 |
| | | $VENV/bin/pserve development.ini --reload |
| | | Starting subprocess with file monitor |
| | | Starting server in PID 16601. |
| | | Serving on http://localhost:6543 |
| | | Serving on http://localhost:6543 |
| | | |
| | | Now if you make a change to any of your project's ``.py`` files or ``.ini`` |
| | | files, you'll see the server restart automatically: |
| | | |
| | | .. code-block:: text |
| | | |
| | | development.ini changed; reloading... |
| | | -------------------- Restarting -------------------- |
| | | Starting server in PID 16602. |
| | | serving on http://127.0.0.1:6543 |
| | | development.ini changed; reloading... |
| | | -------------------- Restarting -------------------- |
| | | Starting server in PID 16602. |
| | | Serving on http://localhost:6543 |
| | | Serving on http://localhost:6543 |
| | | |
| | | Changes to template files (such as ``.pt`` or ``.mak`` files) won't cause the |
| | | server to restart. Changes to template files don't require a server restart as |
| | | long as the ``pyramid.reload_templates`` setting in the ``development.ini`` |
| | | file is ``true``. Changes made to template files when this setting is true |
| | | file is ``true``. Changes made to template files when this setting is ``true`` |
| | | will take effect immediately without a server restart. |
| | | |
| | | .. index:: |
| | |
| | | |
| | | .. image:: project.png |
| | | |
| | | This is the page shown by default when you visit an unmodified ``pcreate`` |
| | | generated ``starter`` application in a browser. |
| | | This is the page shown by default when you visit an unmodified ``cookiecutter`` |
| | | generated ``pyramid-cookiecutter-starter`` application in a browser. |
| | | |
| | | .. index:: |
| | | single: debug toolbar |
| | |
| | | |
| | | .. code-block:: ini |
| | | |
| | | [app:main] |
| | | # .. other settings ... |
| | | debugtoolbar.hosts = 192.168.1.1 |
| | | [app:main] |
| | | # .. other settings ... |
| | | debugtoolbar.hosts = 192.168.1.1 |
| | | |
| | | For more information about what the debug toolbar allows you to do, see the |
| | | :ref:`documentation for pyramid_debugtoolbar <toolbar:overview>`. |
| | |
| | | commenting out a line. For example, instead of: |
| | | |
| | | .. code-block:: ini |
| | | :linenos: |
| | | :linenos: |
| | | |
| | | [app:main] |
| | | # ... elided configuration |
| | | pyramid.includes = |
| | | pyramid_debugtoolbar |
| | | [app:main] |
| | | # ... elided configuration |
| | | pyramid.includes = |
| | | pyramid_debugtoolbar |
| | | |
| | | Put a hash mark at the beginning of the ``pyramid_debugtoolbar`` line: |
| | | |
| | | .. code-block:: ini |
| | | :linenos: |
| | | :linenos: |
| | | |
| | | [app:main] |
| | | # ... elided configuration |
| | | pyramid.includes = |
| | | # pyramid_debugtoolbar |
| | | [app:main] |
| | | # ... elided configuration |
| | | pyramid.includes = |
| | | # pyramid_debugtoolbar |
| | | |
| | | Then restart the application to see that the toolbar has been turned off. |
| | | |
| | |
| | | |
| | | .. code-block:: text |
| | | |
| | | ImportError: No module named #pyramid_debugtoolbar |
| | | ImportError: No module named #pyramid_debugtoolbar |
| | | |
| | | .. index:: |
| | | single: project structure |
| | |
| | | The Project Structure |
| | | --------------------- |
| | | |
| | | The ``starter`` scaffold generated a :term:`project` (named ``MyProject``), |
| | | The ``pyramid-cookiecutter-starter`` cookiecutter generated a :term:`project` (named ``myproject``), |
| | | which contains a Python :term:`package`. The package is *also* named |
| | | ``myproject``, but it's lowercased; the scaffold generates a project which |
| | | contains a package that shares its name except for case. |
| | | ``myproject``; the cookiecutter generates a project which |
| | | contains a package that shares its name. |
| | | |
| | | All :app:`Pyramid` ``pcreate``-generated projects share a similar structure. |
| | | The ``MyProject`` project we've generated has the following directory structure: |
| | | All :app:`Pyramid` ``cookiecutter``-generated projects share a similar structure. |
| | | The ``myproject`` project we've generated has the following directory structure: |
| | | |
| | | .. code-block:: text |
| | | |
| | | MyProject/ |
| | | |-- CHANGES.txt |
| | | |-- development.ini |
| | | |-- MANIFEST.in |
| | | |-- myproject |
| | | | |-- __init__.py |
| | | | |-- static |
| | | | | |-- pyramid-16x16.png |
| | | | | |-- pyramid.png |
| | | | | |-- theme.css |
| | | | | `-- theme.min.css |
| | | | |-- templates |
| | | | | `-- mytemplate.pt |
| | | | |-- tests.py |
| | | | `-- views.py |
| | | |-- production.ini |
| | | |-- README.txt |
| | | `-- setup.py |
| | | myproject |
| | | ├── .coveragerc |
| | | ├── .gitignore |
| | | ├── CHANGES.txt |
| | | ├── MANIFEST.in |
| | | ├── myproject |
| | | │  ├── __init__.py |
| | | │  ├── routes.py |
| | | │  ├── static |
| | | │  │  ├── pyramid-16x16.png |
| | | │  │  ├── pyramid.png |
| | | │  │  └── theme.css |
| | | │  ├── templates |
| | | │  │  ├── 404.jinja2 |
| | | │  │  ├── layout.jinja2 |
| | | │  │  └── mytemplate.jinja2 |
| | | │  ├── tests.py |
| | | │  └── views |
| | | │  ├── __init__.py |
| | | │  ├── default.py |
| | | │  └── notfound.py |
| | | ├── README.txt |
| | | ├── development.ini |
| | | ├── production.ini |
| | | ├── pytest.ini |
| | | └── setup.py |
| | | |
| | | The ``MyProject`` :term:`Project` |
| | | |
| | | The ``myproject`` :term:`Project` |
| | | --------------------------------- |
| | | |
| | | The ``MyProject`` :term:`project` directory is the distribution and deployment |
| | | The ``myproject`` :term:`project` directory is the distribution and deployment |
| | | wrapper for your application. It contains both the ``myproject`` |
| | | :term:`package` representing your application as well as files used to |
| | | describe, run, and test your application. |
| | | |
| | | #. ``.coveragerc`` configures coverage when running tests. |
| | | |
| | | #. ``.gitignore`` tells git which files and directories to ignore from source code version control. |
| | | |
| | | #. ``CHANGES.txt`` describes the changes you've made to the application. It is |
| | | conventionally written in :term:`ReStructuredText` format. |
| | | conventionally written in :term:`reStructuredText` format. |
| | | |
| | | #. ``MANIFEST.in`` is a :term:`distutils` "manifest" file, naming which files |
| | | should be included in a source distribution of the package when ``python |
| | | setup.py sdist`` is run. |
| | | |
| | | #. ``README.txt`` describes the application in general. It is conventionally |
| | | written in :term:`ReStructuredText` format. |
| | | written in :term:`reStructuredText` format. |
| | | |
| | | #. ``development.ini`` is a :term:`PasteDeploy` configuration file that can be |
| | | used to execute your application during development. |
| | |
| | | #. ``production.ini`` is a :term:`PasteDeploy` configuration file that can be |
| | | used to execute your application in a production configuration. |
| | | |
| | | #. ``MANIFEST.in`` is a :term:`distutils` "manifest" file, naming which files |
| | | should be included in a source distribution of the package when ``python |
| | | setup.py sdist`` is run. |
| | | #. ``pytest.ini`` is a configuration file for running tests. |
| | | |
| | | #. ``setup.py`` is the file you'll use to test and distribute your application. |
| | | It is a standard :term:`setuptools` ``setup.py`` file. |
| | | It is a standard :term:`Setuptools` ``setup.py`` file. |
| | | |
| | | .. index:: |
| | | single: PasteDeploy |
| | | single: ini file |
| | | |
| | | .. _MyProject_ini: |
| | | .. _myproject_ini: |
| | | |
| | | ``development.ini`` |
| | | ~~~~~~~~~~~~~~~~~~~ |
| | |
| | | |
| | | The generated ``development.ini`` file looks like so: |
| | | |
| | | .. literalinclude:: MyProject/development.ini |
| | | .. literalinclude:: myproject/development.ini |
| | | :language: ini |
| | | :linenos: |
| | | |
| | |
| | | |
| | | The ``[app:main]`` section represents configuration for your :app:`Pyramid` |
| | | application. The ``use`` setting is the only setting required to be present in |
| | | the ``[app:main]`` section. Its default value, ``egg:MyProject``, indicates |
| | | that our MyProject project contains the application that should be served. |
| | | the ``[app:main]`` section. Its default value, ``egg:myproject``, indicates |
| | | that our myproject project contains the application that should be served. |
| | | Other settings added to this section are passed as keyword arguments to the |
| | | function named ``main`` in our package's ``__init__.py`` module. You can |
| | | provide startup-time configuration parameters to your application by adding |
| | | more settings to this section. |
| | | |
| | | .. seealso:: See :ref:`pastedeploy_entry_points` for more information about the |
| | | meaning of the ``use = egg:MyProject`` value in this section. |
| | | meaning of the ``use = egg:myproject`` value in this section. |
| | | |
| | | The ``pyramid.reload_templates`` setting in the ``[app:main]`` section is a |
| | | :app:`Pyramid`-specific setting which is passed into the framework. If it |
| | |
| | | server which listens on TCP port 6543. It is configured to listen on localhost |
| | | only (``127.0.0.1``). |
| | | |
| | | .. _MyProject_ini_logging: |
| | | .. _myproject_ini_logging: |
| | | |
| | | The sections after ``# logging configuration`` represent Python's standard |
| | | library :mod:`logging` module configuration for your application. These |
| | |
| | | code into a version control repository, ``setup.py sdist`` places only *Python |
| | | source files* (files ending with a ``.py`` extension) into tarballs generated |
| | | by ``python setup.py sdist``. This means, for example, if your project was not |
| | | checked into a setuptools-compatible source control system, and your project |
| | | checked into a Setuptools-compatible source control system, and your project |
| | | directory didn't contain a ``MANIFEST.in`` file that told the ``sdist`` |
| | | machinery to include ``*.pt`` files, the ``myproject/templates/mytemplate.pt`` |
| | | file would not be included in the generated tarball. |
| | | |
| | | Projects generated by Pyramid scaffolds include a default ``MANIFEST.in`` file. |
| | | Projects generated by Pyramid cookiecutters include a default ``MANIFEST.in`` file. |
| | | The ``MANIFEST.in`` file contains declarations which tell it to include files |
| | | like ``*.pt``, ``*.css`` and ``*.js`` in the generated tarball. If you include |
| | | files with extensions other than the files named in the project's |
| | | ``MANIFEST.in`` and you don't make use of a setuptools-compatible version |
| | | ``MANIFEST.in`` and you don't make use of a Setuptools-compatible version |
| | | control system, you'll need to edit the ``MANIFEST.in`` file and include the |
| | | statements necessary to include your new files. See |
| | | https://docs.python.org/2/distutils/sourcedist.html#principle for more |
| | | information about how to do this. |
| | | |
| | | You can also delete ``MANIFEST.in`` from your project and rely on a setuptools |
| | | You can also delete ``MANIFEST.in`` from your project and rely on a :term:`Setuptools` |
| | | feature which simply causes all files checked into a version control system to |
| | | be put into the generated tarball. To allow this to happen, check all the |
| | | files that you'd like to be distributed along with your application's Python |
| | | files into Subversion. After you do this, when you rerun ``setup.py sdist``, |
| | | all files checked into the version control system will be included in the |
| | | tarball. If you don't use Subversion, and instead use a different version |
| | | control system, you may need to install a setuptools add-on such as |
| | | control system, you may need to install a :term:`Setuptools` add-on such as |
| | | ``setuptools-git`` or ``setuptools-hg`` for this behavior to work properly. |
| | | |
| | | .. index:: |
| | |
| | | ``setup.py`` |
| | | ~~~~~~~~~~~~ |
| | | |
| | | The ``setup.py`` file is a :term:`setuptools` setup file. It is meant to be |
| | | The ``setup.py`` file is a :term:`Setuptools` setup file. It is meant to be |
| | | used to define requirements for installing dependencies for your package and |
| | | testing, as well as distributing your application. |
| | | |
| | |
| | | ``setup.py`` is the de facto standard which Python developers use to |
| | | distribute their reusable code. You can read more about ``setup.py`` files |
| | | and their usage in the `Python Packaging User Guide |
| | | <https://packaging.python.org/en/latest/>`_ and `Setuptools documentation |
| | | <http://pythonhosted.org/setuptools/>`_. |
| | | <https://packaging.python.org/>`_ and `Setuptools documentation |
| | | <https://setuptools.readthedocs.io/en/latest/>`_. |
| | | |
| | | Our generated ``setup.py`` looks like this: |
| | | |
| | | .. literalinclude:: MyProject/setup.py |
| | | .. literalinclude:: myproject/setup.py |
| | | :language: python |
| | | :linenos: |
| | | |
| | | The ``setup.py`` file calls the setuptools ``setup`` function, which does |
| | | The ``setup.py`` file calls the :term:`Setuptools` ``setup`` function, which does |
| | | various things depending on the arguments passed to ``pip`` on the command |
| | | line. |
| | | |
| | | Within the arguments to this function call, information about your application |
| | | is kept. While it's beyond the scope of this documentation to explain |
| | | everything about setuptools setup files, we'll provide a whirlwind tour of what |
| | | everything about :term:`Setuptools` setup files, we'll provide a whirlwind tour of what |
| | | exists in this file in this section. |
| | | |
| | | Your application's name can be any string; it is specified in the ``name`` |
| | |
| | | description is provided in the ``description`` field. The ``long_description`` |
| | | is conventionally the content of the ``README`` and ``CHANGES`` files appended |
| | | together. The ``classifiers`` field is a list of `Trove classifiers |
| | | <https://pypi.python.org/pypi?%3Aaction=list_classifiers>`_ describing your |
| | | <https://pypi.org/pypi?%3Aaction=list_classifiers>`_ describing your |
| | | application. ``author`` and ``author_email`` are text fields which probably |
| | | don't need any description. ``url`` is a field that should point at your |
| | | application project's URL (if any). ``packages=find_packages()`` causes all |
| | |
| | | |
| | | .. code-block:: text |
| | | |
| | | $ $VENV/bin/python setup.py sdist |
| | | $VENV/bin/python setup.py sdist |
| | | |
| | | This will create a tarball of your application in a ``dist`` subdirectory named |
| | | ``MyProject-0.0.tar.gz``. You can send this tarball to other people who want |
| | | ``myproject-0.0.tar.gz``. You can send this tarball to other people who want |
| | | to install and use your application. |
| | | |
| | | .. index:: |
| | |
| | | The ``myproject`` :term:`Package` |
| | | --------------------------------- |
| | | |
| | | The ``myproject`` :term:`package` lives inside the ``MyProject`` |
| | | The ``myproject`` :term:`package` lives inside the ``myproject`` |
| | | :term:`project`. It contains: |
| | | |
| | | #. An ``__init__.py`` file signifies that this is a Python :term:`package`. It |
| | |
| | | ``main`` function which is used as a entry point for commands such as |
| | | ``pserve``, ``pshell``, ``pviews``, and others. |
| | | |
| | | #. A ``templates`` directory, which contains :term:`Chameleon` (or other types |
| | | #. A ``templates`` directory, which contains :term:`Jinja2` (or other types |
| | | of) templates. |
| | | |
| | | #. A ``tests.py`` module, which contains unit test code for the application. |
| | | |
| | | #. A ``views.py`` module, which contains view code for the application. |
| | | #. A ``routes.py`` module, which contains routing code for the application. |
| | | |
| | | These are purely conventions established by the scaffold. :app:`Pyramid` |
| | | #. A ``views`` package, which contains view code for the application. |
| | | |
| | | #. A ``static`` directory, which contains static files, including images and CSS. |
| | | |
| | | These are purely conventions established by the cookiecutter. :app:`Pyramid` |
| | | doesn't insist that you name things in any particular way. However, it's |
| | | generally a good idea to follow Pyramid standards for naming, so that other |
| | | Pyramid developers can get up to speed quickly on your code when you need help. |
| | |
| | | This is the file named ``__init__.py``. The presence of an ``__init__.py`` |
| | | also informs Python that the directory which contains it is a *package*. |
| | | |
| | | .. literalinclude:: MyProject/myproject/__init__.py |
| | | .. literalinclude:: myproject/myproject/__init__.py |
| | | :language: python |
| | | :linenos: |
| | | |
| | |
| | | |
| | | Within this function, application configuration is performed. |
| | | |
| | | Line 7 creates an instance of a :term:`Configurator`. |
| | | Line 7 opens a context manager with an instance of a :term:`Configurator`. |
| | | |
| | | Line 8 adds support for Chameleon templating bindings, allowing us to |
| | | specify renderers with the ``.pt`` extension. |
| | | Line 8 adds support for Jinja2 templating bindings, allowing us to |
| | | specify renderers with the ``.jinja2`` extension. |
| | | |
| | | Line 9 registers a static view, which will serve up the files from the |
| | | ``myproject:static`` :term:`asset specification` (the ``static`` directory |
| | | of the ``myproject`` package). |
| | | Line 9 includes the ``routes.py`` module. |
| | | |
| | | Line 10 adds a :term:`route` to the configuration. This route is later used |
| | | by a view in the ``views`` module. |
| | | |
| | | Line 11 calls ``config.scan()``, which picks up view registrations declared |
| | | Line 10 calls ``config.scan()``, which picks up view registrations declared |
| | | elsewhere in the package (in this case, in the ``views.py`` module). |
| | | |
| | | Line 12 returns a :term:`WSGI` application to the caller of the function |
| | | Line 11 returns a :term:`WSGI` application to the caller of the function |
| | | (Pyramid's pserve). |
| | | |
| | | |
| | | .. index:: |
| | | single: routes.py |
| | | |
| | | .. _routes_py: |
| | | |
| | | ``routes.py`` |
| | | ~~~~~~~~~~~~~ |
| | | |
| | | The ``routes.py`` module gets included by the ``main`` function in our ``__init__.py``. |
| | | It registers a view and a route. |
| | | |
| | | .. literalinclude:: myproject/myproject/routes.py |
| | | :language: python |
| | | :linenos: |
| | | |
| | | Line 2 registers a static view, which will serve up the files from the ``myproject:static`` :term:`asset specification` (the ``static`` directory of the ``myproject`` package). |
| | | |
| | | Line 3 adds a :term:`route` to the configuration. This route is later used by a view in the ``views`` module. |
| | | |
| | | |
| | | .. index:: |
| | | single: views.py |
| | | |
| | | ``views.py`` |
| | | ~~~~~~~~~~~~ |
| | | ``views`` package |
| | | ~~~~~~~~~~~~~~~~~ |
| | | |
| | | Much of the heavy lifting in a :app:`Pyramid` application is done by *view |
| | | callables*. A :term:`view callable` is the main tool of a :app:`Pyramid` web |
| | | application developer; it is a bit of code which accepts a :term:`request` and |
| | | which returns a :term:`response`. |
| | | |
| | | .. literalinclude:: MyProject/myproject/views.py |
| | | Our project has a ``views`` package by virtue of it being a directory containing an ``__init__.py`` file. |
| | | This ``__init__.py`` file happens to have no content, although it could as a project develops. |
| | | |
| | | We have two view modules in the ``views`` package. |
| | | Let's look at ``default.py``. |
| | | |
| | | .. literalinclude:: myproject/myproject/views/default.py |
| | | :language: python |
| | | :linenos: |
| | | |
| | |
| | | function named ``my_view`` is decorated with a ``view_config`` decorator (which |
| | | is processed by the ``config.scan()`` line in our ``__init__.py``). The |
| | | view_config decorator asserts that this view be found when a :term:`route` |
| | | named ``home`` is matched. In our case, because our ``__init__.py`` maps the |
| | | named ``home`` is matched. In our case, because our ``routes.py`` maps the |
| | | route named ``home`` to the URL pattern ``/``, this route will match when a |
| | | visitor visits the root URL. The view_config decorator also names a |
| | | ``renderer``, which in this case is a template that will be used to render the |
| | | result of the view callable. This particular view declaration points at |
| | | ``templates/mytemplate.pt``, which is an :term:`asset specification` that |
| | | specifies the ``mytemplate.pt`` file within the ``templates`` directory of the |
| | | ``../templates/mytemplate.jinja2``, which is an :term:`asset specification` that |
| | | specifies the ``mytemplate.jinja2`` file within the ``templates`` directory of the |
| | | ``myproject`` package. The asset specification could have also been specified |
| | | as ``myproject:templates/mytemplate.pt``; the leading package name and colon is |
| | | optional. The template file pointed to is a :term:`Chameleon` ZPT template |
| | | file (``templates/my_template.pt``). |
| | | as ``myproject:templates/mytemplate.jinja2``; the leading package name and colon is |
| | | optional. The template file pointed to is a :term:`Jinja2` template |
| | | file (``templates/mytemplate.jinja2``). |
| | | |
| | | This view callable function is handed a single piece of information: the |
| | | :term:`request`. The *request* is an instance of the :term:`WebOb` ``Request`` |
| | |
| | | |
| | | .. note:: Dictionaries provide values to :term:`template`\s. |
| | | |
| | | .. note:: When the application is run with the scaffold's :ref:`default |
| | | development.ini <MyProject_ini>` configuration, :ref:`logging is set up |
| | | <MyProject_ini_logging>` to aid debugging. If an exception is raised, |
| | | Now let's look at ``notfound.py``. |
| | | |
| | | .. literalinclude:: myproject/myproject/views/notfound.py |
| | | :language: python |
| | | :linenos: |
| | | |
| | | This file is similar to ``default.py``. |
| | | It merely returns a ``404`` response status and an empty dictionary to the template at ``../templates/404.jinja2``. |
| | | |
| | | .. note:: When the application is run with the cookiecutter's :ref:`default |
| | | development.ini <myproject_ini>` configuration, :ref:`logging is set up |
| | | <myproject_ini_logging>` to aid debugging. If an exception is raised, |
| | | uncaught tracebacks are displayed after the startup messages on :ref:`the |
| | | console running the server <running_the_project_application>`. Also |
| | | ``print()`` statements may be inserted into the application for debugging to |
| | |
| | | .. note:: ``development.ini`` has a setting that controls how templates are |
| | | reloaded, ``pyramid.reload_templates``. |
| | | |
| | | - When set to ``True`` (as in the scaffold ``development.ini``), changed |
| | | - When set to ``True`` (as in the cookiecutter ``development.ini``), changed |
| | | templates automatically reload without a server restart. This is |
| | | convenient while developing, but slows template rendering speed. |
| | | |
| | |
| | | ``static`` |
| | | ~~~~~~~~~~ |
| | | |
| | | This directory contains static assets which support the ``mytemplate.pt`` |
| | | This directory contains static assets which support the ``layout.jinja2`` |
| | | template. It includes CSS and images. |
| | | |
| | | ``templates/mytemplate.pt`` |
| | | |
| | | ``templates/layout.jinja2`` |
| | | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| | | |
| | | This is the single :term:`Chameleon` template that exists in the project. Its |
| | | contents are too long to show here, but it displays a default page when |
| | | rendered. It is referenced by the call to ``@view_config`` as the ``renderer`` |
| | | of the ``my_view`` view callable in the ``views.py`` file. See |
| | | :ref:`views_which_use_a_renderer` for more information about renderers. |
| | | This is the base layout content. It contains a single marker for content block. Other templates inherit its content, providing layout for the web application. Its contents are too long to show here, but here is an excerpt: |
| | | |
| | | .. literalinclude:: myproject/myproject/templates/layout.jinja2 |
| | | :language: jinja |
| | | :lines: 34-38 |
| | | :lineno-match: |
| | | |
| | | |
| | | ``templates/mytemplate.jinja2`` |
| | | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| | | |
| | | This is the content :term:`Jinja2` template that exists in the project. It is referenced by the call to ``@view_config`` as the ``renderer`` |
| | | of the ``my_view`` view callable in the ``views/default.py`` file. See |
| | | :ref:`views_which_use_a_renderer` for more information about renderers. It inherits ("extends") the HTML provided by ``layout.jinja2``, replacing the content block with its own content. |
| | | |
| | | .. literalinclude:: myproject/myproject/templates/mytemplate.jinja2 |
| | | :language: jinja |
| | | :linenos: |
| | | |
| | | Templates are accessed and used by view configurations and sometimes by view |
| | | functions themselves. See :ref:`templates_used_directly` and |
| | | :ref:`templates_used_as_renderers`. |
| | | |
| | | |
| | | ``templates/404.jinja2`` |
| | | ~~~~~~~~~~~~~~~~~~~~~~~~ |
| | | |
| | | This template is similar to ``mytemplate.jinja2``, but with a few differences. |
| | | It is referenced by the call to ``@notfound_view_config`` as the ``renderer`` of the ``notfound_view`` view callable in the ``views/notfound.py`` file. |
| | | It inherits the HTML provided by ``layout.jinja2``, replacing the content block with its own content. |
| | | |
| | | .. literalinclude:: myproject/myproject/templates/404.jinja2 |
| | | :language: jinja |
| | | :linenos: |
| | | |
| | | |
| | | .. index:: |
| | | single: tests.py |
| | |
| | | ``tests.py`` |
| | | ~~~~~~~~~~~~ |
| | | |
| | | The ``tests.py`` module includes unit tests for your application. |
| | | The ``tests.py`` module includes tests for your application. |
| | | |
| | | .. literalinclude:: MyProject/myproject/tests.py |
| | | .. literalinclude:: myproject/myproject/tests.py |
| | | :language: python |
| | | :linenos: |
| | | |
| | | This sample ``tests.py`` file has one unit test and one functional test defined |
| | | within it. These tests are executed when you run ``py.test myproject/tests.py |
| | | -q``. You may add more tests here as you build your application. You are not |
| | | required to write tests to use :app:`Pyramid`. This file is simply provided for |
| | | convenience and example. |
| | | within it. These tests are executed when you run ``pytest -q``. You may add |
| | | more tests here as you build your application. You are not required to write |
| | | tests to use :app:`Pyramid`. This file is simply provided for convenience and |
| | | example. |
| | | |
| | | See :ref:`testing_chapter` for more information about writing :app:`Pyramid` |
| | | unit tests. |
| | |
| | | --------------------------- |
| | | |
| | | It is best practice for your application's code layout to not stray too much |
| | | from accepted Pyramid scaffold defaults. If you refrain from changing things |
| | | from accepted Pyramid cookiecutter defaults. If you refrain from changing things |
| | | very much, other Pyramid coders will be able to more quickly understand your |
| | | application. However, the code layout choices made for you by a scaffold are |
| | | application. However, the code layout choices made for you by a cookiecutter are |
| | | in no way magical or required. Despite the choices made for you by any |
| | | scaffold, you can decide to lay your code out any way you see fit. |
| | | cookiecutter, you can decide to lay your code out any way you see fit. |
| | | |
| | | For example, the configuration method named |
| | | :meth:`~pyramid.config.Configurator.add_view` requires you to pass a |
| | | :term:`dotted Python name` or a direct object reference as the class or |
| | | function to be used as a view. By default, the ``starter`` scaffold would have |
| | | you add view functions to the ``views.py`` module in your package. However, you |
| | | might be more comfortable creating a ``views`` *directory*, and adding a single |
| | | file for each view. |
| | | function to be used as a view. |
| | | By default, the ``starter`` cookiecutter would have you create a ``views`` directory, and add a single file for each view or collection of related views. |
| | | However, you might be more comfortable creating a single ``views.py`` module in your package and add view functions to it. |
| | | |
| | | If your project package name was ``myproject`` and you wanted to arrange all |
| | | your views in a Python subpackage within the ``myproject`` :term:`package` |
| | | named ``views`` instead of within a single ``views.py`` file, you might do the |
| | | following. |
| | | |
| | | - Create a ``views`` directory inside your ``myproject`` package directory (the |
| | | same directory which holds ``views.py``). |
| | | |
| | | - Create a file within the new ``views`` directory named ``__init__.py``. (It |
| | | can be empty. This just tells Python that the ``views`` directory is a |
| | | *package*.) |
| | | |
| | | - *Move* the content from the existing ``views.py`` file to a file inside the |
| | | new ``views`` directory named, say, ``blog.py``. Because the ``templates`` |
| | | directory remains in the ``myproject`` package, the template :term:`asset |
| | | specification` values in ``blog.py`` must now be fully qualified with the |
| | | project's package name (``myproject:templates/blog.pt``). |
| | | |
| | | You can then continue to add view callable functions to the ``blog.py`` module, |
| | | but you can also add other ``.py`` files which contain view callable functions |
| | | to the ``views`` directory. As long as you use the ``@view_config`` directive |
| | | Whatever structure you prefer, as long as you use the ``@view_config`` directive |
| | | to register views in conjunction with ``config.scan()``, they will be picked up |
| | | automatically when the application is restarted. |
| | | |
| | |
| | | What Is This ``pserve`` Thing |
| | | ----------------------------- |
| | | |
| | | The code generated by a :app:`Pyramid` scaffold assumes that you will be using |
| | | The code generated by a :app:`Pyramid` cookiecutter assumes that you will be using |
| | | the ``pserve`` command to start your application while you do development. |
| | | ``pserve`` is a command that reads a :term:`PasteDeploy` ``.ini`` file (e.g., |
| | | ``development.ini``), and configures a server to serve a :app:`Pyramid` |
| | |
| | | application. As we saw in :ref:`firstapp_chapter`, ``pserve`` needn't be |
| | | invoked at all to run a :app:`Pyramid` application. The use of ``pserve`` to |
| | | run a :app:`Pyramid` application is purely conventional based on the output of |
| | | its scaffolding. But we strongly recommend using ``pserve`` while developing |
| | | its cookiecutter. But we strongly recommend using ``pserve`` while developing |
| | | your application because many other convenience introspection commands (such as |
| | | ``pviews``, ``prequest``, ``proutes``, and others) are also implemented in |
| | | terms of configuration availability of this ``.ini`` file format. It also |
| | |
| | | Using an Alternate WSGI Server |
| | | ------------------------------ |
| | | |
| | | Pyramid scaffolds generate projects which use the :term:`Waitress` WSGI server. |
| | | Pyramid cookiecutters generate projects which use the :term:`Waitress` WSGI server. |
| | | Waitress is a server that is suited for development and light production |
| | | usage. It's not the fastest nor the most featureful WSGI server. Instead, its |
| | | main feature is that it works on all platforms that Pyramid needs to run on, |
| | |
| | | provide the best development experience. |
| | | |
| | | One popular production alternative to the default Waitress server is |
| | | :term:`mod_wsgi`. You can use mod_wsgi to serve your :app:`Pyramid` application |
| | | :term:`mod_wsgi`. You can use ``mod_wsgi`` to serve your :app:`Pyramid` application |
| | | using the Apache web server rather than any "pure-Python" server like Waitress. |
| | | It is fast and featureful. See :ref:`modwsgi_tutorial` for details. |
| | | |
| | | Another good production alternative is :term:`Green Unicorn` (aka |
| | | ``gunicorn``). It's faster than Waitress and slightly easier to configure than |
| | | mod_wsgi, although it depends, in its default configuration, on having a |
| | | ``mod_wsgi``, although it depends, in its default configuration, on having a |
| | | buffering HTTP proxy in front of it. It does not, as of this writing, work on |
| | | Windows. |
| | | |
| | | Automatically Reloading Your Code |
| | | --------------------------------- |
| | | |
| | | During development, it can be really useful to automatically have the |
| | | webserver restart when you make changes. ``pserve`` has a ``--reload`` switch |
| | | to enable this. It uses the |
| | | `hupper <https://docs.pylonsproject.org/projects/hupper/en/latest/>`_ package |
| | | to enable this behavior. When your code crashes, ``hupper`` will wait for |
| | | another change or the ``SIGHUP`` signal before restarting again. |
| | | |
| | | inotify support |
| | | ~~~~~~~~~~~~~~~ |
| | | |
| | | By default ``hupper`` will poll the filesystem for changes to all Python |
| | | code. This can be pretty inefficient in larger projects. To be nicer to your |
| | | hard drive, you should install the |
| | | `watchdog <https://pythonhosted.org/watchdog/>`_ package in development. |
| | | ``hupper`` will automatically use ``watchdog`` to more efficiently poll the |
| | | filesystem. |
| | | |
| | | Monitoring Custom Files |
| | | ~~~~~~~~~~~~~~~~~~~~~~~ |
| | | |
| | | By default, ``pserve --reload`` will monitor all imported Python code |
| | | (everything in ``sys.modules``) as well as the config file passed to |
| | | ``pserve`` (e.g., ``development.ini``). You can instruct ``pserve`` to watch |
| | | other files for changes as well by defining a ``[pserve]`` section in your |
| | | configuration file. For example, let's say your application loads the |
| | | ``favicon.ico`` file at startup and stores it in memory to efficiently |
| | | serve it many times. When you change it, you want ``pserve`` to restart: |
| | | |
| | | .. code-block:: ini |
| | | |
| | | [pserve] |
| | | watch_files = |
| | | myproject/static/favicon.ico |
| | | |
| | | Paths may be absolute or relative to the configuration file. They may also |
| | | be an :term:`asset specification`. These paths are passed to ``hupper``, which |
| | | has some basic support for globbing. Acceptable glob patterns depend on the |
| | | version of Python being used. |