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:
parent
d6ba2d477c
commit
39d42d4861
@ -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.
|
||||
* 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()
|
||||
|
@ -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.
|
||||
|
||||
|
@ -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'),
|
||||
|
@ -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``.
|
||||
|
Loading…
x
Reference in New Issue
Block a user