Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Fixed #16671 - Added a tutorial on reuseable apps

Thank-you Katie Miller and Ben Sturmfels for the initial draft,
as well as Russ and Carl for the reviews.
  • Loading branch information...
commit 08cf54990ae112083b159aa4e263c1f64f396f39 1 parent 2f035a9
Tim Graham authored October 30, 2012
2  AUTHORS
@@ -380,6 +380,7 @@ answer newbie questions, and generally made Django that much better:
380 380
     Christian Metts
381 381
     michal@plovarna.cz
382 382
     Slawek Mikula <slawek dot mikula at gmail dot com>
  383
+    Katie Miller <katie@sub50.com>
383 384
     Shawn Milochik <shawn@milochik.com>
384 385
     mitakummaa@gmail.com
385 386
     Taylor Mitchell <taylor.mitchell@gmail.com>
@@ -510,6 +511,7 @@ answer newbie questions, and generally made Django that much better:
510 511
     Johan C. Stöver <johan@nilling.nl>
511 512
     Nowell Strite <http://nowell.strite.org/>
512 513
     Thomas Stromberg <tstromberg@google.com>
  514
+    Ben Sturmfels <ben@sturm.com.au>
513 515
     Travis Swicegood <travis@domain51.com>
514 516
     Pascal Varet
515 517
     SuperJared
3  docs/index.txt
@@ -46,6 +46,9 @@ Are you new to Django or to programming? This is the place to start!
46 46
   :doc:`Part 3 <intro/tutorial03>` |
47 47
   :doc:`Part 4 <intro/tutorial04>`
48 48
 
  49
+* **Advanced Tutorials:**
  50
+  :doc:`How to write reusable apps <intro/reusable-apps>`
  51
+
49 52
 The model layer
50 53
 ===============
51 54
 
13  docs/intro/index.txt
@@ -6,31 +6,32 @@ place: read this material to quickly get up and running.
6 6
 
7 7
 .. toctree::
8 8
    :maxdepth: 1
9  
-    
  9
+
10 10
    overview
11 11
    install
12 12
    tutorial01
13 13
    tutorial02
14 14
    tutorial03
15 15
    tutorial04
  16
+   reusable-apps
16 17
    whatsnext
17  
-   
  18
+
18 19
 .. seealso::
19 20
 
20 21
     If you're new to Python_, you might want to start by getting an idea of what
21 22
     the language is like. Django is 100% Python, so if you've got minimal
22 23
     comfort with Python you'll probably get a lot more out of Django.
23  
-    
  24
+
24 25
     If you're new to programming entirely, you might want to start with this
25 26
     `list of Python resources for non-programmers`_
26  
-    
  27
+
27 28
     If you already know a few other languages and want to get up to speed with
28 29
     Python quickly, we recommend `Dive Into Python`_ (also available in a
29 30
     `dead-tree version`_). If that's not quite your style, there are quite
30 31
     a few other `books about Python`_.
31  
-    
  32
+
32 33
     .. _python: http://python.org/
33 34
     .. _list of Python resources for non-programmers: http://wiki.python.org/moin/BeginnersGuide/NonProgrammers
34 35
     .. _dive into python: http://diveintopython.net/
35 36
     .. _dead-tree version: http://www.amazon.com/exec/obidos/ASIN/1590593561/ref=nosim/jacobian20
36  
-    .. _books about Python: http://wiki.python.org/moin/PythonBooks
  37
+    .. _books about Python: http://wiki.python.org/moin/PythonBooks
363  docs/intro/reusable-apps.txt
... ...
@@ -0,0 +1,363 @@
  1
+=============================================
  2
+Advanced tutorial: How to write reusable apps
  3
+=============================================
  4
+
  5
+This advanced tutorial begins where :doc:`Tutorial 4 </intro/tutorial04>` left
  6
+off. We'll be turning our Web-poll into a standalone Python package you can
  7
+reuse in new projects and share with other people.
  8
+
  9
+If you haven't recently completed Tutorials 1–4, we encourage you to review
  10
+these so that your example project matches the one described below.
  11
+
  12
+Reusability matters
  13
+===================
  14
+
  15
+It's a lot of work to design, build, test and maintain a web application. Many
  16
+Python and Django projects share common problems. Wouldn't it be great if we
  17
+could save some of this repeated work?
  18
+
  19
+Reusability is the way of life in Python. `The Python Package Index (PyPI)
  20
+<http://guide.python-distribute.org/contributing.html#pypi-info>`_ has a vast
  21
+range of packages you can use in your own Python programs. Check out `Django
  22
+Packages <http://www.djangopackages.com>`_ for existing reusable apps you could
  23
+incorporate in your project. Django itself is also just a Python package. This
  24
+means that you can take existing Python packages or Django apps and compose
  25
+them into your own web project. You only need to write the parts that make
  26
+your project unique.
  27
+
  28
+Let's say you were starting a new project that needed a polls app like the one
  29
+we've been working on. How do you make this app reusable? Luckily, you're well
  30
+on the way already. In :doc:`Tutorial 3 </intro/tutorial03>`, we saw how we
  31
+could decouple polls from the project-level URLconf using an ``include``.
  32
+In this tutorial, we'll take further steps to make the app easy to use in new
  33
+projects and ready to publish for others to install and use.
  34
+
  35
+.. admonition:: Package? App?
  36
+
  37
+    A Python `package <http://docs.python.org/tutorial/modules.html#packages>`_
  38
+    provides a way of grouping related Python code for easy reuse. A package
  39
+    contains one or more files of Python code (also known as "modules").
  40
+
  41
+    A package can be imported with ``import foo.bar`` or ``from foo import
  42
+    bar``. For a directory (like ``polls``) to form a package, it must contain
  43
+    a special file ``__init__.py``, even if this file is empty.
  44
+
  45
+    A Django *app* is just a Python package that is specifically intended for
  46
+    use in a Django project. An app may also use common Django conventions,
  47
+    such as having a ``models.py`` file.
  48
+
  49
+    Later on we use the term *packaging* to describe the process of making a
  50
+    Python package easy for others to install. It can be a little confusing, we
  51
+    know.
  52
+
  53
+Completing your reusable app
  54
+============================
  55
+
  56
+After the previous tutorials, our project should look like this::
  57
+
  58
+    mysite/
  59
+        manage.py
  60
+        mysite/
  61
+            __init__.py
  62
+            settings.py
  63
+            urls.py
  64
+            wsgi.py
  65
+        polls/
  66
+            admin.py
  67
+            __init__.py
  68
+            models.py
  69
+            tests.py
  70
+            urls.py
  71
+            views.py
  72
+
  73
+You also have a directory somewhere called ``mytemplates`` which you created in
  74
+:doc:`Tutorial 2 </intro/tutorial02>`. You specified its location in the
  75
+TEMPLATE_DIRS setting. This directory should look like this::
  76
+
  77
+    mytemplates/
  78
+        admin/
  79
+            base_site.html
  80
+        polls/
  81
+            detail.html
  82
+            index.html
  83
+            results.html
  84
+
  85
+The polls app is already a Python package, thanks to the ``polls/__init__.py``
  86
+file. That's a great start, but we can't just pick up this package and drop it
  87
+into a new project. The polls templates are currently stored in the
  88
+project-wide ``mytemplates`` directory. To make the app self-contained, it
  89
+should also contain the necessary templates.
  90
+
  91
+Inside the ``polls`` app, create a new ``templates`` directory. Now move the
  92
+``polls`` template directory from ``mytemplates`` into the new
  93
+``templates``. Your project should now look like this::
  94
+
  95
+    mysite/
  96
+        manage.py
  97
+        mysite/
  98
+            __init__.py
  99
+            settings.py
  100
+            urls.py
  101
+            wsgi.py
  102
+        polls/
  103
+            admin.py
  104
+            __init__.py
  105
+            models.py
  106
+            templates/
  107
+                polls/
  108
+                    detail.html
  109
+                    index.html
  110
+                    results.html
  111
+            tests.py
  112
+            urls.py
  113
+            views.py
  114
+
  115
+Your project-wide templates directory should now look like this::
  116
+
  117
+    mytemplates/
  118
+        admin/
  119
+            base_site.html
  120
+
  121
+Looking good! Now would be a good time to confirm that your polls application
  122
+still works correctly.  How does Django know how to find the new location of
  123
+the polls templates even though we didn't modify :setting:`TEMPLATE_DIRS`?
  124
+Django has a :setting:`TEMPLATE_LOADERS` setting which contains a list
  125
+of callables that know how to import templates from various sources.  One of
  126
+the defaults is :class:`django.template.loaders.app_directories.Loader` which
  127
+looks for a "templates" subdirectory in each of the :setting:`INSTALLED_APPS`.
  128
+
  129
+The ``polls`` directory could now be copied into a new Django project and
  130
+immediately reused. It's not quite ready to be published though. For that, we
  131
+need to package the app to make it easy for others to install.
  132
+
  133
+.. admonition:: Why nested?
  134
+
  135
+   Why create a ``polls`` directory under ``templates`` when we're
  136
+   already inside the polls app? This directory is needed to avoid conflicts in
  137
+   Django's ``app_directories`` template loader.  For example, if two
  138
+   apps had a template called ``base.html``, without the extra directory it
  139
+   wouldn't be possible to distinguish between the two. It's a good convention
  140
+   to use the name of your app for this directory.
  141
+
  142
+.. _installing-reusable-apps-prerequisites:
  143
+
  144
+Installing some prerequisites
  145
+=============================
  146
+
  147
+The current state of Python packaging is a bit muddled with various tools. For
  148
+this tutorial, we're going to use distribute_ to build our package. It's a
  149
+community-maintained fork of the older ``setuptools`` project. We'll also be
  150
+using `pip`_ to uninstall it after we're finished. You should install these
  151
+two packages now. If you need help, you can refer to :ref:`how to install
  152
+Django with pip<installing-official-release>`. You can install ``distribute``
  153
+the same way.
  154
+
  155
+.. _distribute: http://pypi.python.org/pypi/distribute
  156
+.. _pip: http://pypi.python.org/pypi/pip
  157
+
  158
+Packaging your app
  159
+==================
  160
+
  161
+Python *packaging* refers to preparing your app in a specific format that can
  162
+be easily installed and used. Django itself is packaged very much like
  163
+this. For a small app like polls, this process isn't too difficult.
  164
+
  165
+1. First, create a parent directory for ``polls``, outside of your Django
  166
+   project. Call this directory ``django-polls``.
  167
+
  168
+.. admonition::  Choosing a name for your app
  169
+
  170
+   When choosing a name for your package, check resources like PyPI to avoid
  171
+   naming conflicts with existing packages. It's often useful to prepend
  172
+   ``django-`` to your module name when creating a package to distribute.
  173
+   This helps others looking for Django apps identify your app as Django
  174
+   specific.
  175
+
  176
+2. Move the ``polls`` directory into the ``django-polls`` directory.
  177
+
  178
+3. Create a file ``django-polls/README.txt`` with the following contents::
  179
+
  180
+    =====
  181
+    Polls
  182
+    =====
  183
+
  184
+    Polls is a simple Django app to conduct Web-based polls. For each
  185
+    question, visitors can choose between a fixed number of answers.
  186
+
  187
+    Detailed documentation is in the "docs" directory.
  188
+
  189
+    Quick start
  190
+    -----------
  191
+
  192
+    1. Add "polls" to your INSTALLED_APPS setting like this::
  193
+
  194
+          INSTALLED_APPS = (
  195
+              ...
  196
+              'polls',
  197
+          )
  198
+
  199
+    2. Include the polls URLconf in your project urls.py like this::
  200
+
  201
+          url(r'^polls/', include('polls.urls')),
  202
+
  203
+    3. Run `python manage.py syncdb` to create the polls models.
  204
+
  205
+    4. Start the development server and visit http://127.0.0.1:8000/admin/
  206
+      to create a poll (you'll need the Admin app enabled).
  207
+
  208
+    5. Visit http://127.0.0.1:8000/polls/ to participate in the poll.
  209
+
  210
+4. Create a ``django-polls/LICENSE`` file. Choosing a license is beyond the
  211
+scope of this tutorial, but suffice it to say that code released publicly
  212
+without a license is *useless*. Django and many Django-compatible apps are
  213
+distributed under the BSD license; however, you're free to pick your own
  214
+license. Just be aware that your licensing choice will affect who is able
  215
+to use your code.
  216
+
  217
+5. Next we'll create a ``setup.py`` file which provides details about how to
  218
+build and install the app.  A full explanation of this file is beyond the
  219
+scope of this tutorial, but the `distribute docs
  220
+<http://packages.python.org/distribute/setuptools.html>`_ have a good explanation.
  221
+Create a file ``django-polls/setup.py`` with the following contents::
  222
+
  223
+    import os
  224
+    from setuptools import setup
  225
+
  226
+    README = open(os.path.join(os.path.dirname(__file__), 'README.txt')).read()
  227
+
  228
+    # allow setup.py to be run from any path
  229
+    os.chdir(os.path.normpath(os.path.join(os.path.abspath(__file__), os.pardir)))
  230
+
  231
+    setup(
  232
+        name = 'django-polls',
  233
+        version = '0.1',
  234
+        packages = ['polls'],
  235
+        include_package_data = True,
  236
+        license = 'BSD License', # example license
  237
+        description = 'A simple Django app to conduct Web-based polls.',
  238
+        long_description = README,
  239
+        url = 'http://www.example.com/',
  240
+        author = 'Your Name',
  241
+        author_email = 'yourname@example.com',
  242
+        classifiers = [
  243
+            'Environment :: Web Environment',
  244
+            'Framework :: Django',
  245
+            'Intended Audience :: Developers',
  246
+            'License :: OSI Approved :: BSD License', # example license
  247
+            'Operating System :: OS Independent',
  248
+            'Programming Language :: Python',
  249
+            'Programming Language :: Python :: 2.6',
  250
+            'Programming Language :: Python :: 2.7',
  251
+            'Topic :: Internet :: WWW/HTTP',
  252
+            'Topic :: Internet :: WWW/HTTP :: Dynamic Content',
  253
+        ],
  254
+    )
  255
+
  256
+.. admonition:: I thought you said we were going to use ``distribute``?
  257
+
  258
+    Distribute is a drop-in replacement for ``setuptools``. Even though we
  259
+    appear to import from ``setuptools``, since we have ``distribute``
  260
+    installed, it will override the import.
  261
+
  262
+6. Only Python modules and packages are included in the package by default. To
  263
+   include additional files, we'll need to create a ``MANIFEST.in`` file. The
  264
+   distribute docs referred to in the previous step discuss this file in more
  265
+   details. To include the templates and our LICENSE file, create a file
  266
+   ``django-polls/MANIFEST.in`` with the following contents::
  267
+
  268
+    include LICENSE
  269
+    recursive-include polls/templates *
  270
+
  271
+7. It's optional, but recommended, to include detailed documentation with your
  272
+   app. Create an empty directory ``django-polls/docs`` for future
  273
+   documentation. Add an additional line to ``django-polls/MANIFEST.in``::
  274
+
  275
+    recursive-include docs *
  276
+
  277
+   Note that the ``docs`` directory won't be included in your package unless
  278
+   you add some files to it. Many Django apps also provide their documentation
  279
+   online through sites like `readthedocs.org <http://readthedocs.org>`_.
  280
+
  281
+8. Try building your package with ``python setup.py sdist`` (run from inside
  282
+   ``django-polls``). This creates a directory called ``dist`` and builds your
  283
+   new package, ``django-polls-0.1.tar.gz``.
  284
+
  285
+For more information on packaging, see `The Hitchhiker's Guide to Packaging
  286
+<http://guide.python-distribute.org/quickstart.html>`_.
  287
+
  288
+Using your own package
  289
+======================
  290
+
  291
+Since we moved the ``polls`` directory out of the project, it's no longer
  292
+working. We'll now fix this by installing our new ``django-polls`` package.
  293
+
  294
+.. admonition:: Installing as a system library
  295
+
  296
+   The following steps install ``django-polls`` as a system library. In
  297
+   general, it's best to avoid messing with your system libraries to avoid
  298
+   breaking things. For this simple example though, the risk is low and it will
  299
+   help with understanding packaging. We'll explain how to uninstall in
  300
+   step 4.
  301
+
  302
+   For experienced users, a neater way to manage your packages is to use
  303
+   "virtualenv" (see below).
  304
+
  305
+1. Inside ``django-polls/dist``, untar the new package
  306
+   ``django-polls-0.1.tar.gz`` (e.g. ``tar xzvf django-polls-0.1.tar.gz``). If
  307
+   you're using Windows, you can download the command-line tool bsdtar_ to do
  308
+   this, or you can use a GUI-based tool such as 7-zip_.
  309
+
  310
+2. Change into the directory created in step 1 (e.g. ``cd django-polls-0.1``).
  311
+
  312
+3. If you're using GNU/Linux, Mac OS X or some other flavor of Unix, enter the
  313
+   command ``sudo python setup.py install`` at the shell prompt.  If you're
  314
+   using Windows, start up a command shell with administrator privileges and
  315
+   run the command ``setup.py install``.
  316
+
  317
+   With luck, your Django project should now work correctly again. Run the
  318
+   server again to confirm this.
  319
+
  320
+4. To uninstall the package, use pip (you already :ref:`installed it
  321
+   <installing-reusable-apps-prerequisites>`, right?)::
  322
+
  323
+    sudo pip uninstall django-polls
  324
+
  325
+.. _bsdtar: http://gnuwin32.sourceforge.net/packages/bsdtar.htm
  326
+.. _7-zip: http://www.7-zip.org/
  327
+.. _pip: http://pypi.python.org/pypi/pip
  328
+
  329
+Publishing your app
  330
+===================
  331
+
  332
+Now that we've packaged and tested ``django-polls``, it's ready to share with
  333
+the world! If this wasn't just an example, you could now:
  334
+
  335
+* Email the package to a friend.
  336
+
  337
+* Upload the package on your Web site.
  338
+
  339
+* Post the package on a public repository, such as `The Python Package Index
  340
+  (PyPI) <http://guide.python-distribute.org/contributing.html#pypi-info>`_.
  341
+
  342
+For more information on PyPI, see the `Quickstart
  343
+<http://guide.python-distribute.org/quickstart.html#register-your-package-with-the-python-package-index-pypi>`_
  344
+section of The Hitchhiker's Guide to Packaging. One detail this guide mentions
  345
+is choosing the license under which your code is distributed.
  346
+
  347
+Installing Python packages with virtualenv
  348
+==========================================
  349
+
  350
+Earlier, we installed the polls app as a system library. This has some
  351
+disadvantages:
  352
+
  353
+* Modifying the system libraries can affect other Python software on your
  354
+  system.
  355
+
  356
+* You won't be able to run multiple versions of this package (or others with
  357
+  the same name).
  358
+
  359
+Typically, these situations only arise once you're maintaining several Django
  360
+projects. When they do, the best solution is to use `virtualenv
  361
+<http://www.virtualenv.org/>`_. This tool allows you to maintain multiple
  362
+isolated Python environments, each with its own copy of the libraries and
  363
+package namespace.
6  docs/intro/tutorial03.txt
@@ -315,6 +315,12 @@ Load the page in your Web browser, and you should see a bulleted-list
315 315
 containing the "What's up" poll from Tutorial 1. The link points to the poll's
316 316
 detail page.
317 317
 
  318
+.. admonition:: Organizing Templates
  319
+
  320
+    Rather than one big templates directory, you can also store templates
  321
+    within each app. We'll discuss this in more detail in the :doc:`reusable
  322
+    apps tutorial</intro/reusable-apps>`.
  323
+
318 324
 A shortcut: :func:`~django.shortcuts.render`
319 325
 --------------------------------------------
320 326
 
9  docs/intro/tutorial04.txt
@@ -278,5 +278,10 @@ For full details on generic views, see the :doc:`generic views documentation
278 278
 What's next?
279 279
 ============
280 280
 
281  
-The tutorial ends here for the time being. In the meantime, you might want to
282  
-check out some pointers on :doc:`where to go from here </intro/whatsnext>`.
  281
+The beginner tutorial ends here for the time being. In the meantime, you might
  282
+want to check out some pointers on :doc:`where to go from here
  283
+</intro/whatsnext>`.
  284
+
  285
+If you are familiar with Python packaging and interested in learning how to
  286
+turn polls into a "reusable app", check out :doc:`Advanced tutorial: How to
  287
+write reusable apps</intro/reusable-apps>`.

0 notes on commit 08cf549

Please sign in to comment.
Something went wrong with that request. Please try again.