mirror of
https://github.com/django/django.git
synced 2025-10-24 14:16:09 +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:
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
==============
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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`
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
Toolbar’s is `on GitHub <https://github.com/django-commons/django-debug-toolbar/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc>`_.
|
||||
Toolbar’s 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>`_.
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user