Commits

Anonymous committed 5edf6fa

Updated tutorials 1-4 to use manage.py instead of django-admin.py, new directory layout (no /apps/ subdirectory) and other various tweaks

Comments (0)

Files changed (5)

docs/django-admin.txt

 This document outlines all it can do.
 
 The ``django-admin.py`` script should be on your system path if you installed
-Django via its setup.py utility. If it's not on your path, you can find it in
+Django via its ``setup.py`` utility. If it's not on your path, you can find it in
 ``site-packages/django/bin`` within your Python installation. Consider
 symlinking to it from some place on your path, such as ``/usr/local/bin``.
 
+In addition, ``manage.py`` is automatically created in each Django project.
+``manage.py`` is a thin wrapper around ``django-admin.py`` that takes care of
+two things for you before delegating to ``django-admin.py``::
+
+    * It puts your project's package on ``sys.path``.
+
+    * It sets the ``DJANGO_SETTINGS_MODULE`` environment variable so that it
+      points to your project's ``settings.py`` file.
+
+Generally, when working on a single Django project, it's easier to use
+``manage.py``. Use ``django-admin.py`` with ``DJANGO_SETTINGS_MODULE``, or the
+``--settings`` command line option, if you need to switch between multiple
+Django settings files.
+
 Usage
 =====
 
 ``django-admin.py action [options]``
+``manage.py action [options]``
 
 ``action`` should be one of the actions listed in this document. ``options``,
 which is optional, should be zero or more of the options listed in this
 in Python path syntax, e.g. "myproject.settings". If this isn't provided,
 ``django-admin.py`` will use the DJANGO_SETTINGS_MODULE environment variable.
 
+Note that this option is unnecessary in ``manage.py``, because it takes care of
+setting ``DJANGO_SETTINGS_MODULE`` for you.
+
 --pythonpath
 ------------
 
 isn't provided, ``django-admin.py`` will use the ``PYTHONPATH`` environment
 variable.
 
+Note that this option is unnecessary in ``manage.py``, because it takes care of
+setting the Python path for you.
+
 .. _import search path: http://diveintopython.org/getting_to_know_python/everything_is_an_object.html
 
 --help

docs/tutorial01.txt

 
 .. admonition:: Where should this code live?
 
-   If your background is in PHP, you're probably used to putting code under the
-   Web server's document root (in a place such as ``/var/www``). With Django,
-   you don't do that. It's not a good idea to put any of this Python code within
-   your Web server's document root, because it risks the possibility that
-   people may be able to view your code over the Web. That's not good for
-   security.
+    If your background is in PHP, you're probably used to putting code under the
+    Web server's document root (in a place such as ``/var/www``). With Django,
+    you don't do that. It's not a good idea to put any of this Python code within
+    your Web server's document root, because it risks the possibility that
+    people may be able to view your code over the Web. That's not good for
+    security.
 
-   Put your code in some directory **outside** of the document root, such as
-   ``/home/mycode``.
+    Put your code in some directory **outside** of the document root, such as
+    ``/home/mycode``.
 
 A project is a collection of settings for an instance of Django -- including
 database configuration, Django-specific options and application-specific
 
     myproject/
         __init__.py
-        apps/
-            __init__.py
+        manage.py
         settings.py
         urls.py
 
-First, edit ``myproject/settings.py``. It's a normal Python module with
-module-level variables representing Django settings. Edit the file and change
-these settings to match your database's connection parameters:
+These files are:
+
+    * ``manage.py``: A command-line utility that lets you interact with this
+      Django project in various ways.
+    * ``settings.py``: Settings/configuration for this Django project.
+    * ``urls.py``: The URL declarations for this Django project; a "table of
+      contents" of your Django-powered site.
+
+The development server
+----------------------
+
+Change into the ``myproject`` directory, if you haven't already, and run the
+command ``python manage.py runserver``. You'll see the following output on the
+command line::
+
+    Validating models...
+    0 errors found.
+
+    Starting server on port 8000 with settings module 'myproject.settings'.
+    Go to http://127.0.0.1:8000/ for Django.
+    Quit the server with CONTROL-C (Unix) or CTRL-BREAK (Windows).
+
+You've started the Django development server, a lightweight, pure-Python Web
+server that builds on the BaseHTTPServer included in Python's standard library.
+We've included this with Django so you can develop things rapidly, without
+having to deal with configuring Apache until you're ready for production.
+
+DON'T use this server in anything resembling a production environment. It's
+intended only for use while developing.
+
+.. admonition:: Changing the port
+
+    By default, the ``runserver`` command starts the development server on port
+    8000. If you want to change the server's port, pass it as a command-line
+    argument::
+
+        python manage.py runserver 8080
+
+Now that the server's running, visit http://127.0.0.1:8000/ with your Web
+browser. You'll see a "Welcome to Django" page, in pleasant, light-blue pastel.
+It worked!
+
+Database setup
+--------------
+
+Now, edit ``settings.py``. It's a normal Python module with module-level
+variables representing Django settings. Change these settings to match your
+database's connection parameters:
 
     * ``DATABASE_ENGINE`` -- Either 'postgresql', 'mysql' or 'sqlite3'.
       More coming soon.
     * ``DATABASE_NAME`` -- The name of your database, or the full (absolute)
-      path to the database file if you're using sqlite.
-    * ``DATABASE_USER`` -- Your database username (not used for sqlite).
-    * ``DATABASE_PASSWORD`` -- Your database password (not used for sqlite).
+      path to the database file if you're using SQLite.
+    * ``DATABASE_USER`` -- Your database username (not used for SQLite).
+    * ``DATABASE_PASSWORD`` -- Your database password (not used for SQLite).
     * ``DATABASE_HOST`` -- The host your database is on. Leave this as an
       empty string if your database server is on the same physical machine
-      (not used for sqlite).
+      (not used for SQLite).
 
 .. admonition:: Note
 
     point. Do that with "``CREATE DATABASE database_name;``" within your
     database's interactive prompt.
 
-Now, take a second to make sure ``myproject`` is on your Python path. You
-can do this by copying ``myproject`` to Python's ``site-packages`` directory,
-or you can do it by altering the ``PYTHONPATH`` environment variable. See the
-`Python path documentation`_ for more information. If you opt to set the
-``PYTHONPATH`` environment variable, note that you'll need to set it to the
-*parent* directory of ``myproject``. (You can test this by typing
-"import myproject" into the Python interactive prompt.)
+Run the following command to initialize your database with Django's core
+database tables::
 
-Run the following command::
+    python manage.py init
 
-    django-admin.py init --settings=myproject.settings
+If you don't see any errors, it worked.
 
-The ``django-admin.py`` utility generally needs to know which settings module
-you're using. Here, we're doing that by specifying ``settings=`` on the command
-line, but that can get tedious. If you don't want to type ``settings=`` each
-time, you can set the ``DJANGO_SETTINGS_MODULE`` environment variable. Here's
-how you do that in the Bash shell on Unix::
+If you're interested, run the command-line client for your database and type
+``\dt`` (PostgreSQL), ``SHOW TABLES;`` (MySQL), or ``.schema`` (SQLite) to
+display the tables Django created.
 
-    export DJANGO_SETTINGS_MODULE=myproject.settings
+.. admonition:: About those database tables
 
-On Windows, you'd use ``set`` instead::
-
-    set DJANGO_SETTINGS_MODULE=myproject.settings
-
-If you don't see any errors after running ``django-admin.py init``, you know it
-worked. That command initialized your database with Django's core database
-tables. If you're interested, run the command-line client for your database and
-type ``\dt`` (PostgreSQL), ``SHOW TABLES;`` (MySQL), or ``.schema`` (SQLite) to
-display the tables.
-
-.. _`Python path documentation`: http://docs.python.org/tut/node8.html#SECTION008110000000000000000
+    The tables created by ``manage.py init`` are for sessions, authentication
+    and other features Django provides. The next release of Django will have
+    a "lite" version of the ``init`` command that won't install any database
+    tables if you don't want them.
 
 Creating models
 ===============
 
 Now that your environment -- a "project" -- is set up, you're set to start
-doing work. (You won't have to take care of this boring administrative stuff
+doing work. (You won't have to take care of that boring administrative stuff
 again.)
 
-Each application you write in Django -- e.g., a weblog system, a database of
-public records or a simple poll app -- consists of a Python package, somewhere
-on your Python path, that follows a certain convention. Django comes with a
+Each application you write in Django consists of a Python package, somewhere
+on your `Python path`_, that follows a certain convention. Django comes with a
 utility that automatically generates the basic directory structure of an app,
 so you can focus on writing code rather than creating directories.
 
-In this tutorial, we'll create our poll app in the ``myproject/apps``
-directory, for simplicity. As a consequence, the app will be coupled to the
-project -- that is, Python code within the poll app will refer to
-``myproject.apps.polls``. Later in this tutorial, we'll discuss decoupling
-your apps for distribution.
+.. admonition:: Projects vs. apps
 
-To create your app, change into the ``myproject/apps`` directory and type this
-command::
+    What's the difference between a project and an app? An app is a Web
+    application that does something -- e.g., a weblog system, a database of
+    public records or a simple poll app. A project is a collection of
+    configuration and apps for a particular Web site. A project can contain
+    multiple apps. An app can be in multiple projects.
 
-    django-admin.py startapp polls
+In this tutorial, we'll create our poll app in the ``myproject`` directory,
+for simplicity. As a consequence, the app will be coupled to the project --
+that is, Python code within the poll app will refer to ``myproject.polls``.
+Later in this tutorial, we'll discuss decoupling your apps for distribution.
 
-(From now on, this tutorial will leave out the ``--settings`` parameter and
-will assume you've either set your ``DJANGO_SETTINGS_MODULE`` environment
-variable or included the ``--settings`` option in your call to the command.)
+To create your app, make sure you're in the ``myproject`` directory and type
+this command::
 
-That'll create a directory structure like this::
+    python manage.py startapp polls
+
+That'll create a directory ``polls``, which is laid out like this::
 
     polls/
         __init__.py
 Django each Choice is related to a single Poll. Django supports all the common
 database relationships: many-to-ones, many-to-manys and one-to-ones.
 
+.. _`Python path`: http://docs.python.org/tut/node8.html#SECTION008110000000000000000
 .. _DRY Principle: http://c2.com/cgi/wiki?DontRepeatYourself
 
 Activating models
 That small bit of model code gives Django a lot of information. With it, Django
 is able to:
 
-* Create a database schema (``CREATE TABLE`` statements) for this app.
-* Create a Python database-access API for accessing Poll and Choice objects.
+    * Create a database schema (``CREATE TABLE`` statements) for this app.
+    * Create a Python database-access API for accessing Poll and Choice objects.
 
 But first we need to tell our project that the ``polls`` app is installed.
 
 .. admonition:: Philosophy
 
-   Django apps are "pluggable": You can use an app in multiple
-   projects, and you can distribute apps, because they don't have to be tied to
-   a given Django installation.
+    Django apps are "pluggable": You can use an app in multiple projects, and
+    you can distribute apps, because they don't have to be tied to a given
+    Django installation.
 
-Edit the myproject/settings.py file again, and change the ``INSTALLED_APPS``
-setting to include the string "myproject.apps.polls". So it'll look like this::
+Edit the ``settings.py`` file again, and change the ``INSTALLED_APPS`` setting
+to include the string ``'myproject.polls'``. So it'll look like this::
 
     INSTALLED_APPS = (
-        'myproject.apps.polls',
+        'myproject.polls',
     )
 
-(Don't forget the trailing comma because of Python's rules about single-value
-tuples.)
+(Don't forget the trailing comma, because of Python's rule about single-value
+tuples: Without a trailing comma, Python wouldn't know this was a tuple.)
 
-Now Django knows myproject includes the polls app. Let's run another command::
+Now Django knows ``myproject`` includes the ``polls`` app. Let's run another command::
 
-    django-admin.py sql polls
-
-(Note that it doesn't matter which directory you're in when you run this command.)
+    python manage.py sql polls
 
 You should see the following (the CREATE TABLE SQL statements for the polls app)::
 
 Note the following:
 
     * Table names are automatically generated by combining the name of the app
-      (polls) with a plural version of the object name (polls and choices). (You
-      can override this behavior.)
+      (``polls``) with a plural version of the object name (polls and choices).
+      (You can override this behavior.)
 
     * Primary keys (IDs) are added automatically. (You can override this, too.)
 
 
     * The foreign key relationship is made explicit by a ``REFERENCES`` statement.
 
-    * It's tailored to the database you're using, so database-specific field types
-      such as ``auto_increment`` (MySQL), ``serial`` (PostgreSQL), or ``integer
-      primary key`` (SQLite) are handled for you automatically. Same goes for
-      quoting of field names -- e.g., using double quotes or single quotes. The
-      author of this tutorial runs PostgreSQL, so the example output is in
-      PostgreSQL syntax.
+    * It's tailored to the database you're using, so database-specific field
+      types such as ``auto_increment`` (MySQL), ``serial`` (PostgreSQL), or
+      ``integer primary key`` (SQLite) are handled for you automatically. Same
+      goes for quoting of field names -- e.g., using double quotes or single
+      quotes. The author of this tutorial runs PostgreSQL, so the example
+      output is inPostgreSQL syntax.
 
 If you're interested, also run the following commands:
 
-    * ``django-admin.py sqlinitialdata polls`` -- Outputs the initial-data
+    * ``python manage.py sqlinitialdata polls`` -- Outputs the initial-data
       inserts required for Django's admin framework.
 
-    * ``django-admin.py sqlclear polls`` -- Outputs the necessary ``DROP
+    * ``python manage.py sqlclear polls`` -- Outputs the necessary ``DROP
       TABLE`` statements for this app, according to which tables already exist
       in your database (if any).
 
-    * ``django-admin.py sqlindexes polls`` -- Outputs the ``CREATE INDEX``
+    * ``python manage.py sqlindexes polls`` -- Outputs the ``CREATE INDEX``
       statements for this app.
 
-    * ``django-admin.py sqlall polls`` -- A combination of 'sql' and
+    * ``python manage.py sqlall polls`` -- A combination of 'sql' and
       'sqlinitialdata'.
 
 Looking at the output of those commands can help you understand what's actually
 Now, run this command to create the database tables for the polls app
 automatically::
 
-    django-admin.py install polls
+    python manage.py install polls
 
 Behind the scenes, all that command does is take the output of
-``django-admin.py sqlall polls`` and execute it in the database pointed-to by
+``python manage.py sqlall polls`` and execute it in the database pointed-to by
 your Django settings file.
 
-Read the `django-admin.py documentation`_ for full information on what this
-utility can do.
+Read the `django-admin.py documentation`_ for full information on what the
+``manage.py`` utility can do.
 
 .. _django-admin.py documentation: http://www.djangoproject.com/documentation/django_admin/
 
 Playing with the API
 ====================
 
-Now, make sure your DJANGO_SETTINGS_MODULE environment variable is set (as
-explained above), and open the Python interactive shell to play around with the
-free Python API Django gives you::
+Now, let's hop into the interactive Python shell and play around with the free
+API Django gives you. To invoke the Python shell, use this command::
+
+    python manage.py shell
+
+We're using this instead of simply typing "python", because ``manage.py`` sets
+up the project's environment for you. "Setting up the environment" involves two
+things:
+
+    * Putting ``myproject`` on ``sys.path``. For flexibility, several pieces of
+      Django refer to projects in Python dotted-path notation (e.g.
+      ``'myproject.polls.models'``). In order for this to work, the
+      ``myproject`` package has to be on ``sys.path``.
+
+      We've already seen one example of this: the ``INSTALLED_APPS`` setting is
+      a list of packages in dotted-path notation.
+
+    * Setting the ``DJANGO_SETTINGS_MODULE`` environment variable, which gives
+      Django the path to your ``settings.py`` file.
+
+.. admonition:: Bypassing manage.py
+
+    If you'd rather not use ``manage.py``, no problem. Just make sure
+    ``myproject`` is at the root level on the Python path (i.e.,
+    ``import myproject`` works) and set the ``DJANGO_SETTINGS_MODULE``
+    environment variable to ``myproject.settings``.
+
+    For more information on all of this, see the `django-admin.py documentation`_.
+
+Once you're in the shell, explore the database API::
 
     # Modules are dynamically created within django.models.
     # Their names are plural versions of the model class names.
     # Save the object into the database. You have to call save() explicitly.
     >>> p.save()
 
-    # Now it has an ID.
+    # Now it has an ID. Note that this might say "1L" instead of "1", depending
+    # on which database you're using. That's no biggie; it just means your
+    # database backend prefers to return integers as Python long integer
+    # objects.
     >>> p.id
     1
 
 a handful of commonly-used variables for convenience, including the
 ``datetime`` module from the Python standard library.
 
-Let's jump back into the Python interactive shell::
+Let's jump back into the Python interactive shell by running
+``python manage.py shell`` again::
 
     >>> from django.models.polls import polls, choices
     # Make sure our __repr__() addition worked.

docs/tutorial02.txt

 activate the admin site for your installation, do these three things:
 
     * Add ``"django.contrib.admin"`` to your ``INSTALLED_APPS`` setting.
-    * Run the command ``django-admin.py install admin``. This will create an
+    * Run the command ``python manage.py install admin``. This will create an
       extra database table that the admin needs.
     * Edit your ``myproject/urls.py`` file and uncomment the line below
       "Uncomment this for admin:". This file is a URLconf; we'll dig into
 
 Run the following command to create a superuser account for your admin site::
 
-    django-admin.py createsuperuser --settings=myproject.settings
+    python manage.py createsuperuser
 
 The script will prompt you for a username, e-mail address and password (twice).
 
 Start the development server
 ============================
 
-To make things easy, Django comes with a pure-Python Web server that builds on
-the BaseHTTPServer included in Python's standard library. Let's start the
-server and explore the admin site.
+Let's start the development server and explore the admin site.
 
-Just run the following command to start the server::
+Recall from Tutorial 1 that you start the development server like so::
 
-    django-admin.py runserver --settings=myproject.settings
-
-It'll start a Web server running locally -- on port 8000, by default. If you
-want to change the server's port, pass it as a command-line argument::
-
-    django-admin.py runserver 8080 --settings=myproject.settings
-
-DON'T use this server in anything resembling a production environment. It's
-intended only for use while developing.
+    python manage.py runserver
 
 Now, open a Web browser and go to "/admin/" on your local domain -- e.g.,
 http://127.0.0.1:8000/admin/. You should see the admin's login screen:
 
 But where's our poll app? It's not displayed on the admin index page.
 
-Just one thing to do: We need to specify in the ``polls.Poll`` model that Poll
-objects have an admin interface. Edit the ``myproject/apps/polls/models/polls.py``
+Just one thing to do: We need to specify in the ``Poll`` model that ``Poll``
+objects have an admin interface. Edit the ``myproject/polls/models/polls.py``
 file and make the following change to add an inner ``META`` class with an
 ``admin`` attribute::
 
         class META:
             admin = meta.Admin()
 
-The ``class META`` contains all non-field metadata about this model.
+The ``class META`` contains all `non-field metadata`_ about this model.
 
 Now reload the Django admin page to see your changes. Note that you don't have
 to restart the development server -- it auto-reloads code.
 
+.. _non-field metadata: http://www.djangoproject.com/documentation/model_api/#meta-options
+
 Explore the free admin functionality
 ====================================
 
 Adding related objects
 ======================
 
-OK, we have our Poll admin page. But a ``Poll`` has multiple ``Choices``, and the admin
-page doesn't display choices.
+OK, we have our Poll admin page. But a ``Poll`` has multiple ``Choices``, and
+the admin page doesn't display choices.
 
 Yet.
 
-In this case, there are two ways to solve this problem. The first is to give
-the ``Choice`` model its own ``admin`` attribute, just as we did with ``Poll``.
-Here's what that would look like::
+There are two ways to solve this problem. The first is to give the ``Choice``
+model its own ``admin`` attribute, just as we did with ``Poll``. Here's what
+that would look like::
 
     class Choice(meta.Model):
         # ...
    :alt: Choice admin page
 
 In that form, the "Poll" field is a select box containing every poll in the
-database. In our case, only one poll exists at this point.
+database. Django knows that a ``ForeignKey`` should be represented in the admin
+as a ``<select>`` box. In our case, only one poll exists at this point.
 
 Also note the "Add Another" link next to "Poll." Every object with a ForeignKey
 relationship to another gets this for free. When you click "Add Another," you'll
 
 That adds a search box at the top of the change list. When somebody enters
 search terms, Django will search the ``question`` field. You can use as many
-fields as you'd like -- although because it uses a LIKE query behind the
+fields as you'd like -- although because it uses a ``LIKE`` query behind the
 scenes, keep it reasonable, to keep your database happy.
 
 Finally, because Poll objects have dates, it'd be convenient to be able to
 best.
 
 Django offers another shortcut in this department. Run the command
-``django-admin.py adminindex polls`` to get a chunk of template code for
+``python manage.py adminindex polls`` to get a chunk of template code for
 inclusion in the admin index template. It's a useful starting point.
 
 For full details on customizing the look and feel of the Django admin site in

docs/tutorial03.txt

 For more on ``HTTPRequest`` objects, see the `request and response documentation`_.
 For more details on URLconfs, see the `URLconf documentation`_.
 
-When you ran ``django-admin.py startproject myproject`` at the beginning of
+When you ran ``python manage.py startproject myproject`` at the beginning of
 Tutorial 1, it created a default URLconf in ``myproject/urls.py``. It also
 automatically set your ``ROOT_URLCONF`` setting to point at that file::
 
     from django.conf.urls.defaults import *
 
     urlpatterns = patterns('',
-        (r'^polls/$', 'myproject.apps.polls.views.index'),
-        (r'^polls/(?P<poll_id>\d+)/$', 'myproject.apps.polls.views.detail'),
-        (r'^polls/(?P<poll_id>\d+)/results/$', 'myproject.apps.polls.views.results'),
-        (r'^polls/(?P<poll_id>\d+)/vote/$', 'myproject.apps.polls.views.vote'),
+        (r'^polls/$', 'myproject.polls.views.index'),
+        (r'^polls/(\d+)/$', 'myproject.polls.views.detail'),
+        (r'^polls/(\d+)/results/$', 'myproject.polls.views.results'),
+        (r'^polls/(\d+)/vote/$', 'myproject.polls.views.vote'),
     )
 
 This is worth a review. When somebody requests a page from your Web site --
 say, "/polls/23/", Django will load this Python module, because it's pointed to
 by the ``ROOT_URLCONF`` setting. It finds the variable named ``urlpatterns``
 and traverses the regular expressions in order. When it finds a regular
-expression that matches -- ``r'^polls/(?P<poll_id>\d+)/$'`` -- it loads the
-associated Python package/module: ``myproject.apps.polls.views.detail``. That
-corresponds to the function ``detail()`` in ``myproject/apps/polls/views.py``.
+expression that matches -- ``r'^polls/(\d+)/$'`` -- it loads the
+associated Python package/module: ``myproject.polls.views.detail``. That
+corresponds to the function ``detail()`` in ``myproject/polls/views.py``.
 Finally, it calls that ``detail()`` function like so::
 
     detail(request=<HttpRequest object>, poll_id='23')
 
-The ``poll_id='23'`` part comes from ``(?P<poll_id>\d+)``. Using
-``(?P<name>pattern)`` "captures" the text matched by ``pattern`` and sends it
-as a keyword argument to the view function.
+The ``poll_id='23'`` part comes from ``(\d+)``. Using parenthesis around a
+pattern "captures" the text matched by that pattern and sends it as an argument
+to the view function.
 
 Because the URL patterns are regular expressions, there really is no limit on
 what you can do with them. And there's no need to add URL cruft such as
 ``.php`` -- unless you have a sick sense of humor, in which case you can do
 something like this::
 
-    (r'^polls/latest\.php$', 'myproject.apps.polls.views.index'),
+    (r'^polls/latest\.php$', 'myproject.polls.views.index'),
 
 But, don't do that. It's silly.
 
 
 Fire up the Django development Web server::
 
-    django-admin.py runserver --settings=myproject.settings
+    python manage.py runserver
 
 Now go to "http://localhost:8000/polls/" on your domain in your Web browser.
 You should get a pleasantly-colored error page with the following message::
 
     ViewDoesNotExist at /polls/
 
-    Tried index in module myproject.apps.polls.views. Error was: 'module'
+    Tried index in module myproject.polls.views. Error was: 'module'
     object has no attribute 'index'
 
 This error happened because you haven't written a function ``index()`` in the
-module ``myproject/apps/polls/views.py``.
+module ``myproject/polls/views.py``.
 
 Try "/polls/23/", "/polls/23/results/" and "/polls/23/vote/". The error
 messages tell you which view Django tried (and failed to find, because you
 haven't written any views yet).
 
-Time to write the first view. Open the file ``myproject/apps/polls/views.py``
+Time to write the first view. Open the file ``myproject/polls/views.py``
 and put the following Python code in it::
 
     from django.utils.httpwrappers import HttpResponse
 your server runs.) Don't put them under your document root, though. You
 probably shouldn't make them public, just for security's sake.
 
-Then edit ``TEMPLATE_DIRS`` in your settings file (``settings.py``) to tell
-Django where it can find templates -- just as you did in the "Customize the
-admin look and feel" section of Tutorial 2.
+Then edit ``TEMPLATE_DIRS`` in your ``settings.py`` to tell Django where it can
+find templates -- just as you did in the "Customize the admin look and feel"
+section of Tutorial 2.
 
 When you've done that, create a directory ``polls`` in your template directory.
 Within that, create a file called ``index.html``. Django requires that
 the URLconf, you may notice there's a fair bit of redundancy in it::
 
     urlpatterns = patterns('',
-        (r'^polls/$', 'myproject.apps.polls.views.index'),
-        (r'^polls/(?P<poll_id>\d+)/$', 'myproject.apps.polls.views.detail'),
-        (r'^polls/(?P<poll_id>\d+)/results/$', 'myproject.apps.polls.views.results'),
-        (r'^polls/(?P<poll_id>\d+)/vote/$', 'myproject.apps.polls.views.vote'),
+        (r'^polls/$', 'myproject.polls.views.index'),
+        (r'^polls/(?P<poll_id>\d+)/$', 'myproject.polls.views.detail'),
+        (r'^polls/(?P<poll_id>\d+)/results/$', 'myproject.polls.views.results'),
+        (r'^polls/(?P<poll_id>\d+)/vote/$', 'myproject.polls.views.vote'),
     )
 
-Namely, ``myproject.apps.polls.views`` is in every callback.
+Namely, ``myproject.polls.views`` is in every callback.
 
 Because this is a common case, the URLconf framework provides a shortcut for
 common prefixes. You can factor out the common prefixes and add them as the
 first argument to ``patterns()``, like so::
 
-    urlpatterns = patterns('myproject.apps.polls.views',
+    urlpatterns = patterns('myproject.polls.views',
         (r'^polls/$', 'index'),
         (r'^polls/(?P<poll_id>\d+)/$', 'detail'),
         (r'^polls/(?P<poll_id>\d+)/results/$', 'results'),
 with minimal fuss.
 
 Our poll app is pretty decoupled at this point, thanks to the strict directory
-structure that ``django-admin.py startapp`` created, but one part of it is
+structure that ``python manage.py startapp`` created, but one part of it is
 coupled to the Django settings: The URLconf.
 
 We've been editing the URLs in ``myproject/urls.py``, but the URL design of an
 app is specific to the app, not to the Django installation -- so let's move the
 URLs within the app directory.
 
-Copy the file ``myproject/urls.py`` to ``myproject/apps/polls/urls.py``. Then,
+Copy the file ``myproject/urls.py`` to ``myproject/polls/urls.py``. Then,
 change ``myproject/urls.py`` to remove the poll-specific URLs and insert an
 ``include()``::
 
-    (r'^polls/', include('myproject.apps.polls.urls')),
+    (r'^polls/', include('myproject.polls.urls')),
 
 ``include()``, simply, references another URLconf. Note that the regular
 expression doesn't have a ``$`` (end-of-string match character) but has the
 
 * Django will find the match at ``'^polls/'``
 * It will strip off the matching text (``"polls/"``) and send the remaining
-  text -- ``"34/"`` -- to the 'myproject.apps.polls.urls' urlconf for
+  text -- ``"34/"`` -- to the 'myproject.polls.urls' urlconf for
   further processing.
 
 Now that we've decoupled that, we need to decouple the
-'myproject.apps.polls.urls' urlconf by removing the leading "polls/" from each
+'myproject.polls.urls' urlconf by removing the leading "polls/" from each
 line::
 
-    urlpatterns = patterns('myproject.apps.polls.views',
+    urlpatterns = patterns('myproject.polls.views',
         (r'^$', 'index'),
         (r'^(?P<poll_id>\d+)/$', 'detail'),
         (r'^(?P<poll_id>\d+)/results/$', 'results'),

docs/tutorial04.txt

 something with it. Remember, in `Tutorial 3`_, we create a URLconf that
 included this line::
 
-    (r'^polls/(?P<poll_id>\d+)/vote/$', 'myproject.apps.polls.views.vote'),
+    (r'^polls/(?P<poll_id>\d+)/vote/$', 'myproject.polls.views.vote'),
 
-So let's create a ``vote()`` function in ``myproject/apps/polls/views.py``::
+So let's create a ``vote()`` function in ``myproject/polls/views.py``::
 
     from django.core.extensions import get_object_or_404, render_to_response
     from django.models.polls import choices, polls
 
     from django.conf.urls.defaults import *
 
-    urlpatterns = patterns('myproject.apps.polls.views',
+    urlpatterns = patterns('myproject.polls.views',
         (r'^$', 'index'),
         (r'^(?P<poll_id>\d+)/$', 'detail'),
         (r'^(?P<poll_id>\d+)/results/$', 'results'),
         (r'^$', 'django.views.generic.list_detail.object_list', info_dict),
         (r'^(?P<object_id>\d+)/$', 'django.views.generic.list_detail.object_detail', info_dict),
         (r'^(?P<object_id>\d+)/results/$', 'django.views.generic.list_detail.object_detail', dict(info_dict, template_name='polls/results')),
-        (r'^(?P<poll_id>\d+)/vote/$', 'myproject.apps.polls.views.vote'),
+        (r'^(?P<poll_id>\d+)/vote/$', 'myproject.polls.views.vote'),
     )
 
 We're using two generic views here: ``object_list`` and ``object_detail``.
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.