1
0
mirror of https://github.com/django/django.git synced 2025-07-04 17:59:13 +00:00

magic-removal: Began to refactor tutorial

git-svn-id: http://code.djangoproject.com/svn/django/branches/magic-removal@2699 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Adrian Holovaty 2006-04-15 15:56:12 +00:00
parent d6ba2d477c
commit 39d42d4861
4 changed files with 89 additions and 83 deletions

View File

@ -2,8 +2,6 @@
Writing your first Django app, part 1
=====================================
By Adrian Holovaty <holovaty@gmail.com>
Let's learn by example.
Throughout this tutorial, we'll walk you through the creation of a basic
@ -11,26 +9,34 @@ blogging application.
It'll consist of two parts:
* A public site that lets people read your blog entries and submit comments.
* A public site that lets people read your blog entries and submit
comments.
* An admin site that lets you add, change and delete entries and comments.
We'll assume you have `Django installed`_ already.
We'll assume you have `Django installed`_ already. You can tell Django is
installed by running the Python interactive interpreter and typing
``import django``. If that command runs successfully, with no errors, Django is
installed.
.. _`Django installed`: http://www.djangoproject.com/documentation/install/
Initial setup
=============
Creating a project
==================
If this is your first time using Django, you'll have to take care of some
initial setup.
initial setup. Namely, you'll need to auto-generate some code that establishes
a Django *project* -- a collection of settings for an instance of Django,
including database configuration, Django-specific options and
application-specific settings.
Run the command ``django-admin.py startproject myproject``. This will create a
``myproject`` directory in your current directory.
From the command line, ``cd`` into a directory where you'd like to store your
code, then run the command ``django-admin.py startproject mysite``. This
will create a ``mysite`` directory in your current directory.
(``django-admin.py`` 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
its ``setup.py`` utility. If it's not on your path, you can find it in
``site-packages/django/bin``; consider symlinking to it from some place
on your path, such as /usr/local/bin.)
on your path, such as ``/usr/local/bin``.)
.. admonition:: Where should this code live?
@ -44,11 +50,9 @@ on your path, such as /usr/local/bin.)
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
settings. Let's look at what ``startproject`` created::
Let's look at what ``startproject`` created::
myproject/
mysite/
__init__.py
manage.py
settings.py
@ -65,25 +69,29 @@ These files are:
The development server
----------------------
Let's verify this worked. Change into the ``myproject`` directory, if you
Let's verify this worked. Change into the ``mysite`` 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.
Django version 0.92, using settings 'myproject.settings'
Django version 0.92, using settings 'mysite.settings'
Development server is running at http://127.0.0.1:8000/
Quit the server with CONTROL-C (Unix) or CTRL-BREAK (Windows).
You've started the Django development server, a lightweight, pure-Python Web
server. 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.
without having to deal with configuring a production server -- such as
Apache -- until you're ready for production.
Now's a good time to note: DON'T use this server in anything resembling a
production environment. It's intended only for use while developing.
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!
.. admonition:: Changing the port
By default, the ``runserver`` command starts the development server on port
@ -94,12 +102,16 @@ production environment. It's intended only for use while developing.
Full docs for the development server are at `django-admin documentation`_.
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!
.. django-admin documentation: http://www.djangoproject.com/documentation/django_admin/
Your first page
---------------
Let's create our first Django-powered Web page, a classic "hello world" example.
Database setup
--------------
@ -183,12 +195,12 @@ 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 ``myproject`` directory,
In this tutorial, we'll create our poll app in the ``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 ``myproject.polls``.
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.
To create your app, make sure you're in the ``myproject`` directory and type
To create your app, make sure you're in the ``mysite`` directory and type
this command::
python manage.py startapp polls
@ -278,17 +290,17 @@ But first we need to tell our project that the ``polls`` app is installed.
Django installation.
Edit the ``settings.py`` file again, and change the ``INSTALLED_APPS`` setting
to include the string ``'myproject.polls'``. So it'll look like this::
to include the string ``'mysite.polls'``. So it'll look like this::
INSTALLED_APPS = (
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
'myproject.polls'
'mysite.polls'
)
Now Django knows ``myproject`` includes the ``polls`` app. Let's run another command::
Now Django knows ``mysite`` includes the ``polls`` app. Let's run another command::
python manage.py sql polls
@ -379,10 +391,10 @@ 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
* Putting ``mysite`` 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``.
``'mysite.polls.models'``). In order for this to work, the
``mysite`` 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.
@ -393,16 +405,16 @@ things:
.. 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``.
``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``.
For more information on all of this, see the `django-admin.py documentation`_.
Once you're in the shell, explore the database API::
# Import the model classes we just wrote.
>>> from myproject.polls.models import Poll, Choice
>>> from mysite.polls.models import Poll, Choice
# No polls are in the system yet.
>>> Poll.objects.all()
@ -472,7 +484,7 @@ Note the addition of ``import datetime`` to reference Python's standard
Let's jump back into the Python interactive shell by running
``python manage.py shell`` again::
>>> from myproject.polls.models import Poll, Choice
>>> from mysite.polls.models import Poll, Choice
# Make sure our __repr__() addition worked.
>>> Poll.objects.all()

View File

@ -2,8 +2,6 @@
Writing your first Django app, part 2
=====================================
By Adrian Holovaty <holovaty@gmail.com>
This tutorial begins where `Tutorial 1`_ left off. We're continuing the Web-poll
application and will focus on Django's automatically-generated admin site.
@ -33,7 +31,7 @@ activate the admin site for your installation, do these three things:
* Add ``"django.contrib.admin"`` to your ``INSTALLED_APPS`` setting.
* Run ``python manage.py syncdb``. Since you have added a new application
to ``INSTALLED_APPS``, the database tables need to be updated.
* Edit your ``myproject/urls.py`` file and uncomment the line below
* Edit your ``mysite/urls.py`` file and uncomment the line below
"Uncomment this for admin:". This file is a URLconf; we'll dig into
URLconfs in the next tutorial. For now, all you need to know is that it
maps URL roots to applications.
@ -73,7 +71,7 @@ Make the poll app modifiable in the admin
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 ``Poll`` model that ``Poll``
objects have an admin interface. Edit the ``myproject/polls/models/polls.py``
objects have an admin interface. Edit the ``mysite/polls/models/polls.py``
file and make the following change to add an inner ``Admin`` class::
class Poll(models.Model):
@ -370,7 +368,7 @@ That's easy to change, though, using Django's template system. The Django admin
is powered by Django itself, and its interfaces use Django's own template
system. (How meta!)
Open your settings file (``myproject/settings.py``, remember) and look at the
Open your settings file (``mysite/settings.py``, remember) and look at the
``TEMPLATE_DIRS`` setting. ``TEMPLATE_DIRS`` is a tuple of filesystem
directories to check when loading Django templates. It's a search path.

View File

@ -2,8 +2,6 @@
Writing your first Django app, part 3
=====================================
By Adrian Holovaty <holovaty@gmail.com>
This tutorial begins where `Tutorial 2`_ left off. We're continuing the Web-poll
application and will focus on creating the public interface -- "views."
@ -62,21 +60,21 @@ arguments from the dictionary (an optional third item in the tuple).
For more on ``HTTPRequest`` objects, see the `request and response documentation`_.
For more details on URLconfs, see the `URLconf documentation`_.
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
When you ran ``python manage.py startproject mysite`` at the beginning of
Tutorial 1, it created a default URLconf in ``mysite/urls.py``. It also
automatically set your ``ROOT_URLCONF`` setting to point at that file::
ROOT_URLCONF = 'myproject.urls'
ROOT_URLCONF = 'mysite.urls'
Time for an example. Edit ``myproject/urls.py`` so it looks like this::
Time for an example. Edit ``mysite/urls.py`` so it looks like this::
from django.conf.urls.defaults import *
urlpatterns = patterns('',
(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'),
(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'),
)
This is worth a review. When somebody requests a page from your Web site --
@ -84,8 +82,8 @@ 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.polls.views.detail``. That
corresponds to the function ``detail()`` in ``myproject/polls/views.py``.
associated Python package/module: ``mysite.polls.views.detail``. That
corresponds to the function ``detail()`` in ``mysite/polls/views.py``.
Finally, it calls that ``detail()`` function like so::
detail(request=<HttpRequest object>, poll_id='23')
@ -101,7 +99,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$', 'myproject.polls.views.index'),
(r'^polls/latest\.php$', 'mysite.polls.views.index'),
But, don't do that. It's silly.
@ -137,17 +135,17 @@ You should get a pleasantly-colored error page with the following message::
ViewDoesNotExist at /polls/
Tried index in module myproject.polls.views. Error was: 'module'
Tried index in module mysite.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/polls/views.py``.
module ``mysite/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/polls/views.py``
Time to write the first view. Open the file ``mysite/polls/views.py``
and put the following Python code in it::
from django.http import HttpResponse
@ -187,7 +185,7 @@ in Tutorial 1. 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 myproject.polls.models import Poll
from mysite.polls.models import Poll
from django.http import HttpResponse
def index(request):
@ -200,7 +198,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 myproject.polls.models import Poll
from mysite.polls.models import Poll
from django.http import HttpResponse
def index(request):
@ -257,7 +255,7 @@ It's a very common idiom to load a template, fill a context and return an
provides a shortcut. Here's the full ``index()`` view, rewritten::
from django.shortcuts import render_to_response
from myproject.polls.models import Poll
from mysite.polls.models import Poll
def index(request):
latest_poll_list = Poll.objects.all().order_by('-pub_date')
@ -389,19 +387,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/$', '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'),
(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'),
)
Namely, ``myproject.polls.views`` is in every callback.
Namely, ``mysite.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.polls.views',
urlpatterns = patterns('mysite.polls.views',
(r'^polls/$', 'index'),
(r'^polls/(?P<poll_id>\d+)/$', 'detail'),
(r'^polls/(?P<poll_id>\d+)/results/$', 'results'),
@ -423,15 +421,15 @@ Our poll app is pretty decoupled at this point, thanks to the strict directory
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
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 ``myproject/urls.py`` to ``myproject/polls/urls.py``. Then,
change ``myproject/urls.py`` to remove the poll-specific URLs and insert an
Copy the file ``mysite/urls.py`` to ``mysite/polls/urls.py``. Then,
change ``mysite/urls.py`` to remove the poll-specific URLs and insert an
``include()``::
(r'^polls/', include('myproject.polls.urls')),
(r'^polls/', include('mysite.polls.urls')),
``include()``, simply, references another URLconf. Note that the regular
expression doesn't have a ``$`` (end-of-string match character) but has the
@ -443,14 +441,14 @@ Here's what happens if a user goes to "/polls/34/" in this system:
* Django will find the match at ``'^polls/'``
* It will strip off the matching text (``"polls/"``) and send the remaining
text -- ``"34/"`` -- to the 'myproject.polls.urls' urlconf for
text -- ``"34/"`` -- to the 'mysite.polls.urls' urlconf for
further processing.
Now that we've decoupled that, we need to decouple the
'myproject.polls.urls' urlconf by removing the leading "polls/" from each
'mysite.polls.urls' urlconf by removing the leading "polls/" from each
line::
urlpatterns = patterns('myproject.polls.views',
urlpatterns = patterns('mysite.polls.views',
(r'^$', 'index'),
(r'^(?P<poll_id>\d+)/$', 'detail'),
(r'^(?P<poll_id>\d+)/results/$', 'results'),

View File

@ -2,8 +2,6 @@
Writing your first Django app, part 4
=====================================
By Adrian Holovaty <holovaty@gmail.com>
This tutorial begins where `Tutorial 3`_ left off. We're continuing the Web-poll
application and will focus on simple form processing and cutting down our code.
@ -44,13 +42,13 @@ Now, let's create a Django view that handles the submitted data and does
something with it. Remember, in `Tutorial 3`_, we create a URLconf for the
polls application that includes this line::
(r'^(?P<poll_id>\d+)/vote/$', 'myproject.polls.views.vote'),
(r'^(?P<poll_id>\d+)/vote/$', 'mysite.polls.views.vote'),
So let's create a ``vote()`` function in ``myproject/polls/views.py``::
So let's create a ``vote()`` function in ``mysite/polls/views.py``::
from django.shortcuts import get_object_or_404, render_to_response
from django.http import Http404,HttpResponseRedirect
from myproject.polls.models import Choice, Poll
from mysite.polls.models import Choice, Poll
# ...
def vote(request, poll_id):
p = get_object_or_404(Poll, pk=poll_id)
@ -158,7 +156,7 @@ so far::
from django.conf.urls.defaults import *
urlpatterns = patterns('myproject.polls.views',
urlpatterns = patterns('mysite.polls.views',
(r'^$', 'index'),
(r'^(?P<poll_id>\d+)/$', 'detail'),
(r'^(?P<poll_id>\d+)/results/$', 'results'),
@ -168,7 +166,7 @@ so far::
Change it like so::
from django.conf.urls.defaults import *
from myproject.polls.models import Poll
from mysite.polls.models import Poll
info_dict = {
'queryset': Poll.objects.all(),
@ -178,7 +176,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),
(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.polls.views.vote'),
(r'^(?P<poll_id>\d+)/vote/$', 'mysite.polls.views.vote'),
)
We're using two generic views here: ``object_list`` and ``object_detail``.