[1.2.X] Fixed #14255 -- factor project name out of app imports in tutorial. Thanks to adamend for the report and initial patch.

Backport of r14066 from trunk.


git-svn-id: http://code.djangoproject.com/svn/django/branches/releases/1.2.X@14067 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Simon Meers 2010-10-09 07:48:09 +00:00
parent b2bd6c9d56
commit 824ca0d6e5
4 changed files with 44 additions and 46 deletions

View File

@ -268,10 +268,8 @@ so you can focus on writing code rather than creating directories.
configuration and apps for a particular Web site. A project can contain
multiple apps. An app can be in multiple projects.
In this tutorial, we'll create our poll app in the :file:`mysite` 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 ``mysite.polls``.
Later in this tutorial, we'll discuss decoupling your apps for distribution.
Your apps can live anywhere on your `Python path`_. In this tutorial we will
create our poll app in the :file:`mysite` directory for simplicity.
To create your app, make sure you're in the :file:`mysite` directory and type
this command:
@ -369,7 +367,7 @@ But first we need to tell our project that the ``polls`` app is installed.
Django installation.
Edit the :file:`settings.py` file again, and change the
:setting:`INSTALLED_APPS` setting to include the string ``'mysite.polls'``. So
:setting:`INSTALLED_APPS` setting to include the string ``'polls'``. So
it'll look like this::
INSTALLED_APPS = (
@ -377,10 +375,10 @@ it'll look like this::
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
'mysite.polls'
'polls'
)
Now Django knows ``mysite`` includes the ``polls`` app. Let's run another
Now Django knows to include the ``polls`` app. Let's run another
command:
.. code-block:: bash
@ -488,9 +486,9 @@ 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 ``mysite`` on ``sys.path``. For flexibility, several pieces of
* Putting ``polls`` on ``sys.path``. For flexibility, several pieces of
Django refer to projects in Python dotted-path notation (e.g.
``'mysite.polls.models'``). In order for this to work, the ``mysite``
``'polls.models'``). In order for this to work, the ``polls``
package has to be on ``sys.path``.
We've already seen one example of this: the :setting:`INSTALLED_APPS`
@ -502,16 +500,16 @@ things:
.. admonition:: Bypassing manage.py
If you'd rather not use ``manage.py``, no problem. Just make sure ``mysite``
is at the root level on the Python path (i.e., ``import mysite`` works) and
set the ``DJANGO_SETTINGS_MODULE`` environment variable to
``mysite.settings``.
and ``polls`` are at the root level on the Python path (i.e., ``import mysite``
and ``import polls`` work) and set the ``DJANGO_SETTINGS_MODULE`` environment
variable to ``mysite.settings``.
For more information on all of this, see the :doc:`django-admin.py
documentation </ref/django-admin>`.
Once you're in the shell, explore the :doc:`database API </topics/db/queries>`::
>>> from mysite.polls.models import Poll, Choice # Import the model classes we just wrote.
>>> from polls.models import Poll, Choice # Import the model classes we just wrote.
# No polls are in the system yet.
>>> Poll.objects.all()
@ -619,7 +617,7 @@ Note the addition of ``import datetime`` to reference Python's standard
Save these changes and start a new Python interactive shell by running
``python manage.py shell`` again::
>>> from mysite.polls.models import Poll, Choice
>>> from polls.models import Poll, Choice
# Make sure our __unicode__() addition worked.
>>> Poll.objects.all()

View File

@ -103,7 +103,7 @@ Just one thing to do: We need to tell the admin that ``Poll``
objects have an admin interface. To do this, create a file called
``admin.py`` in your ``polls`` directory, and edit it to look like this::
from mysite.polls.models import Poll
from polls.models import Poll
from django.contrib import admin
admin.site.register(Poll)
@ -239,7 +239,7 @@ Yet.
There are two ways to solve this problem. The first is to register ``Choice``
with the admin just as we did with ``Poll``. That's easy::
from mysite.polls.models import Choice
from polls.models import Choice
admin.site.register(Choice)

View File

@ -84,10 +84,10 @@ Time for an example. Edit ``mysite/urls.py`` so it looks like this::
admin.autodiscover()
urlpatterns = patterns('',
(r'^polls/$', 'mysite.polls.views.index'),
(r'^polls/(?P<poll_id>\d+)/$', 'mysite.polls.views.detail'),
(r'^polls/(?P<poll_id>\d+)/results/$', 'mysite.polls.views.results'),
(r'^polls/(?P<poll_id>\d+)/vote/$', 'mysite.polls.views.vote'),
(r'^polls/$', 'polls.views.index'),
(r'^polls/(?P<poll_id>\d+)/$', 'polls.views.detail'),
(r'^polls/(?P<poll_id>\d+)/results/$', 'polls.views.results'),
(r'^polls/(?P<poll_id>\d+)/vote/$', 'polls.views.vote'),
(r'^admin/', include(admin.site.urls)),
)
@ -96,8 +96,8 @@ This is worth a review. When somebody requests a page from your Web site -- say,
the :setting:`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
function ``detail()`` from ``mysite/polls/views.py``. Finally,
it calls that ``detail()`` function like so::
function ``detail()`` from ``polls/views.py``. Finally, it calls that
``detail()`` function like so::
detail(request=<HttpRequest object>, poll_id='23')
@ -112,7 +112,7 @@ 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$', 'mysite.polls.views.index'),
(r'^polls/latest\.php$', 'polls.views.index'),
But, don't do that. It's silly.
@ -148,17 +148,17 @@ You should get a pleasantly-colored error page with the following message::
ViewDoesNotExist at /polls/
Tried index in module mysite.polls.views. Error was: 'module'
Tried index in module polls.views. Error was: 'module'
object has no attribute 'index'
This error happened because you haven't written a function ``index()`` in the
module ``mysite/polls/views.py``.
module ``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 ``mysite/polls/views.py``
Time to write the first view. Open the file ``polls/views.py``
and put the following Python code in it::
from django.http import HttpResponse
@ -207,7 +207,7 @@ in :doc:`Tutorial 1 </intro/tutorial01>`. Here's one stab at the ``index()``
view, which displays the latest 5 poll questions in the system, separated by
commas, according to publication date::
from mysite.polls.models import Poll
from polls.models import Poll
from django.http import HttpResponse
def index(request):
@ -220,7 +220,7 @@ you want to change the way the page looks, you'll have to edit this Python code.
So let's use Django's template system to separate the design from Python::
from django.template import Context, loader
from mysite.polls.models import Poll
from polls.models import Poll
from django.http import HttpResponse
def index(request):
@ -279,7 +279,7 @@ template. Django provides a shortcut. Here's the full ``index()`` view,
rewritten::
from django.shortcuts import render_to_response
from mysite.polls.models import Poll
from polls.models import Poll
def index(request):
latest_poll_list = Poll.objects.all().order_by('-pub_date')[:5]
@ -432,19 +432,19 @@ Take some time to play around with the views and template system. As you edit
the URLconf, you may notice there's a fair bit of redundancy in it::
urlpatterns = patterns('',
(r'^polls/$', 'mysite.polls.views.index'),
(r'^polls/(?P<poll_id>\d+)/$', 'mysite.polls.views.detail'),
(r'^polls/(?P<poll_id>\d+)/results/$', 'mysite.polls.views.results'),
(r'^polls/(?P<poll_id>\d+)/vote/$', 'mysite.polls.views.vote'),
(r'^polls/$', 'polls.views.index'),
(r'^polls/(?P<poll_id>\d+)/$', 'polls.views.detail'),
(r'^polls/(?P<poll_id>\d+)/results/$', 'polls.views.results'),
(r'^polls/(?P<poll_id>\d+)/vote/$', 'polls.views.vote'),
)
Namely, ``mysite.polls.views`` is in every callback.
Namely, ``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 :func:`~django.conf.urls.defaults.patterns`, like so::
urlpatterns = patterns('mysite.polls.views',
urlpatterns = patterns('polls.views',
(r'^polls/$', 'index'),
(r'^polls/(?P<poll_id>\d+)/$', 'detail'),
(r'^polls/(?P<poll_id>\d+)/results/$', 'results'),
@ -470,7 +470,7 @@ We've been editing the URLs in ``mysite/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 ``mysite/urls.py`` to ``mysite/polls/urls.py``. Then, change
Copy the file ``mysite/urls.py`` to ``polls/urls.py``. Then, change
``mysite/urls.py`` to remove the poll-specific URLs and insert an
:func:`~django.conf.urls.defaults.include`::
@ -479,7 +479,7 @@ Copy the file ``mysite/urls.py`` to ``mysite/polls/urls.py``. Then, change
# ...
urlpatterns = patterns('',
(r'^polls/', include('mysite.polls.urls')),
(r'^polls/', include('polls.urls')),
# ...
)
@ -495,14 +495,14 @@ Here's what happens if a user goes to "/polls/34/" in this system:
* Django will find the match at ``'^polls/'``
* Then, Django will strip off the matching text (``"polls/"``) and send the
remaining text -- ``"34/"`` -- to the 'mysite.polls.urls' URLconf for
remaining text -- ``"34/"`` -- to the 'polls.urls' URLconf for
further processing.
Now that we've decoupled that, we need to decouple the 'mysite.polls.urls'
Now that we've decoupled that, we need to decouple the 'polls.urls'
URLconf by removing the leading "polls/" from each line, and removing the
lines registering the admin site::
urlpatterns = patterns('mysite.polls.views',
urlpatterns = patterns('polls.views',
(r'^$', 'index'),
(r'^(?P<poll_id>\d+)/$', 'detail'),
(r'^(?P<poll_id>\d+)/results/$', 'results'),

View File

@ -74,13 +74,13 @@ created a URLconf for the polls application that includes this line::
(r'^(?P<poll_id>\d+)/vote/$', 'vote'),
We also created a dummy implementation of the ``vote()`` function. Let's
create a real version. Add the following to ``mysite/polls/views.py``::
create a real version. Add the following to ``polls/views.py``::
from django.shortcuts import get_object_or_404, render_to_response
from django.http import HttpResponseRedirect, HttpResponse
from django.core.urlresolvers import reverse
from django.template import RequestContext
from mysite.polls.models import Choice, Poll
from polls.models import Choice, Poll
# ...
def vote(request, poll_id):
p = get_object_or_404(Poll, pk=poll_id)
@ -98,7 +98,7 @@ create a real version. Add the following to ``mysite/polls/views.py``::
# Always return an HttpResponseRedirect after successfully dealing
# with POST data. This prevents data from being posted twice if a
# user hits the Back button.
return HttpResponseRedirect(reverse('mysite.polls.views.results', args=(p.id,)))
return HttpResponseRedirect(reverse('polls.views.results', args=(p.id,)))
This code includes a few things we haven't covered yet in this tutorial:
@ -222,7 +222,7 @@ tutorial so far::
from django.conf.urls.defaults import *
urlpatterns = patterns('mysite.polls.views',
urlpatterns = patterns('polls.views',
(r'^$', 'index'),
(r'^(?P<poll_id>\d+)/$', 'detail'),
(r'^(?P<poll_id>\d+)/results/$', 'results'),
@ -232,7 +232,7 @@ tutorial so far::
Change it like so::
from django.conf.urls.defaults import *
from mysite.polls.models import Poll
from polls.models import Poll
info_dict = {
'queryset': Poll.objects.all(),
@ -242,7 +242,7 @@ Change it like so::
(r'^$', 'django.views.generic.list_detail.object_list', info_dict),
(r'^(?P<object_id>\d+)/$', 'django.views.generic.list_detail.object_detail', info_dict),
url(r'^(?P<object_id>\d+)/results/$', 'django.views.generic.list_detail.object_detail', dict(info_dict, template_name='polls/results.html'), 'poll_results'),
(r'^(?P<poll_id>\d+)/vote/$', 'mysite.polls.views.vote'),
(r'^(?P<poll_id>\d+)/vote/$', 'polls.views.vote'),
)
We're using two generic views here: