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

magic-removal: Fixes #1599, Refs #1464 -- Updated all tutorials for new syntax, changes in manage.py, etc.

git-svn-id: http://code.djangoproject.com/svn/django/branches/magic-removal@2632 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Russell Keith-Magee 2006-04-08 08:33:52 +00:00
parent 218035c3e1
commit d1083f15fb
4 changed files with 102 additions and 92 deletions

View File

@ -24,7 +24,7 @@ Initial setup
If this is your first time using Django, you'll have to take care of some
initial setup.
Run the command ``django-admin.py startproject myproject``. That'll create a
Run the command ``django-admin.py startproject myproject``. This will create a
``myproject`` directory in your current directory.
(``django-admin.py`` should be on your system path if you installed Django via
@ -125,9 +125,10 @@ database's connection parameters:
database's interactive prompt.
While you're editing ``settings.py``, take note of the ``INSTALLED_APPS``
setting. That variable holds the names of all Django applications that are
activated in this Django instance. Apps can be used in multiple projects,
and you can distribute them.
setting towards the bottom of the file. That variable holds the names of all
Django applications that are activated in this Django instance. Apps can be
used in multiple projects, and you can package and distribute them for use
by others in their projects.
By default, ``INSTALLED_APPS`` contains the following apps, all of which come
with Django::
@ -285,12 +286,9 @@ to include the string ``'myproject.polls'``. So it'll look like this::
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
'myproject.polls',
'myproject.polls'
)
(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::
python manage.py sql polls
@ -331,6 +329,12 @@ Note the following:
quotes. The author of this tutorial runs PostgreSQL, so the example
output is in PostgreSQL syntax.
* The `sql` command doesn't actually run the SQL in your database - it just
prints it to the screen so that you can see what SQL Django thinks is required.
If you wanted to, you could copy and paste this SQL into your database prompt.
However, as we will see shortly, Django provides an easier way of committing
the SQL to the database.
If you're interested, also run the following commands:
* ``python manage.py sqlinitialdata polls`` -- Outputs any initial data
@ -343,8 +347,8 @@ If you're interested, also run the following commands:
* ``python manage.py sqlindexes polls`` -- Outputs the ``CREATE INDEX``
statements for this app.
* ``python manage.py sqlall polls`` -- A combination of 'sql' and
'sqlinitialdata'.
* ``python manage.py sqlall polls`` -- A combination of all the SQL from
the 'sql', 'sqlinitialdata', and 'sqlindexes' commands.
Looking at the output of those commands can help you understand what's actually
happening under the hood.
@ -353,9 +357,11 @@ Now, run ``syncdb`` again to create those model tables in your database::
python manage.py syncdb
As a review, the ``syncdb`` command creates the tables for all apps in
``INSTALLED_APPS`` that don't already exist in your database. So you can run it
again and again, and it'll always just create the tables that don't exist.
The ``syncdb`` command runs the sql from 'sqlall' on your database for all apps
in ``INSTALLED_APPS`` that don't already exist in your database. This creates
all the tables, initial data and indexes for any apps you have added to your
project since the last time you ran syncdb. ``syncdb`` can be called as often
as you like, and it will only ever create the tables that don't exist.
Read the `django-admin.py documentation`_ for full information on what the
``manage.py`` utility can do.
@ -454,10 +460,11 @@ representations are used throughout Django's automatically-generated admin.
Note these are normal Python methods. Let's add a custom method, just for
demonstration::
import datetime
# ...
class Poll(models.Model):
# ...
def was_published_today(self):
import datetime
return self.pub_date.date() == datetime.date.today()
Note the addition of ``import datetime`` to reference Python's standard
@ -488,8 +495,6 @@ Let's jump back into the Python interactive shell by running
Traceback (most recent call last):
...
DoesNotExist: Poll does not exist for {'id': 2}
>>> Poll.objects.filter(question__startswith='What')
[What's up?]
# Lookup by a primary key is the most common case, so Django provides a
# shortcut for primary-key exact lookups.
@ -502,14 +507,15 @@ Let's jump back into the Python interactive shell by running
>>> p.was_published_today()
False
# Give the Poll a couple of Choices. Each one of these method calls does an
# INSERT statement behind the scenes and returns the new Choice object.
# Give the Poll a couple of Choices. The create call constructs a new
# choice object, does the INSERT statement, adds the choice to the set
# of available choices and returns the new Choice object.
>>> p = Poll.objects.get(pk=1)
>>> p.choice_set.add(choice='Not much', votes=0)
>>> p.choice_set.create(choice='Not much', votes=0)
Not much
>>> p.choice_set.add(choice='The sky', votes=0)
>>> p.choice_set.create(choice='The sky', votes=0)
The sky
>>> c = p.choice_set.add(choice='Just hacking again', votes=0)
>>> c = p.choice_set.create(choice='Just hacking again', votes=0)
# Choice objects have API access to their related Poll objects.
>>> c.poll
@ -518,7 +524,7 @@ Let's jump back into the Python interactive shell by running
# And vice versa: Poll objects get access to Choice objects.
>>> p.choice_set.all()
[Not much, The sky, Just hacking again]
>>> p.choice_set.all().count()
>>> p.choice_set.count()
3
# The API automatically follows relationships as far as you need.

View File

@ -31,22 +31,13 @@ The Django admin site is not activated by default -- it's an opt-in thing. To
activate the admin site for your installation, do these three things:
* Add ``"django.contrib.admin"`` to your ``INSTALLED_APPS`` setting.
* Run the command ``python manage.py install admin``. This will create an
extra database table that the admin needs.
* 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
"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.
Create a user account
=====================
Run the following command to create a superuser account for your admin site::
python manage.py createsuperuser
The script will prompt you for a username, e-mail address and password (twice).
Start the development server
============================
@ -96,7 +87,8 @@ creating an empty class means "give this object an admin interface using
all the default options."
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.
to restart the development server -- the server will auto-reloads your project,
so any modifications code will be seen immediately in your browser.
Explore the free admin functionality
====================================

View File

@ -74,25 +74,27 @@ Time for an example. Edit ``myproject/urls.py`` so it looks like this::
urlpatterns = patterns('',
(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'),
(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'),
)
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/(\d+)/$'`` -- it loads the
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``.
Finally, it calls that ``detail()`` function like so::
detail(request=<HttpRequest object>, poll_id='23')
The ``poll_id='23'`` part comes from ``(\d+)``. Using parenthesis around a
The ``poll_id='23'`` part comes from ``(?P<poll_id>\d+)``. Using parenthesis around a
pattern "captures" the text matched by that pattern and sends it as an argument
to the view function.
to the view function; the ``?P<poll_id>`` defines the name that will be used to
identify the matched pattern; and \d+ is a regular experession to match a sequence of
digits (i.e., a number).
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
@ -185,11 +187,11 @@ 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 django.models.polls import polls
from myproject.polls.models import Poll
from django.http import HttpResponse
def index(request):
latest_poll_list = polls.get_list(order_by=['-pub_date'], limit=5)
latest_poll_list = Poll.objects.all().order_by('-pub_date')
output = ', '.join([p.question for p in latest_poll_list])
return HttpResponse(output)
@ -198,11 +200,11 @@ 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 django.models.polls import polls
from myproject.polls.models import Poll
from django.http import HttpResponse
def index(request):
latest_poll_list = polls.get_list(order_by=['-pub_date'], limit=5)
latest_poll_list = Poll.objects.all().order_by('-pub_date')
t = loader.get_template('polls/index')
c = Context({
'latest_poll_list': latest_poll_list,
@ -255,10 +257,10 @@ 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 django.models.polls import polls
from myproject.polls.models import Poll
def index(request):
latest_poll_list = polls.get_list(order_by=['-pub_date'], limit=5)
latest_poll_list = Poll.objects.all().order_by('-pub_date')
return render_to_response('polls/index', {'latest_poll_list': latest_poll_list})
Note that we no longer need to import ``loader``, ``Context`` or
@ -275,10 +277,11 @@ Now, let's tackle the poll detail view -- the page that displays the question
for a given poll. Here's the view::
from django.http import Http404
# ...
def detail(request, poll_id):
try:
p = polls.get_object(pk=poll_id)
except polls.PollDoesNotExist:
p = Poll.objects.get(pk=poll_id)
except Poll.DoesNotExist:
raise Http404
return render_to_response('polls/detail', {'poll': p})
@ -292,9 +295,10 @@ It's a very common idiom to use ``get_object()`` and raise ``Http404`` if the
object doesn't exist. Django provides a shortcut. Here's the ``detail()`` view,
rewritten::
from django.shortcuts import get_object_or_404
from django.shortcuts import render_to_response, get_object_or_404
# ...
def detail(request, poll_id):
p = get_object_or_404(polls, pk=poll_id)
p = get_object_or_404(Poll, pk=poll_id)
return render_to_response('polls/detail', {'poll': p})
The ``get_object_or_404()`` function takes a Django model module as its first

View File

@ -18,7 +18,7 @@ template contains an HTML ``<form>`` element::
{% if error_message %}<p><strong>{{ error_message }}</strong></p>{% endif %}
<form action="/polls/{{ poll.id }}/vote/" method="post">
{% for choice in poll.get_choice_list %}
{% for choice in poll.choice_set.all %}
<input type="radio" name="choice" id="choice{{ forloop.counter }}" value="{{ choice.id }}" />
<label for="choice{{ forloop.counter }}">{{ choice.choice }}</label><br />
{% endfor %}
@ -41,22 +41,22 @@ A quick rundown:
Django; it's just good Web development practice.
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 that
included this line::
something with it. Remember, in `Tutorial 3`_, we create a URLconf for the
polls application that includes this line::
(r'^polls/(?P<poll_id>\d+)/vote/$', 'myproject.polls.views.vote'),
(r'^(?P<poll_id>\d+)/vote/$', 'myproject.polls.views.vote'),
So let's create a ``vote()`` function in ``myproject/polls/views.py``::
from django.shortcuts import get_object_or_404, render_to_response
from django.http import HttpResponseRedirect
from django.http import Http404,HttpResponseRedirect
from myproject.polls.models import Choice, Poll
# ...
def vote(request, poll_id):
p = get_object_or_404(Poll, pk=poll_id)
try:
selected_choice = p.choice_set.filter(pk=request.POST['choice'])
except (KeyError, choices.ChoiceDoesNotExist):
except (KeyError, Choice.DoesNotExist):
# Redisplay the poll voting form.
return render_to_response('polls/detail', {
'poll': p,
@ -113,7 +113,7 @@ Now, create a ``results.html`` template::
<h1>{{ poll.question }}</h1>
<ul>
{% for choice in poll.get_choice_list %}
{% for choice in poll.choice_set.all %}
<li>{{ choice.choice }} -- {{ choice.votes }} vote{{ choice.votes|pluralize }}</li>
{% endfor %}
</ul>
@ -185,37 +185,45 @@ We're using two generic views here: ``object_list`` and ``object_detail``.
Respectively, those two views abstract the concepts of "display a list of
objects" and "display a detail page for a particular type of object."
* Each generic view needs to know which model its acting on. This
is done using a QuerySet.
* Each generic view needs to know what data it will be acting upon. This
data is provided in a dictionary. The ``queryset`` key in this dictionary
points to the list of objects to be manipulated by the generic view.
* The ``object_detail`` generic view expects that the ID value captured
from the URL is called ``"object_id"``, so we've changed ``poll_id`` to
* The ``object_detail`` generic view expects the ID value captured
from the URL to be called ``"object_id"``, so we've changed ``poll_id`` to
``object_id`` for the generic views.
By default, the ``object_detail`` generic view uses a template called
``<app_label>/<module_name>_detail``. In our case, it'll use the template
``"polls/polls_detail"``. Thus, rename your ``polls/detail.html`` template to
``polls/polls_detail.html``, and change the ``render_to_response()`` line in
``<app name>/<module name>_detail``. In our case, it'll use the template
``"polls/poll_detail"``. Thus, rename your ``polls/detail.html`` template to
``polls/poll_detail.html``, and change the ``render_to_response()`` line in
``vote()``.
Similarly, the ``object_list`` generic view uses a template called
``<app_label>/<module_name>_list``. Thus, rename ``polls/index.html`` to
``polls/polls_list.html``.
``<app name>/<module name>_list``. Thus, rename ``poll/index.html`` to
``polls/poll_list.html``.
Because we have more than one entry in the URLconf that uses ``object_detail``
for the polls app, we manually specify a template name for the results view:
``template_name='polls/results'``. Otherwise, both views would use the same
template. Note that we use ``dict()`` to return an altered dictionary in place.
The generic views pass ``object`` and ``object_list`` to their templates, so
change your templates so that ``latest_poll_list`` becomes ``object_list`` and
``poll`` becomes ``object``.
In previous versions of the tutorial, the templates have been provided with a context
that contains the ``poll` and ``latest_poll_list`` context variables. However,
the generic views provide the variables ``object`` and ``object_list`` as context.
Therefore, you need to change your templates to match the new context variables.
Go through your templates, and modify any reference to ``latest_poll_list`` to
``object_list``, and change any reference to ``poll`` to ``object``.
In the ``vote()`` view, change the template call from ``polls/detail`` to
``polls/polls_detail``, and pass ``object`` in the context instead of ``poll``.
You can now delete the ``index()``, ``detail()`` and ``results()`` views
from ``polls/views.py``. We don't need them anymore -- they have been replaced
by generic views.
Finally, you can delete the ``index()``, ``detail()`` and ``results()`` views
from ``polls/views.py``. We don't need them anymore.
The ``vote()`` view is still required. However, it must be modified to match
the new templates and context variables. Change the template call from ``polls/detail``
to ``polls/polls_detail``, and pass ``object`` in the context instead of ``poll``.
Run the server, and use your new polling app based on generic views.
For full details on generic views, see the `generic views documentation`_.