1
0
mirror of https://github.com/django/django.git synced 2025-10-23 21:59:11 +00:00

Refs #36485 -- Rewrapped docs to 79 columns line length.

Lines in the docs files were manually adjusted to conform to the
79 columns limit per line (plus newline), improving readability and
consistency across the content.
This commit is contained in:
David Smith
2025-07-25 10:24:17 +01:00
committed by nessita
parent 4286a23df6
commit f81e6e3a53
230 changed files with 3250 additions and 2914 deletions

View File

@@ -32,9 +32,9 @@ don't, `Dive Into Python`_ is a fantastic (and free) online book for beginning
Python programmers.
Those of you who are unfamiliar with version control systems and Trac will find
that this tutorial and its links include just enough information to get started.
However, you'll probably want to read some more about these different tools if
you plan on contributing to Django regularly.
that this tutorial and its links include just enough information to get
started. However, you'll probably want to read some more about these different
tools if you plan on contributing to Django regularly.
For the most part though, this tutorial tries to explain as much as possible,
so that it can be of use to the widest audience.
@@ -52,9 +52,9 @@ so that it can be of use to the widest audience.
What does this tutorial cover?
------------------------------
We'll be walking you through contributing to Django for the first time.
By the end of this tutorial, you should have a basic understanding of both the
tools and the processes involved. Specifically, we'll be covering the following:
We'll be walking you through contributing to Django for the first time. By the
end of this tutorial, you should have a basic understanding of both the tools
and the processes involved. Specifically, we'll be covering the following:
* Installing Git.
* Downloading a copy of Django's development version.
@@ -85,7 +85,8 @@ Code of Conduct
===============
As a contributor, you can help us keep the Django community open and inclusive.
Please read and follow our `Code of Conduct <https://www.djangoproject.com/conduct/>`_.
Please read and follow our `Code of Conduct
<https://www.djangoproject.com/conduct/>`_.
Installing Git
==============
@@ -123,11 +124,11 @@ Download the Django source code repository using the following command:
all of Django's commit history, which reduces data transfer from ~250 MB
to ~70 MB.
Now that you have a local copy of Django, you can install it just like you would
install any package using ``pip``. The most convenient way to do so is by using
a *virtual environment*, which is a feature built into Python that allows you
to keep a separate directory of installed packages for each of your projects so
that they don't interfere with each other.
Now that you have a local copy of Django, you can install it just like you
would install any package using ``pip``. The most convenient way to do so is by
using a *virtual environment*, which is a feature built into Python that allows
you to keep a separate directory of installed packages for each of your
projects so that they don't interfere with each other.
It's a good idea to keep all your virtual environments in one place, for
example in ``.virtualenvs/`` in your home directory.
@@ -176,20 +177,20 @@ Go ahead and install the previously cloned copy of Django:
$ python -m pip install -e /path/to/your/local/clone/django/
The installed version of Django is now pointing at your local copy by installing
in editable mode. You will immediately see any changes you make to it, which is
of great help when testing your first contribution.
The installed version of Django is now pointing at your local copy by
installing in editable mode. You will immediately see any changes you make to
it, which is of great help when testing your first contribution.
Running Django's test suite for the first time
==============================================
When contributing to Django it's very important that your code changes don't
introduce bugs into other areas of Django. One way to check that Django still
works after you make your changes is by running Django's test suite. If all
the tests still pass, then you can be reasonably sure that your changes
work and haven't broken other parts of Django. If you've never run Django's test
suite before, it's a good idea to run it once beforehand to get familiar with
its output.
works after you make your changes is by running Django's test suite. If all the
tests still pass, then you can be reasonably sure that your changes work and
haven't broken other parts of Django. If you've never run Django's test suite
before, it's a good idea to run it once beforehand to get familiar with its
output.
Before running the test suite, enter the Django ``tests/`` directory using the
``cd tests`` command, and install test dependencies by running:
@@ -348,8 +349,8 @@ that's really what happens. ``cd`` to the Django ``tests/`` directory and run:
$ ./runtests.py shortcuts
If the tests ran correctly, you should see one failure corresponding to the test
method we added, with this error:
If the tests ran correctly, you should see one failure corresponding to the
test method we added, with this error:
.. code-block:: pytb

View File

@@ -24,8 +24,8 @@ place: read this material to quickly get up and running.
.. seealso::
If you're new to Python_, you might want to start by getting an idea of what
the language is like. Django is 100% Python, so if you've got minimal
If you're new to Python_, you might want to start by getting an idea of
what the language is like. Django is 100% Python, so if you've got minimal
comfort with Python you'll probably get a lot more out of Django.
If you're new to programming entirely, you might want to start with this

View File

@@ -32,9 +32,9 @@ you should see something like:
Set up a database
=================
This step is only necessary if you'd like to work with a "large" database engine
like PostgreSQL, MariaDB, MySQL, or Oracle. To install such a database, consult
the :ref:`database installation information <database-installation>`.
This step is only necessary if you'd like to work with a "large" database
engine like PostgreSQL, MariaDB, MySQL, or Oracle. To install such a database,
consult the :ref:`database installation information <database-installation>`.
Install Django
==============

View File

@@ -9,15 +9,15 @@ overview of how to write a database-driven web app with Django.
The goal of this document is to give you enough technical specifics to
understand how Django works, but this isn't intended to be a tutorial or
reference -- but we've got both! When you're ready to start a project, you can
:doc:`start with the tutorial </intro/tutorial01>` or :doc:`dive right into more
detailed documentation </topics/index>`.
:doc:`start with the tutorial </intro/tutorial01>` or :doc:`dive right into
more detailed documentation </topics/index>`.
Design your model
=================
Although you can use Django without a database, it comes with an
`object-relational mapper`_ in which you describe your database layout in Python
code.
`object-relational mapper`_ in which you describe your database layout in
Python code.
.. _object-relational mapper: https://en.wikipedia.org/wiki/Object-relational_mapping
@@ -247,19 +247,19 @@ and renders the template with the retrieved data. Here's an example view for
context = {"year": year, "article_list": a_list}
return render(request, "news/year_archive.html", context)
This example uses Django's :doc:`template system </topics/templates>`, which has
several powerful features but strives to stay simple enough for non-programmers
to use.
This example uses Django's :doc:`template system </topics/templates>`, which
has several powerful features but strives to stay simple enough for
non-programmers to use.
Design your templates
=====================
The code above loads the ``news/year_archive.html`` template.
Django has a template search path, which allows you to minimize redundancy among
templates. In your Django settings, you specify a list of directories to check
for templates with :setting:`DIRS <TEMPLATES-DIRS>`. If a template doesn't exist
in the first directory, it checks the second, and so on.
Django has a template search path, which allows you to minimize redundancy
among templates. In your Django settings, you specify a list of directories to
check for templates with :setting:`DIRS <TEMPLATES-DIRS>`. If a template
doesn't exist in the first directory, it checks the second, and so on.
Let's say the ``news/year_archive.html`` template was found. Here's what that
might look like:
@@ -287,14 +287,14 @@ used only for attribute lookup. They also can do dictionary-key lookup, index
lookup and function calls.
Note ``{{ article.pub_date|date:"F j, Y" }}`` uses a Unix-style "pipe" (the "|"
character). This is called a template filter, and it's a way to filter the value
of a variable. In this case, the date filter formats a Python datetime object in
the given format (as found in PHP's date function).
character). This is called a template filter, and it's a way to filter the
value of a variable. In this case, the date filter formats a Python datetime
object in the given format (as found in PHP's date function).
You can chain together as many filters as you'd like. You can write :ref:`custom
template filters <howto-writing-custom-template-filters>`. You can write
:doc:`custom template tags </howto/custom-template-tags>`, which run custom
Python code behind the scenes.
You can chain together as many filters as you'd like. You can write
:ref:`custom template filters <howto-writing-custom-template-filters>`. You can
write :doc:`custom template tags </howto/custom-template-tags>`, which run
custom Python code behind the scenes.
Finally, Django uses the concept of "template inheritance". That's what the
``{% extends "base.html" %}`` does. It means "First load the template called
@@ -319,9 +319,9 @@ Here's what the "base.html" template, including the use of :doc:`static files
</body>
</html>
Simplistically, it defines the look-and-feel of the site (with the site's logo),
and provides "holes" for child templates to fill. This means that a site redesign
can be done by changing a single file -- the base template.
Simplistically, it defines the look-and-feel of the site (with the site's
logo), and provides "holes" for child templates to fill. This means that a site
redesign can be done by changing a single file -- the base template.
It also lets you create multiple versions of a site, with different base
templates, while reusing child templates. Django's creators have used this

View File

@@ -344,8 +344,8 @@ the world! If this wasn't just an example, you could now:
* Upload the package on your website.
* Post the package on a public repository, such as `the Python Package Index
(PyPI)`_. `packaging.python.org <https://packaging.python.org>`_ has `a good
tutorial <https://packaging.python.org/tutorials/packaging-projects/#uploading-the-distribution-archives>`_
(PyPI)`_. There is `a good tutorial
<https://packaging.python.org/tutorials/packaging-projects/#uploading-the-distribution-archives>`_
for doing this.
Installing Python packages with a virtual environment

View File

@@ -39,8 +39,8 @@ Creating a project
==================
If this is your first time using Django, you'll have to take care of some
initial setup. Namely, you'll need to auto-generate some code that establishes a
Django :term:`project` -- a collection of settings for an instance of Django,
initial setup. Namely, you'll need to auto-generate some code that establishes
a Django :term:`project` -- a collection of settings for an instance of Django,
including database configuration, Django-specific options and
application-specific settings.
@@ -122,8 +122,8 @@ You'll see the following output on the command line:
System check identified no issues (0 silenced).
You have unapplied migrations; your app may not work properly until they are applied.
Run 'python manage.py migrate' to apply them.
You have unapplied migrations; your app may not work properly until they are
applied. Run 'python manage.py migrate' to apply them.
|today| - 15:50:53
Django version |version|, using settings 'mysite.settings'
@@ -150,7 +150,8 @@ 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. (We're in
the business of making web frameworks, not web servers.)
(To serve the site on a different port, see the :djadmin:`runserver` reference.)
(To serve the site on a different port, see the :djadmin:`runserver`
reference.)
.. admonition:: Automatic reloading of :djadmin:`runserver`

View File

@@ -51,7 +51,8 @@ come with Django:
* :mod:`django.contrib.staticfiles` -- A framework for managing
static files.
These applications are included by default as a convenience for the common case.
These applications are included by default as a convenience for the common
case.
Some of these applications make use of at least one database table, though,
so we need to create the tables in the database before we can use them. To do
@@ -62,13 +63,13 @@ that, run the following command:
$ python manage.py migrate
The :djadmin:`migrate` command looks at the :setting:`INSTALLED_APPS` setting
and creates any necessary database tables according to the database settings
in your :file:`mysite/settings.py` file and the database migrations shipped
with the app (we'll cover those later). You'll see a message for each
migration it applies. If you're interested, run the command-line client for your
database and type ``\dt`` (PostgreSQL), ``SHOW TABLES;`` (MariaDB, MySQL),
``.tables`` (SQLite), or ``SELECT TABLE_NAME FROM USER_TABLES;`` (Oracle) to
display the tables Django created.
and creates any necessary database tables according to the database settings in
your :file:`mysite/settings.py` file and the database migrations shipped with
the app (we'll cover those later). You'll see a message for each migration it
applies. If you're interested, run the command-line client for your database
and type ``\dt`` (PostgreSQL), ``SHOW TABLES;`` (MariaDB, MySQL), ``.tables``
(SQLite), or ``SELECT TABLE_NAME FROM USER_TABLES;`` (Oracle) to display the
tables Django created.
.. admonition:: For the minimalists
@@ -94,8 +95,8 @@ additional metadata.
Django follows the :ref:`DRY Principle <dry>`. The goal is to define your
data model in one place and automatically derive things from it.
This includes the migrations - unlike in Ruby On Rails, for example, migrations
are entirely derived from your models file, and are essentially a
This includes the migrations - unlike in Ruby On Rails, for example,
migrations are entirely derived from your models file, and are essentially a
history that Django can roll through to update your database schema to
match your current models.
@@ -138,12 +139,12 @@ format. You'll use this value in your Python code, and your database will use
it as the column name.
You can use an optional first positional argument to a
:class:`~django.db.models.Field` to designate a human-readable name. That's used
in a couple of introspective parts of Django, and it doubles as documentation.
If this field isn't provided, Django will use the machine-readable name. In this
example, we've only defined a human-readable name for ``Question.pub_date``.
For all other fields in this model, the field's machine-readable name will
suffice as its human-readable name.
:class:`~django.db.models.Field` to designate a human-readable name. That's
used in a couple of introspective parts of Django, and it doubles as
documentation. If this field isn't provided, Django will use the
machine-readable name. In this example, we've only defined a human-readable
name for ``Question.pub_date``. For all other fields in this model, the field's
machine-readable name will suffice as its human-readable name.
Some :class:`~django.db.models.Field` classes have required arguments.
:class:`~django.db.models.CharField`, for example, requires that you give it a
@@ -166,7 +167,8 @@ That small bit of model code gives Django a lot of information. With it, Django
is able to:
* Create a database schema (``CREATE TABLE`` statements) for this app.
* Create a Python database-access API for accessing ``Question`` and ``Choice`` objects.
* Create a Python database-access API for accessing ``Question`` and ``Choice``
objects.
But first we need to tell our project that the ``polls`` app is installed.
@@ -223,8 +225,8 @@ they're designed to be human-editable in case you want to manually tweak how
Django changes things.
There's a command that will run the migrations for you and manage your database
schema automatically - that's called :djadmin:`migrate`, and we'll come to it in a
moment - but first, let's see what SQL that migration would run. The
schema automatically - that's called :djadmin:`migrate`, and we'll come to it
in a moment - but first, let's see what SQL that migration would run. The
:djadmin:`sqlmigrate` command takes migration names and returns their SQL:
.. console::
@@ -297,7 +299,8 @@ If you're interested, you can also run
:djadmin:`python manage.py check <check>`; this checks for any problems in
your project without making migrations or touching the database.
Now, run :djadmin:`migrate` again to create those model tables in your database:
Now, run :djadmin:`migrate` again to create those model tables in your
database:
.. console::
@@ -534,8 +537,8 @@ Introducing the Django Admin
Django was written in a newsroom environment, with a very clear separation
between "content publishers" and the "public" site. Site managers use the
system to add news stories, events, sports scores, etc., and that content is
displayed on the public site. Django solves the problem of creating a
system to add news stories, events, sports scores, etc., and that content
is displayed on the public site. Django solves the problem of creating a
unified interface for site administrators to edit content.
The admin isn't intended to be used by site visitors. It's for site
@@ -597,8 +600,8 @@ given language (if Django has appropriate translations).
Enter the admin site
--------------------
Now, try logging in with the superuser account you created in the previous step.
You should see the Django admin index page:
Now, try logging in with the superuser account you created in the previous
step. You should see the Django admin index page:
.. image:: _images/admin02.png
:alt: Django admin index page
@@ -628,15 +631,15 @@ edit it to look like this:
Explore the free admin functionality
------------------------------------
Now that we've registered ``Question``, Django knows that it should be displayed on
the admin index page:
Now that we've registered ``Question``, Django knows that it should be
displayed on the admin index page:
.. image:: _images/admin03t.png
:alt: Django admin index page, now with polls displayed
Click "Questions". Now you're at the "change list" page for questions. This page
displays all the questions in the database and lets you choose one to change it.
There's the "What's up?" question we created earlier:
Click "Questions". Now you're at the "change list" page for questions. This
page displays all the questions in the database and lets you choose one to
change it. There's the "What's up?" question we created earlier:
.. image:: _images/admin04t.png
:alt: Polls change list page

View File

@@ -2,8 +2,8 @@
Writing your first Django app, part 3
=====================================
This tutorial begins where :doc:`Tutorial 2 </intro/tutorial02>` left off. We're
continuing the web-poll application and will focus on creating the public
This tutorial begins where :doc:`Tutorial 2 </intro/tutorial02>` left off.
We're continuing the web-poll application and will focus on creating the public
interface -- "views."
.. admonition:: Where to get help:
@@ -51,8 +51,8 @@ the part of the URL after the domain name).
Now in your time on the web you may have come across such beauties as
``ME2/Sites/dirmod.htm?sid=&type=gen&mod=Core+Pages&gid=A6CD4967199A42D9B65B1B``.
You will be pleased to know that Django allows us much more elegant
*URL patterns* than that.
You will be pleased to know that Django allows us much more elegant *URL
patterns* than that.
A URL pattern is the general form of a URL - for example:
``/newsarchive/<year>/<month>/``.
@@ -135,8 +135,8 @@ Write views that actually do something
Each view is responsible for doing one of two things: returning an
:class:`~django.http.HttpResponse` object containing the content for the
requested page, or raising an exception such as :exc:`~django.http.Http404`. The
rest is up to you.
requested page, or raising an exception such as :exc:`~django.http.Http404`.
The rest is up to you.
Your view can read records from a database, or not. It can use a template
system such as Django's -- or a third-party Python template system -- or not.
@@ -167,9 +167,9 @@ commas, according to publication date:
# Leave the rest of the views (detail, results, vote) unchanged
There's a problem here, though: the page's design is hardcoded in the view. If
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 by
creating a template that the view can use.
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
by creating a template that the view can use.
First, create a directory called ``templates`` in your ``polls`` directory.
Django will look for templates in there.
@@ -268,8 +268,8 @@ rewritten:
Note that once we've done this in all these views, we no longer need to import
:mod:`~django.template.loader` and :class:`~django.http.HttpResponse` (you'll
want to keep ``HttpResponse`` if you still have the stub methods for ``detail``,
``results``, and ``vote``).
want to keep ``HttpResponse`` if you still have the stub methods for
``detail``, ``results``, and ``vote``).
The :func:`~django.shortcuts.render` function takes the request object as its
first argument, a template name as its second argument and a dictionary as its
@@ -279,8 +279,8 @@ object of the given template rendered with the given context.
Raising a 404 error
===================
Now, let's tackle the question detail view -- the page that displays the question text
for a given poll. Here's the view:
Now, let's tackle the question detail view -- the page that displays the
question text for a given poll. Here's the view:
.. code-block:: python
:caption: ``polls/views.py``
@@ -361,8 +361,8 @@ Use the template system
=======================
Back to the ``detail()`` view for our poll application. Given the context
variable ``question``, here's what the ``polls/detail.html`` template might look
like:
variable ``question``, here's what the ``polls/detail.html`` template might
look like:
.. code-block:: html+django
:caption: ``polls/templates/polls/detail.html``
@@ -375,15 +375,15 @@ like:
</ul>
The template system uses dot-lookup syntax to access variable attributes. In
the example of ``{{ question.question_text }}``, first Django does a dictionary lookup
on the object ``question``. Failing that, it tries an attribute lookup -- which
works, in this case. If attribute lookup had failed, it would've tried a
list-index lookup.
the example of ``{{ question.question_text }}``, first Django does a dictionary
lookup on the object ``question``. Failing that, it tries an attribute lookup
-- which works, in this case. If attribute lookup had failed, it would've tried
a list-index lookup.
Method-calling happens in the :ttag:`{% for %}<for>` loop:
``question.choice_set.all`` is interpreted as the Python code
``question.choice_set.all()``, which returns an iterable of ``Choice`` objects and is
suitable for use in the :ttag:`{% for %}<for>` tag.
``question.choice_set.all()``, which returns an iterable of ``Choice`` objects
and is suitable for use in the :ttag:`{% for %}<for>` tag.
See the :doc:`template guide </topics/templates>` for more about templates.

View File

@@ -2,8 +2,8 @@
Writing your first Django app, part 4
=====================================
This tutorial begins where :doc:`Tutorial 3 </intro/tutorial03>` left off. We're
continuing the web-poll application and will focus on form processing and
This tutorial begins where :doc:`Tutorial 3 </intro/tutorial03>` left off.
We're continuing the web-poll application and will focus on form processing and
cutting down our code.
.. admonition:: Where to get help:
@@ -42,8 +42,8 @@ A quick rundown:
POST data ``choice=#`` where # is the ID of the selected choice. This is the
basic concept of HTML forms.
* We set the form's ``action`` to ``{% url 'polls:vote' question.id %}``, and we
set ``method="post"``. Using ``method="post"`` (as opposed to
* We set the form's ``action`` to ``{% url 'polls:vote' question.id %}``, and
we set ``method="post"``. Using ``method="post"`` (as opposed to
``method="get"``) is very important, because the act of submitting this
form will alter data server-side. Whenever you create a form that alters
data server-side, use ``method="post"``. This tip isn't specific to
@@ -158,8 +158,8 @@ As mentioned in :doc:`Tutorial 3 </intro/tutorial03>`, ``request`` is an
:class:`~django.http.HttpRequest` objects, see the :doc:`request and
response documentation </ref/request-response>`.
After somebody votes in a question, the ``vote()`` view redirects to the results
page for the question. Let's write that view:
After somebody votes in a question, the ``vote()`` view redirects to the
results page for the question. Let's write that view:
.. code-block:: python
:caption: ``polls/views.py``
@@ -190,8 +190,8 @@ Now, create a ``polls/results.html`` template:
<a href="{% url 'polls:detail' question.id %}">Vote again?</a>
Now, go to ``/polls/1/`` in your browser and vote in the question. You should see a
results page that gets updated each time you vote. If you submit the form
Now, go to ``/polls/1/`` in your browser and vote in the question. You should
see a results page that gets updated each time you vote. If you submit the form
without having chosen a choice, you should see the error message.
Use generic views: Less code is better
@@ -206,12 +206,12 @@ the database according to a parameter passed in the URL, loading a template and
returning the rendered template. Because this is so common, Django provides a
shortcut, called the "generic views" system.
Generic views abstract common patterns to the point where you don't even need to
write Python code to write an app. For example, the
Generic views abstract common patterns to the point where you don't even need
to write Python code to write an app. For example, the
:class:`~django.views.generic.list.ListView` and
:class:`~django.views.generic.detail.DetailView` generic views
abstract the concepts of "display a list of objects" and
"display a detail page for a particular type of object" respectively.
:class:`~django.views.generic.detail.DetailView` generic views abstract the
concepts of "display a list of objects" and "display a detail page for a
particular type of object" respectively.
Let's convert our poll app to use the generic views system, so we can delete a
bunch of our own code. We'll have to take a few steps to make the conversion.

View File

@@ -122,7 +122,8 @@ tests earlier, but it's never too late to get started.
Sometimes it's difficult to figure out where to get started with writing tests.
If you have written several thousand lines of Python, choosing something to
test might not be easy. In such a case, it's fruitful to write your first test
the next time you make a change, either when you add a new feature or fix a bug.
the next time you make a change, either when you add a new feature or fix a
bug.
So let's do that right away.
@@ -135,9 +136,10 @@ We identify a bug
-----------------
Fortunately, there's a little bug in the ``polls`` application for us to fix
right away: the ``Question.was_published_recently()`` method returns ``True`` if
the ``Question`` was published within the last day (which is correct) but also if
the ``Question``s ``pub_date`` field is in the future (which certainly isn't).
right away: the ``Question.was_published_recently()`` method returns ``True``
if the ``Question`` was published within the last day (which is correct) but
also if the ``Question``s ``pub_date`` field is in the future (which certainly
isn't).
Confirm the bug by using the :djadmin:`shell` to check the method on a question
whose date lies in the future:
@@ -191,9 +193,9 @@ Put the following in the ``tests.py`` file in the ``polls`` application:
future_question = Question(pub_date=time)
self.assertIs(future_question.was_published_recently(), False)
Here we have created a :class:`django.test.TestCase` subclass with a method that
creates a ``Question`` instance with a ``pub_date`` in the future. We then check
the output of ``was_published_recently()`` - which *ought* to be False.
Here we have created a :class:`django.test.TestCase` subclass with a method
that creates a ``Question`` instance with a ``pub_date`` in the future. We then
check the output of ``was_published_recently()`` - which *ought* to be False.
Running tests
-------------
@@ -242,8 +244,8 @@ What happened is this:
* it looked for test methods - ones whose names begin with ``test``
* in ``test_was_published_recently_with_future_question`` it created a ``Question``
instance whose ``pub_date`` field is 30 days in the future
* in ``test_was_published_recently_with_future_question`` it created a
``Question`` instance whose ``pub_date`` field is 30 days in the future
* ... and using the ``assertIs()`` method, it discovered that its
``was_published_recently()`` returns ``True``, though we wanted it to return
@@ -255,10 +257,10 @@ occurred.
Fixing the bug
--------------
We already know what the problem is: ``Question.was_published_recently()`` should
return ``False`` if its ``pub_date`` is in the future. Amend the method in
``models.py``, so that it will only return ``True`` if the date is also in the
past:
We already know what the problem is: ``Question.was_published_recently()``
should return ``False`` if its ``pub_date`` is in the future. Amend the method
in ``models.py``, so that it will only return ``True`` if the date is also in
the past:
.. code-block:: python
:caption: ``polls/models.py``
@@ -292,8 +294,8 @@ More comprehensive tests
------------------------
While we're here, we can further pin down the ``was_published_recently()``
method; in fact, it would be positively embarrassing if in fixing one bug we had
introduced another.
method; in fact, it would be positively embarrassing if in fixing one bug we
had introduced another.
Add two more test methods to the same class, to test the behavior of the method
more comprehensively:
@@ -320,8 +322,9 @@ more comprehensively:
recent_question = Question(pub_date=time)
self.assertIs(recent_question.was_published_recently(), True)
And now we have three tests that confirm that ``Question.was_published_recently()``
returns sensible values for past, recent, and future questions.
And now we have three tests that confirm that
``Question.was_published_recently()`` returns sensible values for past, recent,
and future questions.
Again, ``polls`` is a minimal application, but however complex it grows in the
future and whatever other code it interacts with, we now have some guarantee
@@ -644,19 +647,19 @@ code is suffering from test bloat, which brings us to:
When testing, more is better
============================
It might seem that our tests are growing out of control. At this rate there will
soon be more code in our tests than in our application, and the repetition
It might seem that our tests are growing out of control. At this rate there
will soon be more code in our tests than in our application, and the repetition
is unaesthetic, compared to the elegant conciseness of the rest of our code.
**It doesn't matter**. Let them grow. For the most part, you can write a test
once and then forget about it. It will continue performing its useful function
as you continue to develop your program.
Sometimes tests will need to be updated. Suppose that we amend our views so that
only ``Question`` entries with associated ``Choice`` instances are published.
In that case, many of our existing tests will fail - *telling us exactly which
tests need to be amended to bring them up to date*, so to that extent tests
help look after themselves.
Sometimes tests will need to be updated. Suppose that we amend our views so
that only ``Question`` entries with associated ``Choice`` instances are
published. In that case, many of our existing tests will fail - *telling us
exactly which tests need to be amended to bring them up to date*, so to that
extent tests help look after themselves.
At worst, as you continue developing, you might find that you have some tests
that are now redundant. Even that's not a problem; in testing redundancy is

View File

@@ -2,10 +2,10 @@
Writing your first Django app, part 7
=====================================
This tutorial begins where :doc:`Tutorial 6 </intro/tutorial06>` left off. We're
continuing the web-poll application and will focus on customizing Django's
automatically-generated admin site that we first explored in :doc:`Tutorial 2
</intro/tutorial02>`.
This tutorial begins where :doc:`Tutorial 6 </intro/tutorial06>` left off.
We're continuing the web-poll application and will focus on customizing
Django's automatically-generated admin site that we first explored in
:doc:`Tutorial 2 </intro/tutorial02>`.
.. admonition:: Where to get help:
@@ -71,8 +71,8 @@ up into fieldsets:
admin.site.register(Question, QuestionAdmin)
The first element of each tuple in
:attr:`~django.contrib.admin.ModelAdmin.fieldsets` is the title of the fieldset.
Here's what our form looks like now:
:attr:`~django.contrib.admin.ModelAdmin.fieldsets` is the title of the
fieldset. Here's what our form looks like now:
.. image:: _images/admin08t.png
:alt: Form has fieldsets now
@@ -104,10 +104,10 @@ looks like this:
.. image:: _images/admin09.png
:alt: Choice admin page
In that form, the "Question" field is a select box containing every question in the
database. Django knows that a :class:`~django.db.models.ForeignKey` should be
represented in the admin as a ``<select>`` box. In our case, only one question
exists at this point.
In that form, the "Question" field is a select box containing every question in
the database. Django knows that a :class:`~django.db.models.ForeignKey` should
be represented in the admin as a ``<select>`` box. In our case, only one
question exists at this point.
Also note the "Add another question" link next to "Question." Every object with
a ``ForeignKey`` relationship to another gets this for free. When you click
@@ -116,12 +116,12 @@ If you add a question in that window and click "Save", Django will save the
question to the database and dynamically add it as the selected choice on the
"Add choice" form you're looking at.
But, really, this is an inefficient way of adding ``Choice`` objects to the system.
It'd be better if you could add a bunch of Choices directly when you create the
``Question`` object. Let's make that happen.
But, really, this is an inefficient way of adding ``Choice`` objects to the
system. It'd be better if you could add a bunch of Choices directly when you
create the ``Question`` object. Let's make that happen.
Remove the ``register()`` call for the ``Choice`` model. Then, edit the ``Question``
registration code to read:
Remove the ``register()`` call for the ``Choice`` model. Then, edit the
``Question`` registration code to read:
.. code-block:: python
:caption: ``polls/admin.py``
@@ -146,8 +146,8 @@ registration code to read:
admin.site.register(Question, QuestionAdmin)
This tells Django: "``Choice`` objects are edited on the ``Question`` admin page. By
default, provide enough fields for 3 choices."
This tells Django: "``Choice`` objects are edited on the ``Question`` admin
page. By default, provide enough fields for 3 choices."
Load the "Add question" page to see how that looks:
@@ -167,8 +167,8 @@ image shows an added slot:
:alt: Additional slot added dynamically
One small problem, though. It takes a lot of screen space to display all the
fields for entering related ``Choice`` objects. For that reason, Django offers a
tabular way of displaying inline related objects. To use it, change the
fields for entering related ``Choice`` objects. For that reason, Django offers
a tabular way of displaying inline related objects. To use it, change the
``ChoiceInline`` declaration to read:
.. code-block:: python
@@ -278,10 +278,10 @@ This is shaping up well. Let's add some search capability::
search_fields = ["question_text"]
That adds a search box at the top of the change list. When somebody enters
search terms, Django will search the ``question_text`` field. You can use as many
fields as you'd like -- although because it uses a ``LIKE`` query behind the
scenes, limiting the number of search fields to a reasonable number will make
it easier for your database to do the search.
search terms, Django will search the ``question_text`` field. You can use as
many fields as you'd like -- although because it uses a ``LIKE`` query behind
the scenes, limiting the number of search fields to a reasonable number will
make it easier for your database to do the search.
Now's also a good time to note that change lists give you free pagination. The
default is to display 100 items per page. :attr:`Change list pagination
@@ -413,9 +413,9 @@ Customize the admin index page
On a similar note, you might want to customize the look and feel of the Django
admin index page.
By default, it displays all the apps in :setting:`INSTALLED_APPS` that have been
registered with the admin application, in alphabetical order. You may want to
make significant changes to the layout. After all, the index is probably the
By default, it displays all the apps in :setting:`INSTALLED_APPS` that have
been registered with the admin application, in alphabetical order. You may want
to make significant changes to the layout. After all, the index is probably the
most important page of the admin, and it should be easy to use.
The template to customize is ``admin/index.html``. (Do the same as with

View File

@@ -2,11 +2,11 @@
Writing your first Django app, part 8
=====================================
This tutorial begins where :doc:`Tutorial 7 </intro/tutorial07>` left off. We've
built our web-poll application and will now look at third-party packages. One of
Django's strengths is the rich ecosystem of third-party packages. They're
community developed packages that can be used to quickly improve the feature set
of an application.
This tutorial begins where :doc:`Tutorial 7 </intro/tutorial07>` left off.
We've built our web-poll application and will now look at third-party packages.
One of Django's strengths is the rich ecosystem of third-party packages.
They're community developed packages that can be used to quickly improve the
feature set of an application.
This tutorial will show how to add :pypi:`Django Debug Toolbar
<django-debug-toolbar>`, a commonly used third-party package. The Django Debug
@@ -68,7 +68,8 @@ resolve the issue yourself, there are options available to you.
<https://django-debug-toolbar.readthedocs.io/en/latest/tips.html>`_ that
outlines troubleshooting options.
#. Search for similar issues on the package's issue tracker. Django Debug
Toolbars is `on GitHub <https://github.com/django-commons/django-debug-toolbar/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc>`_.
Toolbars is `on GitHub
<https://github.com/django-commons/django-debug-toolbar/issues>`_.
#. Consult the `Django Forum <https://forum.djangoproject.com/>`_.
#. Join the `Django Discord server <https://chat.djangoproject.com>`_.

View File

@@ -10,8 +10,8 @@ with this intro (in fact, if you've read every single word, you've read about
So what's next?
Well, we've always been big fans of learning by doing. At this point you should
know enough to start a project of your own and start fooling around. As you need
to learn new tricks, come back to the documentation. There's also a bigger
know enough to start a project of your own and start fooling around. As you
need to learn new tricks, come back to the documentation. There's also a bigger
`Django ecosystem`_ out there for you to explore that the community has
created.
@@ -100,8 +100,8 @@ reasons:
* To add documentation for new features as new features get added, or as
Django APIs or behaviors change.
Django's documentation is kept in the same source control system as its code. It
lives in the :source:`docs` directory of our Git repository. Each document
Django's documentation is kept in the same source control system as its code.
It lives in the :source:`docs` directory of our Git repository. Each document
online is a separate text file in the repository.
Where to get it
@@ -115,15 +115,16 @@ On the web
The most recent version of the Django documentation lives at
https://docs.djangoproject.com/en/dev/. These HTML pages are generated
automatically from the text files in source control. That means they reflect the
"latest and greatest" in Django -- they include the very latest corrections and
additions, and they discuss the latest Django features, which may only be
automatically from the text files in source control. That means they reflect
the "latest and greatest" in Django -- they include the very latest corrections
and additions, and they discuss the latest Django features, which may only be
available to users of the Django development version. (See
:ref:`differences-between-doc-versions` below.)
We encourage you to help improve the docs by submitting changes, corrections and
suggestions in the `ticket system`_. The Django developers actively monitor the
ticket system and use your feedback to improve the documentation for everybody.
We encourage you to help improve the docs by submitting changes, corrections
and suggestions in the `ticket system`_. The Django developers actively monitor
the ticket system and use your feedback to improve the documentation for
everybody.
Note, however, that tickets should explicitly relate to the documentation,
rather than asking broad tech-support questions. If you need help with your