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:
parent
218035c3e1
commit
d1083f15fb
@ -24,7 +24,7 @@ Initial setup
|
|||||||
If this is your first time using Django, you'll have to take care of some
|
If this is your first time using Django, you'll have to take care of some
|
||||||
initial setup.
|
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.
|
``myproject`` directory in your current directory.
|
||||||
|
|
||||||
(``django-admin.py`` should be on your system path if you installed Django via
|
(``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.
|
database's interactive prompt.
|
||||||
|
|
||||||
While you're editing ``settings.py``, take note of the ``INSTALLED_APPS``
|
While you're editing ``settings.py``, take note of the ``INSTALLED_APPS``
|
||||||
setting. That variable holds the names of all Django applications that are
|
setting towards the bottom of the file. That variable holds the names of all
|
||||||
activated in this Django instance. Apps can be used in multiple projects,
|
Django applications that are activated in this Django instance. Apps can be
|
||||||
and you can distribute them.
|
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
|
By default, ``INSTALLED_APPS`` contains the following apps, all of which come
|
||||||
with Django::
|
with Django::
|
||||||
@ -285,12 +286,9 @@ to include the string ``'myproject.polls'``. So it'll look like this::
|
|||||||
'django.contrib.contenttypes',
|
'django.contrib.contenttypes',
|
||||||
'django.contrib.sessions',
|
'django.contrib.sessions',
|
||||||
'django.contrib.sites',
|
'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::
|
Now Django knows ``myproject`` includes the ``polls`` app. Let's run another command::
|
||||||
|
|
||||||
python manage.py sql polls
|
python manage.py sql polls
|
||||||
@ -331,6 +329,12 @@ Note the following:
|
|||||||
quotes. The author of this tutorial runs PostgreSQL, so the example
|
quotes. The author of this tutorial runs PostgreSQL, so the example
|
||||||
output is in PostgreSQL syntax.
|
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:
|
If you're interested, also run the following commands:
|
||||||
|
|
||||||
* ``python manage.py sqlinitialdata polls`` -- Outputs any initial data
|
* ``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``
|
* ``python manage.py sqlindexes polls`` -- Outputs the ``CREATE INDEX``
|
||||||
statements for this app.
|
statements for this app.
|
||||||
|
|
||||||
* ``python manage.py sqlall polls`` -- A combination of 'sql' and
|
* ``python manage.py sqlall polls`` -- A combination of all the SQL from
|
||||||
'sqlinitialdata'.
|
the 'sql', 'sqlinitialdata', and 'sqlindexes' commands.
|
||||||
|
|
||||||
Looking at the output of those commands can help you understand what's actually
|
Looking at the output of those commands can help you understand what's actually
|
||||||
happening under the hood.
|
happening under the hood.
|
||||||
@ -353,9 +357,11 @@ Now, run ``syncdb`` again to create those model tables in your database::
|
|||||||
|
|
||||||
python manage.py syncdb
|
python manage.py syncdb
|
||||||
|
|
||||||
As a review, the ``syncdb`` command creates the tables for all apps in
|
The ``syncdb`` command runs the sql from 'sqlall' on your database for all apps
|
||||||
``INSTALLED_APPS`` that don't already exist in your database. So you can run it
|
in ``INSTALLED_APPS`` that don't already exist in your database. This creates
|
||||||
again and again, and it'll always just create the tables that don't exist.
|
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
|
Read the `django-admin.py documentation`_ for full information on what the
|
||||||
``manage.py`` utility can do.
|
``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
|
Note these are normal Python methods. Let's add a custom method, just for
|
||||||
demonstration::
|
demonstration::
|
||||||
|
|
||||||
|
import datetime
|
||||||
|
# ...
|
||||||
class Poll(models.Model):
|
class Poll(models.Model):
|
||||||
# ...
|
# ...
|
||||||
def was_published_today(self):
|
def was_published_today(self):
|
||||||
import datetime
|
|
||||||
return self.pub_date.date() == datetime.date.today()
|
return self.pub_date.date() == datetime.date.today()
|
||||||
|
|
||||||
Note the addition of ``import datetime`` to reference Python's standard
|
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):
|
Traceback (most recent call last):
|
||||||
...
|
...
|
||||||
DoesNotExist: Poll does not exist for {'id': 2}
|
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
|
# Lookup by a primary key is the most common case, so Django provides a
|
||||||
# shortcut for primary-key exact lookups.
|
# 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()
|
>>> p.was_published_today()
|
||||||
False
|
False
|
||||||
|
|
||||||
# Give the Poll a couple of Choices. Each one of these method calls does an
|
# Give the Poll a couple of Choices. The create call constructs a new
|
||||||
# INSERT statement behind the scenes and returns the new Choice object.
|
# 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 = 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
|
Not much
|
||||||
>>> p.choice_set.add(choice='The sky', votes=0)
|
>>> p.choice_set.create(choice='The sky', votes=0)
|
||||||
The sky
|
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.
|
# Choice objects have API access to their related Poll objects.
|
||||||
>>> c.poll
|
>>> 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.
|
# And vice versa: Poll objects get access to Choice objects.
|
||||||
>>> p.choice_set.all()
|
>>> p.choice_set.all()
|
||||||
[Not much, The sky, Just hacking again]
|
[Not much, The sky, Just hacking again]
|
||||||
>>> p.choice_set.all().count()
|
>>> p.choice_set.count()
|
||||||
3
|
3
|
||||||
|
|
||||||
# The API automatically follows relationships as far as you need.
|
# The API automatically follows relationships as far as you need.
|
||||||
|
@ -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:
|
activate the admin site for your installation, do these three things:
|
||||||
|
|
||||||
* Add ``"django.contrib.admin"`` to your ``INSTALLED_APPS`` setting.
|
* Add ``"django.contrib.admin"`` to your ``INSTALLED_APPS`` setting.
|
||||||
* Run the command ``python manage.py install admin``. This will create an
|
* Run ``python manage.py syncdb``. Since you have added a new application
|
||||||
extra database table that the admin needs.
|
to ``INSTALLED_APPS``, the database tables need to be updated.
|
||||||
* Edit your ``myproject/urls.py`` file and uncomment the line below
|
* Edit your ``myproject/urls.py`` file and uncomment the line below
|
||||||
"Uncomment this for admin:". This file is a URLconf; we'll dig into
|
"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
|
URLconfs in the next tutorial. For now, all you need to know is that it
|
||||||
maps URL roots to applications.
|
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
|
Start the development server
|
||||||
============================
|
============================
|
||||||
|
|
||||||
@ -96,7 +87,8 @@ creating an empty class means "give this object an admin interface using
|
|||||||
all the default options."
|
all the default options."
|
||||||
|
|
||||||
Now reload the Django admin page to see your changes. Note that you don't have
|
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
|
Explore the free admin functionality
|
||||||
====================================
|
====================================
|
||||||
|
@ -74,25 +74,27 @@ Time for an example. Edit ``myproject/urls.py`` so it looks like this::
|
|||||||
|
|
||||||
urlpatterns = patterns('',
|
urlpatterns = patterns('',
|
||||||
(r'^polls/$', 'myproject.polls.views.index'),
|
(r'^polls/$', 'myproject.polls.views.index'),
|
||||||
(r'^polls/(\d+)/$', 'myproject.polls.views.detail'),
|
(r'^polls/(?P<poll_id>\d+)/$', 'myproject.polls.views.detail'),
|
||||||
(r'^polls/(\d+)/results/$', 'myproject.polls.views.results'),
|
(r'^polls/(?P<poll_id>\d+)/results/$', 'myproject.polls.views.results'),
|
||||||
(r'^polls/(\d+)/vote/$', 'myproject.polls.views.vote'),
|
(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 --
|
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
|
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``
|
by the ``ROOT_URLCONF`` setting. It finds the variable named ``urlpatterns``
|
||||||
and traverses the regular expressions in order. When it finds a regular
|
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
|
associated Python package/module: ``myproject.polls.views.detail``. That
|
||||||
corresponds to the function ``detail()`` in ``myproject/polls/views.py``.
|
corresponds to the function ``detail()`` in ``myproject/polls/views.py``.
|
||||||
Finally, it calls that ``detail()`` function like so::
|
Finally, it calls that ``detail()`` function like so::
|
||||||
|
|
||||||
detail(request=<HttpRequest object>, poll_id='23')
|
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
|
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
|
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
|
what you can do with them. And there's no need to add URL cruft such as
|
||||||
@ -185,29 +187,29 @@ 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
|
latest 5 poll questions in the system, separated by commas, according to
|
||||||
publication date::
|
publication date::
|
||||||
|
|
||||||
from django.models.polls import polls
|
from myproject.polls.models import Poll
|
||||||
from django.http import HttpResponse
|
from django.http import HttpResponse
|
||||||
|
|
||||||
def index(request):
|
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])
|
output = ', '.join([p.question for p in latest_poll_list])
|
||||||
return HttpResponse(output)
|
return HttpResponse(output)
|
||||||
|
|
||||||
There's a problem here, though: The page's design is hard-coded in the view. If
|
There's a problem here, though: The page's design is hard-coded in the view. If
|
||||||
you want to change the way the page looks, you'll have to edit this Python code.
|
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::
|
So let's use Django's template system to separate the design from Python::
|
||||||
|
|
||||||
from django.template import Context, loader
|
from django.template import Context, loader
|
||||||
from django.models.polls import polls
|
from myproject.polls.models import Poll
|
||||||
from django.http import HttpResponse
|
from django.http import HttpResponse
|
||||||
|
|
||||||
def index(request):
|
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')
|
t = loader.get_template('polls/index')
|
||||||
c = Context({
|
c = Context({
|
||||||
'latest_poll_list': latest_poll_list,
|
'latest_poll_list': latest_poll_list,
|
||||||
})
|
})
|
||||||
return HttpResponse(t.render(c))
|
return HttpResponse(t.render(c))
|
||||||
|
|
||||||
That code loads the template called "polls/index" and passes it a context. The
|
That code loads the template called "polls/index" and passes it a context. The
|
||||||
context is a dictionary mapping template variable names to Python objects.
|
context is a dictionary mapping template variable names to Python objects.
|
||||||
@ -254,11 +256,11 @@ It's a very common idiom to load a template, fill a context and return an
|
|||||||
``HttpResponse`` object with the result of the rendered template. Django
|
``HttpResponse`` object with the result of the rendered template. Django
|
||||||
provides a shortcut. Here's the full ``index()`` view, rewritten::
|
provides a shortcut. Here's the full ``index()`` view, rewritten::
|
||||||
|
|
||||||
from django.shortcuts import render_to_response
|
from django.shortcuts import render_to_response
|
||||||
from django.models.polls import polls
|
from myproject.polls.models import Poll
|
||||||
|
|
||||||
def index(request):
|
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})
|
return render_to_response('polls/index', {'latest_poll_list': latest_poll_list})
|
||||||
|
|
||||||
Note that we no longer need to import ``loader``, ``Context`` or
|
Note that we no longer need to import ``loader``, ``Context`` or
|
||||||
@ -275,12 +277,13 @@ Now, let's tackle the poll detail view -- the page that displays the question
|
|||||||
for a given poll. Here's the view::
|
for a given poll. Here's the view::
|
||||||
|
|
||||||
from django.http import Http404
|
from django.http import Http404
|
||||||
def detail(request, poll_id):
|
# ...
|
||||||
try:
|
def detail(request, poll_id):
|
||||||
p = polls.get_object(pk=poll_id)
|
try:
|
||||||
except polls.PollDoesNotExist:
|
p = Poll.objects.get(pk=poll_id)
|
||||||
raise Http404
|
except Poll.DoesNotExist:
|
||||||
return render_to_response('polls/detail', {'poll': p})
|
raise Http404
|
||||||
|
return render_to_response('polls/detail', {'poll': p})
|
||||||
|
|
||||||
The new concept here: The view raises the ``django.http.Http404``
|
The new concept here: The view raises the ``django.http.Http404``
|
||||||
exception if a poll with the requested ID doesn't exist.
|
exception if a poll with the requested ID doesn't exist.
|
||||||
@ -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,
|
object doesn't exist. Django provides a shortcut. Here's the ``detail()`` view,
|
||||||
rewritten::
|
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):
|
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})
|
return render_to_response('polls/detail', {'poll': p})
|
||||||
|
|
||||||
The ``get_object_or_404()`` function takes a Django model module as its first
|
The ``get_object_or_404()`` function takes a Django model module as its first
|
||||||
|
@ -18,7 +18,7 @@ template contains an HTML ``<form>`` element::
|
|||||||
{% if error_message %}<p><strong>{{ error_message }}</strong></p>{% endif %}
|
{% if error_message %}<p><strong>{{ error_message }}</strong></p>{% endif %}
|
||||||
|
|
||||||
<form action="/polls/{{ poll.id }}/vote/" method="post">
|
<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 }}" />
|
<input type="radio" name="choice" id="choice{{ forloop.counter }}" value="{{ choice.id }}" />
|
||||||
<label for="choice{{ forloop.counter }}">{{ choice.choice }}</label><br />
|
<label for="choice{{ forloop.counter }}">{{ choice.choice }}</label><br />
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
@ -41,22 +41,22 @@ A quick rundown:
|
|||||||
Django; it's just good Web development practice.
|
Django; it's just good Web development practice.
|
||||||
|
|
||||||
Now, let's create a Django view that handles the submitted data and does
|
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
|
something with it. Remember, in `Tutorial 3`_, we create a URLconf for the
|
||||||
included this line::
|
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``::
|
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.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
|
from myproject.polls.models import Choice, Poll
|
||||||
|
# ...
|
||||||
def vote(request, poll_id):
|
def vote(request, poll_id):
|
||||||
p = get_object_or_404(Poll, pk=poll_id)
|
p = get_object_or_404(Poll, pk=poll_id)
|
||||||
try:
|
try:
|
||||||
selected_choice = p.choice_set.filter(pk=request.POST['choice'])
|
selected_choice = p.choice_set.filter(pk=request.POST['choice'])
|
||||||
except (KeyError, choices.ChoiceDoesNotExist):
|
except (KeyError, Choice.DoesNotExist):
|
||||||
# Redisplay the poll voting form.
|
# Redisplay the poll voting form.
|
||||||
return render_to_response('polls/detail', {
|
return render_to_response('polls/detail', {
|
||||||
'poll': p,
|
'poll': p,
|
||||||
@ -113,7 +113,7 @@ Now, create a ``results.html`` template::
|
|||||||
<h1>{{ poll.question }}</h1>
|
<h1>{{ poll.question }}</h1>
|
||||||
|
|
||||||
<ul>
|
<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>
|
<li>{{ choice.choice }} -- {{ choice.votes }} vote{{ choice.votes|pluralize }}</li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</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
|
Respectively, those two views abstract the concepts of "display a list of
|
||||||
objects" and "display a detail page for a particular type of object."
|
objects" and "display a detail page for a particular type of object."
|
||||||
|
|
||||||
* Each generic view needs to know which model its acting on. This
|
* Each generic view needs to know what data it will be acting upon. This
|
||||||
is done using a QuerySet.
|
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
|
* The ``object_detail`` generic view expects the ID value captured
|
||||||
from the URL is called ``"object_id"``, so we've changed ``poll_id`` to
|
from the URL to be called ``"object_id"``, so we've changed ``poll_id`` to
|
||||||
``object_id`` for the generic views.
|
``object_id`` for the generic views.
|
||||||
|
|
||||||
By default, the ``object_detail`` generic view uses a template called
|
By default, the ``object_detail`` generic view uses a template called
|
||||||
``<app_label>/<module_name>_detail``. In our case, it'll use the template
|
``<app name>/<module name>_detail``. In our case, it'll use the template
|
||||||
``"polls/polls_detail"``. Thus, rename your ``polls/detail.html`` template to
|
``"polls/poll_detail"``. Thus, rename your ``polls/detail.html`` template to
|
||||||
``polls/polls_detail.html``, and change the ``render_to_response()`` line in
|
``polls/poll_detail.html``, and change the ``render_to_response()`` line in
|
||||||
``vote()``.
|
``vote()``.
|
||||||
|
|
||||||
Similarly, the ``object_list`` generic view uses a template called
|
Similarly, the ``object_list`` generic view uses a template called
|
||||||
``<app_label>/<module_name>_list``. Thus, rename ``polls/index.html`` to
|
``<app name>/<module name>_list``. Thus, rename ``poll/index.html`` to
|
||||||
``polls/polls_list.html``.
|
``polls/poll_list.html``.
|
||||||
|
|
||||||
Because we have more than one entry in the URLconf that uses ``object_detail``
|
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:
|
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_name='polls/results'``. Otherwise, both views would use the same
|
||||||
template. Note that we use ``dict()`` to return an altered dictionary in place.
|
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
|
In previous versions of the tutorial, the templates have been provided with a context
|
||||||
change your templates so that ``latest_poll_list`` becomes ``object_list`` and
|
that contains the ``poll` and ``latest_poll_list`` context variables. However,
|
||||||
``poll`` becomes ``object``.
|
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
|
You can now delete the ``index()``, ``detail()`` and ``results()`` views
|
||||||
``polls/polls_detail``, and pass ``object`` in the context instead of ``poll``.
|
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
|
The ``vote()`` view is still required. However, it must be modified to match
|
||||||
from ``polls/views.py``. We don't need them anymore.
|
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`_.
|
For full details on generic views, see the `generic views documentation`_.
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user