mirror of
https://github.com/django/django.git
synced 2024-12-26 02:56:25 +00:00
3f1c7b7053
Squashed commit of: commit 508ec9144b35c50794708225b496bde1eb5e60aa Author: Aymeric Augustin <aymeric.augustin@m4x.org> Date: Tue Jan 29 22:50:55 2013 +0100 Tweaked default settings file. * Explained why BASE_DIR exists. * Added a link to the database configuration options, and put it in its own section. * Moved sensitive settings that must be changed for production at the top. commit 6515fd2f1aa73a86dc8dbd2ccf512ddb6b140d57 Author: Aymeric Augustin <aymeric.augustin@m4x.org> Date: Tue Jan 29 14:35:21 2013 +0100 Documented the simplified app & project templates in the changelog. commit 2c5b576c2ea91d84273a019b3d0b3b8b4da72f23 Author: Aymeric Augustin <aymeric.augustin@m4x.org> Date: Tue Jan 29 13:59:27 2013 +0100 Minor fixes in tutorials 5 and 6. commit 55a51531be8104f21b3cca3f6bf70b0a7139a041 Author: Aymeric Augustin <aymeric.augustin@m4x.org> Date: Tue Jan 29 13:51:11 2013 +0100 Updated tutorial 2 for the new project template. commit 29ddae87bdaecff12dd31b16b000c01efbde9e20 Author: Aymeric Augustin <aymeric.augustin@m4x.org> Date: Tue Jan 29 11:58:54 2013 +0100 Updated tutorial 1 for the new project template. commit 0ecb9f6e2514cfd26a678a280d471433375101a3 Author: Aymeric Augustin <aymeric.augustin@m4x.org> Date: Tue Jan 29 11:29:13 2013 +0100 Adjusted the default URLconf detection to account for the admin. It's now enabled by default. commit 5fb4da0d3d09dac28dd94e3fde92b9d4335c0565 Author: Aymeric Augustin <aymeric.augustin@m4x.org> Date: Tue Jan 29 10:36:55 2013 +0100 Added security warnings for the most sensitive settings. commit 718d84bd8ac4a42fb4b28ec93965de32680f091e Author: Aymeric Augustin <aymeric.augustin@m4x.org> Date: Mon Jan 28 23:24:06 2013 +0100 Used an absolute path for the SQLite database. This ensures the settings file works regardless of which directory django-admin.py / manage.py is invoked from. BASE_DIR got a +1 from a BDFL and another core dev. It doesn't involve the concept of a "Django project"; it's just a convenient way to express relative paths within the source code repository for non-Python files. Thanks Jacob Kaplan-Moss for the suggestion. commit 1b559b4bcda622e10909b68fe5cab90db6727dd9 Author: Aymeric Augustin <aymeric.augustin@m4x.org> Date: Mon Jan 28 23:22:40 2013 +0100 Removed STATIC_ROOT from the default settings template. It isn't necessary in development, and it confuses beginners to no end. Thanks Carl Meyer for the suggestion. commit a55f141a500bb7c9a1bc259bbe1954c13b199671 Author: Aymeric Augustin <aymeric.augustin@m4x.org> Date: Mon Jan 28 23:21:43 2013 +0100 Removed MEDIA_ROOT/URL from default settings template. Many sites will never deal with user-uploaded files, and MEDIA_ROOT is complicated to explain. Thanks Carl Meyer for the suggestion. commit 44bf2f2441420fd9429ee9fe1f7207f92dd87e70 Author: Aymeric Augustin <aymeric.augustin@m4x.org> Date: Mon Jan 28 22:22:09 2013 +0100 Removed logging config. This configuration is applied regardless of the value of LOGGING; duplicating it in LOGGING is confusing. commit eac747e848eaed65fd5f6f254f0a7559d856f88f Author: Aymeric Augustin <aymeric.augustin@m4x.org> Date: Mon Jan 28 22:05:31 2013 +0100 Enabled the locale middleware by default. USE_I18N is True by default, and doesn't work well without LocaleMiddleware. commit d806c62b2d00826dc2688c84b092627b8d571cab Author: Aymeric Augustin <aymeric.augustin@m4x.org> Date: Mon Jan 28 22:03:16 2013 +0100 Enabled clickjacking protection by default. commit 99152c30e6a15003f0b6737dc78e87adf462aacb Author: Aymeric Augustin <aymeric.augustin@m4x.org> Date: Mon Jan 28 22:01:48 2013 +0100 Reorganized settings in logical sections, and trimmed comments. commit d37ffdfcb24b7e0ec7cc113d07190f65fb12fb8a Author: Aymeric Augustin <aymeric.augustin@m4x.org> Date: Mon Jan 28 16:54:11 2013 +0100 Avoided misleading TEMPLATE_DEBUG = DEBUG. According to the docs TEMPLATE_DEBUG works only when DEBUG = True. commit 15d9478d3a9850e85841e7cf09cf83050371c6bf Author: Aymeric Augustin <aymeric.augustin@m4x.org> Date: Mon Jan 28 16:46:25 2013 +0100 Removed STATICFILES_FINDERS/TEMPLATE_LOADERS from default settings file. Only developers with special needs ever need to change these settings. commit 574da0eb5bfb4570883756914b4dbd7e20e1f61e Author: Aymeric Augustin <aymeric.augustin@m4x.org> Date: Mon Jan 28 16:45:01 2013 +0100 Removed STATICFILES/TEMPLATES_DIRS from default settings file. The current best practice is to put static files and templates in applications, for easier testing and deployment. commit 8cb18dbe56629aa1be74718a07e7cc66b4f9c9f0 Author: Aymeric Augustin <aymeric.augustin@m4x.org> Date: Mon Jan 28 16:24:16 2013 +0100 Removed settings related to email reporting from default settings file. While handy for small scale projects, it isn't exactly a best practice. commit 8ecbfcb3638058f0c49922540f874a7d802d864f Author: Aymeric Augustin <aymeric.augustin@m4x.org> Date: Tue Jan 29 18:54:43 2013 +0100 Documented how to enable the sites framework. commit 23fc91a6fa67d91ddd9d71b1c3e0dc26bdad9841 Author: Aymeric Augustin <aymeric.augustin@m4x.org> Date: Mon Jan 28 16:28:59 2013 +0100 Disabled the sites framework by default. RequestSite does the job for single-domain websites. commit c4d82eb8afc0eb8568bf9c4d12644272415e3960 Author: Aymeric Augustin <aymeric.augustin@m4x.org> Date: Tue Jan 29 00:08:33 2013 +0100 Added a default admin.py to the application template. Thanks Ryan D Hiebert for the suggestion. commit 4071dc771e5c44b1c5ebb9beecefb164ae465e22 Author: Aymeric Augustin <aymeric.augustin@m4x.org> Date: Mon Jan 28 10:59:49 2013 +0100 Enabled the admin by default. Everyone uses the admin. commit c807a31f8d89e7e7fd97380e3023f7983a8b6fcb Author: Aymeric Augustin <aymeric.augustin@m4x.org> Date: Mon Jan 28 10:57:05 2013 +0100 Removed admindocs from default project template. commit 09e4ce0e652a97da1a9e285046a91c8ad7a9189c Author: Aymeric Augustin <aymeric.augustin@m4x.org> Date: Mon Jan 28 16:32:52 2013 +0100 Added links to the settings documentation. commit 5b8f5eaef364eb790fcde6f9e86f7d266074cca8 Author: Aymeric Augustin <aymeric.augustin@m4x.org> Date: Mon Jan 28 11:06:54 2013 +0100 Used a significant example for URLconf includes. commit 908e91d6fcee2a3cb51ca26ecdf12a6a24e69ef8 Author: Aymeric Augustin <aymeric.augustin@m4x.org> Date: Mon Jan 28 16:22:31 2013 +0100 Moved code comments about WSGI to docs, and rewrote said docs. commit 50417e51996146f891d08ca8b74dcc736a581932 Author: Aymeric Augustin <aymeric.augustin@m4x.org> Date: Mon Jan 28 15:51:50 2013 +0100 Normalized the default application template. Removed the default test that 1 + 1 = 2, because it's been committed way too many times, in too many projects. Added an import of `render` for views, because the first view will often be: def home(request): return render(request, "mysite/home.html")
366 lines
14 KiB
Plaintext
366 lines
14 KiB
Plaintext
=============================================
|
||
Advanced tutorial: How to write reusable apps
|
||
=============================================
|
||
|
||
This advanced tutorial begins where :doc:`Tutorial 5 </intro/tutorial05>` left
|
||
off. We'll be turning our Web-poll into a standalone Python package you can
|
||
reuse in new projects and share with other people.
|
||
|
||
If you haven't recently completed Tutorials 1–5, we encourage you to review
|
||
these so that your example project matches the one described below.
|
||
|
||
Reusability matters
|
||
===================
|
||
|
||
It's a lot of work to design, build, test and maintain a web application. Many
|
||
Python and Django projects share common problems. Wouldn't it be great if we
|
||
could save some of this repeated work?
|
||
|
||
Reusability is the way of life in Python. `The Python Package Index (PyPI)
|
||
<http://guide.python-distribute.org/contributing.html#pypi-info>`_ has a vast
|
||
range of packages you can use in your own Python programs. Check out `Django
|
||
Packages <http://www.djangopackages.com>`_ for existing reusable apps you could
|
||
incorporate in your project. Django itself is also just a Python package. This
|
||
means that you can take existing Python packages or Django apps and compose
|
||
them into your own web project. You only need to write the parts that make
|
||
your project unique.
|
||
|
||
Let's say you were starting a new project that needed a polls app like the one
|
||
we've been working on. How do you make this app reusable? Luckily, you're well
|
||
on the way already. In :doc:`Tutorial 3 </intro/tutorial03>`, we saw how we
|
||
could decouple polls from the project-level URLconf using an ``include``.
|
||
In this tutorial, we'll take further steps to make the app easy to use in new
|
||
projects and ready to publish for others to install and use.
|
||
|
||
.. admonition:: Package? App?
|
||
|
||
A Python `package <http://docs.python.org/tutorial/modules.html#packages>`_
|
||
provides a way of grouping related Python code for easy reuse. A package
|
||
contains one or more files of Python code (also known as "modules").
|
||
|
||
A package can be imported with ``import foo.bar`` or ``from foo import
|
||
bar``. For a directory (like ``polls``) to form a package, it must contain
|
||
a special file ``__init__.py``, even if this file is empty.
|
||
|
||
A Django *app* is just a Python package that is specifically intended for
|
||
use in a Django project. An app may also use common Django conventions,
|
||
such as having a ``models.py`` file.
|
||
|
||
Later on we use the term *packaging* to describe the process of making a
|
||
Python package easy for others to install. It can be a little confusing, we
|
||
know.
|
||
|
||
Completing your reusable app
|
||
============================
|
||
|
||
After the previous tutorials, our project should look like this::
|
||
|
||
mysite/
|
||
manage.py
|
||
mysite/
|
||
__init__.py
|
||
settings.py
|
||
urls.py
|
||
wsgi.py
|
||
polls/
|
||
__init__.py
|
||
admin.py
|
||
models.py
|
||
tests.py
|
||
urls.py
|
||
views.py
|
||
|
||
You also have a directory somewhere called ``mytemplates`` which you created in
|
||
:doc:`Tutorial 2 </intro/tutorial02>`. You specified its location in the
|
||
TEMPLATE_DIRS setting. This directory should look like this::
|
||
|
||
mytemplates/
|
||
admin/
|
||
base_site.html
|
||
polls/
|
||
detail.html
|
||
index.html
|
||
results.html
|
||
|
||
The polls app is already a Python package, thanks to the ``polls/__init__.py``
|
||
file. That's a great start, but we can't just pick up this package and drop it
|
||
into a new project. The polls templates are currently stored in the
|
||
project-wide ``mytemplates`` directory. To make the app self-contained, it
|
||
should also contain the necessary templates.
|
||
|
||
Inside the ``polls`` app, create a new ``templates`` directory. Now move the
|
||
``polls`` template directory from ``mytemplates`` into the new
|
||
``templates``. Your project should now look like this::
|
||
|
||
mysite/
|
||
manage.py
|
||
mysite/
|
||
__init__.py
|
||
settings.py
|
||
urls.py
|
||
wsgi.py
|
||
polls/
|
||
admin.py
|
||
__init__.py
|
||
models.py
|
||
templates/
|
||
polls/
|
||
detail.html
|
||
index.html
|
||
results.html
|
||
tests.py
|
||
urls.py
|
||
views.py
|
||
|
||
Your project-wide templates directory should now look like this::
|
||
|
||
mytemplates/
|
||
admin/
|
||
base_site.html
|
||
|
||
Looking good! Now would be a good time to confirm that your polls application
|
||
still works correctly. How does Django know how to find the new location of
|
||
the polls templates even though we didn't modify :setting:`TEMPLATE_DIRS`?
|
||
Django has a :setting:`TEMPLATE_LOADERS` setting which contains a list
|
||
of callables that know how to import templates from various sources. One of
|
||
the defaults is :class:`django.template.loaders.app_directories.Loader` which
|
||
looks for a "templates" subdirectory in each of the :setting:`INSTALLED_APPS`.
|
||
|
||
The ``polls`` directory could now be copied into a new Django project and
|
||
immediately reused. It's not quite ready to be published though. For that, we
|
||
need to package the app to make it easy for others to install.
|
||
|
||
.. admonition:: Why nested?
|
||
|
||
Why create a ``polls`` directory under ``templates`` when we're
|
||
already inside the polls app? This directory is needed to avoid conflicts in
|
||
Django's ``app_directories`` template loader. For example, if two
|
||
apps had a template called ``base.html``, without the extra directory it
|
||
wouldn't be possible to distinguish between the two. It's a good convention
|
||
to use the name of your app for this directory.
|
||
|
||
.. _installing-reusable-apps-prerequisites:
|
||
|
||
Installing some prerequisites
|
||
=============================
|
||
|
||
The current state of Python packaging is a bit muddled with various tools. For
|
||
this tutorial, we're going to use distribute_ to build our package. It's a
|
||
community-maintained fork of the older ``setuptools`` project. We'll also be
|
||
using `pip`_ to uninstall it after we're finished. You should install these
|
||
two packages now. If you need help, you can refer to :ref:`how to install
|
||
Django with pip<installing-official-release>`. You can install ``distribute``
|
||
the same way.
|
||
|
||
.. _distribute: http://pypi.python.org/pypi/distribute
|
||
.. _pip: http://pypi.python.org/pypi/pip
|
||
|
||
Packaging your app
|
||
==================
|
||
|
||
Python *packaging* refers to preparing your app in a specific format that can
|
||
be easily installed and used. Django itself is packaged very much like
|
||
this. For a small app like polls, this process isn't too difficult.
|
||
|
||
1. First, create a parent directory for ``polls``, outside of your Django
|
||
project. Call this directory ``django-polls``.
|
||
|
||
.. admonition:: Choosing a name for your app
|
||
|
||
When choosing a name for your package, check resources like PyPI to avoid
|
||
naming conflicts with existing packages. It's often useful to prepend
|
||
``django-`` to your module name when creating a package to distribute.
|
||
This helps others looking for Django apps identify your app as Django
|
||
specific.
|
||
|
||
2. Move the ``polls`` directory into the ``django-polls`` directory.
|
||
|
||
3. Create a file ``django-polls/README.txt`` with the following contents::
|
||
|
||
=====
|
||
Polls
|
||
=====
|
||
|
||
Polls is a simple Django app to conduct Web-based polls. For each
|
||
question, visitors can choose between a fixed number of answers.
|
||
|
||
Detailed documentation is in the "docs" directory.
|
||
|
||
Quick start
|
||
-----------
|
||
|
||
1. Add "polls" to your INSTALLED_APPS setting like this::
|
||
|
||
INSTALLED_APPS = (
|
||
...
|
||
'polls',
|
||
)
|
||
|
||
2. Include the polls URLconf in your project urls.py like this::
|
||
|
||
url(r'^polls/', include('polls.urls')),
|
||
|
||
3. Run `python manage.py syncdb` to create the polls models.
|
||
|
||
4. Start the development server and visit http://127.0.0.1:8000/admin/
|
||
to create a poll (you'll need the Admin app enabled).
|
||
|
||
5. Visit http://127.0.0.1:8000/polls/ to participate in the poll.
|
||
|
||
4. Create a ``django-polls/LICENSE`` file. Choosing a license is beyond the
|
||
scope of this tutorial, but suffice it to say that code released publicly
|
||
without a license is *useless*. Django and many Django-compatible apps are
|
||
distributed under the BSD license; however, you're free to pick your own
|
||
license. Just be aware that your licensing choice will affect who is able
|
||
to use your code.
|
||
|
||
5. Next we'll create a ``setup.py`` file which provides details about how to
|
||
build and install the app. A full explanation of this file is beyond the
|
||
scope of this tutorial, but the `distribute docs
|
||
<http://packages.python.org/distribute/setuptools.html>`_ have a good explanation.
|
||
Create a file ``django-polls/setup.py`` with the following contents::
|
||
|
||
import os
|
||
from setuptools import setup
|
||
|
||
README = open(os.path.join(os.path.dirname(__file__), 'README.txt')).read()
|
||
|
||
# allow setup.py to be run from any path
|
||
os.chdir(os.path.normpath(os.path.join(os.path.abspath(__file__), os.pardir)))
|
||
|
||
setup(
|
||
name = 'django-polls',
|
||
version = '0.1',
|
||
packages = ['polls'],
|
||
include_package_data = True,
|
||
license = 'BSD License', # example license
|
||
description = 'A simple Django app to conduct Web-based polls.',
|
||
long_description = README,
|
||
url = 'http://www.example.com/',
|
||
author = 'Your Name',
|
||
author_email = 'yourname@example.com',
|
||
classifiers = [
|
||
'Environment :: Web Environment',
|
||
'Framework :: Django',
|
||
'Intended Audience :: Developers',
|
||
'License :: OSI Approved :: BSD License', # example license
|
||
'Operating System :: OS Independent',
|
||
'Programming Language :: Python',
|
||
'Programming Language :: Python :: 2.6',
|
||
'Programming Language :: Python :: 2.7',
|
||
'Topic :: Internet :: WWW/HTTP',
|
||
'Topic :: Internet :: WWW/HTTP :: Dynamic Content',
|
||
],
|
||
)
|
||
|
||
.. admonition:: I thought you said we were going to use ``distribute``?
|
||
|
||
Distribute is a drop-in replacement for ``setuptools``. Even though we
|
||
appear to import from ``setuptools``, since we have ``distribute``
|
||
installed, it will override the import.
|
||
|
||
6. Only Python modules and packages are included in the package by default. To
|
||
include additional files, we'll need to create a ``MANIFEST.in`` file. The
|
||
distribute docs referred to in the previous step discuss this file in more
|
||
details. To include the templates and our LICENSE file, create a file
|
||
``django-polls/MANIFEST.in`` with the following contents::
|
||
|
||
include LICENSE
|
||
recursive-include polls/templates *
|
||
|
||
7. It's optional, but recommended, to include detailed documentation with your
|
||
app. Create an empty directory ``django-polls/docs`` for future
|
||
documentation. Add an additional line to ``django-polls/MANIFEST.in``::
|
||
|
||
recursive-include docs *
|
||
|
||
Note that the ``docs`` directory won't be included in your package unless
|
||
you add some files to it. Many Django apps also provide their documentation
|
||
online through sites like `readthedocs.org <http://readthedocs.org>`_.
|
||
|
||
8. Try building your package with ``python setup.py sdist`` (run from inside
|
||
``django-polls``). This creates a directory called ``dist`` and builds your
|
||
new package, ``django-polls-0.1.tar.gz``.
|
||
|
||
For more information on packaging, see `The Hitchhiker's Guide to Packaging
|
||
<http://guide.python-distribute.org/quickstart.html>`_.
|
||
|
||
Using your own package
|
||
======================
|
||
|
||
Since we moved the ``polls`` directory out of the project, it's no longer
|
||
working. We'll now fix this by installing our new ``django-polls`` package.
|
||
|
||
.. admonition:: Installing as a user library
|
||
|
||
The following steps install ``django-polls`` as a user library. Per-user
|
||
installs have a lot of advantages over installing the package system-wide,
|
||
such as being usable on systems where you don't have administrator access
|
||
as well as preventing the package from affecting system services and other
|
||
users of the machine. Python 2.6 added support for user libraries, so if
|
||
you are using an older version this won't work, but Django 1.5 requires
|
||
Python 2.6 or newer anyway.
|
||
|
||
Note that per-user installations can still affect the behavior of system
|
||
tools that run as that user, so ``virtualenv`` is a more robust solution
|
||
(see below).
|
||
|
||
1. Inside ``django-polls/dist``, untar the new package
|
||
``django-polls-0.1.tar.gz`` (e.g. ``tar xzvf django-polls-0.1.tar.gz``). If
|
||
you're using Windows, you can download the command-line tool bsdtar_ to do
|
||
this, or you can use a GUI-based tool such as 7-zip_.
|
||
|
||
2. Change into the directory created in step 1 (e.g. ``cd django-polls-0.1``).
|
||
|
||
3. If you're using GNU/Linux, Mac OS X or some other flavor of Unix, enter the
|
||
command ``python setup.py install --user`` at the shell prompt. If you're
|
||
using Windows, start up a command shell and run the command
|
||
``setup.py install --user``.
|
||
|
||
With luck, your Django project should now work correctly again. Run the
|
||
server again to confirm this.
|
||
|
||
4. To uninstall the package, use pip (you already :ref:`installed it
|
||
<installing-reusable-apps-prerequisites>`, right?)::
|
||
|
||
pip uninstall django-polls
|
||
|
||
.. _bsdtar: http://gnuwin32.sourceforge.net/packages/bsdtar.htm
|
||
.. _7-zip: http://www.7-zip.org/
|
||
.. _pip: http://pypi.python.org/pypi/pip
|
||
|
||
Publishing your app
|
||
===================
|
||
|
||
Now that we've packaged and tested ``django-polls``, it's ready to share with
|
||
the world! If this wasn't just an example, you could now:
|
||
|
||
* Email the package to a friend.
|
||
|
||
* Upload the package on your Web site.
|
||
|
||
* Post the package on a public repository, such as `The Python Package Index
|
||
(PyPI) <http://guide.python-distribute.org/contributing.html#pypi-info>`_.
|
||
|
||
For more information on PyPI, see the `Quickstart
|
||
<http://guide.python-distribute.org/quickstart.html#register-your-package-with-the-python-package-index-pypi>`_
|
||
section of The Hitchhiker's Guide to Packaging. One detail this guide mentions
|
||
is choosing the license under which your code is distributed.
|
||
|
||
Installing Python packages with virtualenv
|
||
==========================================
|
||
|
||
Earlier, we installed the polls app as a user library. This has some
|
||
disadvantages:
|
||
|
||
* Modifying the user libraries can affect other Python software on your system.
|
||
|
||
* You won't be able to run multiple versions of this package (or others with
|
||
the same name).
|
||
|
||
Typically, these situations only arise once you're maintaining several Django
|
||
projects. When they do, the best solution is to use `virtualenv
|
||
<http://www.virtualenv.org/>`_. This tool allows you to maintain multiple
|
||
isolated Python environments, each with its own copy of the libraries and
|
||
package namespace.
|