From 39d42d48618efbb5e5176a8b65b635a84bed45a5 Mon Sep 17 00:00:00 2001 From: Adrian Holovaty Date: Sat, 15 Apr 2006 15:56:12 +0000 Subject: [PATCH] magic-removal: Began to refactor tutorial git-svn-id: http://code.djangoproject.com/svn/django/branches/magic-removal@2699 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- docs/tutorial01.txt | 88 +++++++++++++++++++++++++-------------------- docs/tutorial02.txt | 8 ++--- docs/tutorial03.txt | 62 ++++++++++++++++---------------- docs/tutorial04.txt | 14 ++++---- 4 files changed, 89 insertions(+), 83 deletions(-) diff --git a/docs/tutorial01.txt b/docs/tutorial01.txt index 22b099714f..f91d678c8f 100644 --- a/docs/tutorial01.txt +++ b/docs/tutorial01.txt @@ -2,8 +2,6 @@ Writing your first Django app, part 1 ===================================== -By Adrian Holovaty - 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. -* An admin site that lets you add, change and delete entries and 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() diff --git a/docs/tutorial02.txt b/docs/tutorial02.txt index 3b7060a52c..6cdda32fbb 100644 --- a/docs/tutorial02.txt +++ b/docs/tutorial02.txt @@ -2,8 +2,6 @@ Writing your first Django app, part 2 ===================================== -By Adrian Holovaty - 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. diff --git a/docs/tutorial03.txt b/docs/tutorial03.txt index 5855a7d6b2..993c09c83d 100644 --- a/docs/tutorial03.txt +++ b/docs/tutorial03.txt @@ -2,8 +2,6 @@ Writing your first Django app, part 3 ===================================== -By Adrian Holovaty - 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\d+)/$', 'myproject.polls.views.detail'), - (r'^polls/(?P\d+)/results/$', 'myproject.polls.views.results'), - (r'^polls/(?P\d+)/vote/$', 'myproject.polls.views.vote'), + (r'^polls/$', 'mysite.polls.views.index'), + (r'^polls/(?P\d+)/$', 'mysite.polls.views.detail'), + (r'^polls/(?P\d+)/results/$', 'mysite.polls.views.results'), + (r'^polls/(?P\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\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=, 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\d+)/$', 'myproject.polls.views.detail'), - (r'^polls/(?P\d+)/results/$', 'myproject.polls.views.results'), - (r'^polls/(?P\d+)/vote/$', 'myproject.polls.views.vote'), + (r'^polls/$', 'mysite.polls.views.index'), + (r'^polls/(?P\d+)/$', 'mysite.polls.views.detail'), + (r'^polls/(?P\d+)/results/$', 'mysite.polls.views.results'), + (r'^polls/(?P\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\d+)/$', 'detail'), (r'^polls/(?P\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\d+)/$', 'detail'), (r'^(?P\d+)/results/$', 'results'), diff --git a/docs/tutorial04.txt b/docs/tutorial04.txt index 7dd9943ac9..5cf23a5f5d 100644 --- a/docs/tutorial04.txt +++ b/docs/tutorial04.txt @@ -2,8 +2,6 @@ Writing your first Django app, part 4 ===================================== -By Adrian Holovaty - 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\d+)/vote/$', 'myproject.polls.views.vote'), + (r'^(?P\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\d+)/$', 'detail'), (r'^(?P\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\d+)/$', 'django.views.generic.list_detail.object_detail', info_dict), (r'^(?P\d+)/results/$', 'django.views.generic.list_detail.object_detail', dict(info_dict, template_name='polls/results')), - (r'^(?P\d+)/vote/$', 'myproject.polls.views.vote'), + (r'^(?P\d+)/vote/$', 'mysite.polls.views.vote'), ) We're using two generic views here: ``object_list`` and ``object_detail``.