mirror of
https://github.com/django/django.git
synced 2024-12-22 09:05:43 +00:00
Refs #34140 -- Applied rst code-block to non-Python examples.
Thanks to J.V. Zammit, Paolo Melchiorre, and Mariusz Felisiak for reviews.
This commit is contained in:
parent
7bb741d787
commit
534ac48297
@ -195,7 +195,9 @@ It's difficult to give an official citation format, for two reasons: citation
|
||||
formats can vary wildly between publications, and citation standards for
|
||||
software are still a matter of some debate.
|
||||
|
||||
For example, `APA style`_, would dictate something like::
|
||||
For example, `APA style`_, would dictate something like:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
Django (Version 1.5) [Computer Software]. (2013). Retrieved from https://www.djangoproject.com/.
|
||||
|
||||
|
@ -8,7 +8,9 @@ How can I see the raw SQL queries Django is running?
|
||||
====================================================
|
||||
|
||||
Make sure your Django :setting:`DEBUG` setting is set to ``True``.
|
||||
Then do this::
|
||||
Then do this:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.db import connection
|
||||
>>> connection.queries
|
||||
@ -17,16 +19,18 @@ Then do this::
|
||||
|
||||
``connection.queries`` is only available if :setting:`DEBUG` is ``True``.
|
||||
It's a list of dictionaries in order of query execution. Each dictionary has
|
||||
the following::
|
||||
the following:
|
||||
|
||||
``sql`` -- The raw SQL statement
|
||||
``time`` -- How long the statement took to execute, in seconds.
|
||||
* ``sql`` - The raw SQL statement
|
||||
* ``time`` - How long the statement took to execute, in seconds.
|
||||
|
||||
``connection.queries`` includes all SQL statements -- INSERTs, UPDATES,
|
||||
SELECTs, etc. Each time your app hits the database, the query will be recorded.
|
||||
|
||||
If you are using :doc:`multiple databases</topics/db/multi-db>`, you can use the
|
||||
same interface on each member of the ``connections`` dictionary::
|
||||
same interface on each member of the ``connections`` dictionary:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.db import connections
|
||||
>>> connections['my_db_alias'].queries
|
||||
@ -85,6 +89,8 @@ these options, create a migration with a
|
||||
``ALTER TABLE`` statements that do what you want to do.
|
||||
|
||||
For example, if you're using MySQL and want your tables to use the MyISAM table
|
||||
type, use the following SQL::
|
||||
type, use the following SQL:
|
||||
|
||||
.. code-block:: sql
|
||||
|
||||
ALTER TABLE myapp_mytable ENGINE=MyISAM;
|
||||
|
@ -36,7 +36,9 @@ I'm getting a ``UnicodeDecodeError``. What am I doing wrong?
|
||||
|
||||
This class of errors happen when a bytestring containing non-ASCII sequences is
|
||||
transformed into a Unicode string and the specified encoding is incorrect. The
|
||||
output generally looks like this::
|
||||
output generally looks like this:
|
||||
|
||||
.. code-block:: pytb
|
||||
|
||||
UnicodeDecodeError: 'ascii' codec can't decode byte 0x?? in position ?:
|
||||
ordinal not in range(128)
|
||||
|
@ -225,7 +225,9 @@ decorator so that they no longer rejects requests. In every other respect
|
||||
|
||||
If, for some reason, you *want* the test client to perform CSRF
|
||||
checks, you can create an instance of the test client that enforces
|
||||
CSRF checks::
|
||||
CSRF checks:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.test import Client
|
||||
>>> csrf_client = Client(enforce_csrf_checks=True)
|
||||
|
@ -12,7 +12,9 @@ command for the ``polls`` application from the
|
||||
|
||||
To do this, add a ``management/commands`` directory to the application. Django
|
||||
will register a ``manage.py`` command for each Python module in that directory
|
||||
whose name doesn't begin with an underscore. For example::
|
||||
whose name doesn't begin with an underscore. For example:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
polls/
|
||||
__init__.py
|
||||
|
@ -35,7 +35,9 @@ later, so be careful to pick a name that won't clash with custom tags and
|
||||
filters in another app.
|
||||
|
||||
For example, if your custom tags/filters are in a file called
|
||||
``poll_extras.py``, your app layout might look like this::
|
||||
``poll_extras.py``, your app layout might look like this:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
polls/
|
||||
__init__.py
|
||||
|
@ -2,8 +2,6 @@
|
||||
How to use Django with Daphne
|
||||
=============================
|
||||
|
||||
.. highlight:: bash
|
||||
|
||||
Daphne_ is a pure-Python ASGI server for UNIX, maintained by members of the
|
||||
Django project. It acts as the reference server for ASGI.
|
||||
|
||||
@ -12,7 +10,9 @@ Django project. It acts as the reference server for ASGI.
|
||||
Installing Daphne
|
||||
===================
|
||||
|
||||
You can install Daphne with ``pip``::
|
||||
You can install Daphne with ``pip``:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
python -m pip install daphne
|
||||
|
||||
@ -24,7 +24,9 @@ Daphne server process. At its simplest, Daphne needs to be called with the
|
||||
location of a module containing an ASGI application object, followed by what
|
||||
the application is called (separated by a colon).
|
||||
|
||||
For a typical Django project, invoking Daphne would look like::
|
||||
For a typical Django project, invoking Daphne would look like:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
daphne myproject.asgi:application
|
||||
|
||||
|
@ -2,15 +2,15 @@
|
||||
How to use Django with Hypercorn
|
||||
================================
|
||||
|
||||
.. highlight:: bash
|
||||
|
||||
Hypercorn_ is an ASGI server that supports HTTP/1, HTTP/2, and HTTP/3
|
||||
with an emphasis on protocol support.
|
||||
|
||||
Installing Hypercorn
|
||||
====================
|
||||
|
||||
You can install Hypercorn with ``pip``::
|
||||
You can install Hypercorn with ``pip``:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
python -m pip install hypercorn
|
||||
|
||||
@ -22,7 +22,9 @@ which runs ASGI applications. Hypercorn needs to be called with the
|
||||
location of a module containing an ASGI application object, followed
|
||||
by what the application is called (separated by a colon).
|
||||
|
||||
For a typical Django project, invoking Hypercorn would look like::
|
||||
For a typical Django project, invoking Hypercorn would look like:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
hypercorn myproject.asgi:application
|
||||
|
||||
|
@ -2,15 +2,15 @@
|
||||
How to use Django with Uvicorn
|
||||
==============================
|
||||
|
||||
.. highlight:: bash
|
||||
|
||||
Uvicorn_ is an ASGI server based on ``uvloop`` and ``httptools``, with an
|
||||
emphasis on speed.
|
||||
|
||||
Installing Uvicorn
|
||||
==================
|
||||
|
||||
You can install Uvicorn with ``pip``::
|
||||
You can install Uvicorn with ``pip``:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
python -m pip install uvicorn
|
||||
|
||||
@ -22,7 +22,9 @@ applications. Uvicorn needs to be called with the location of a module
|
||||
containing an ASGI application object, followed by what the application is
|
||||
called (separated by a colon).
|
||||
|
||||
For a typical Django project, invoking Uvicorn would look like::
|
||||
For a typical Django project, invoking Uvicorn would look like:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
python -m uvicorn myproject.asgi:application
|
||||
|
||||
@ -41,11 +43,15 @@ Deploying Django using Uvicorn and Gunicorn
|
||||
Gunicorn_ is a robust web server that implements process monitoring and automatic
|
||||
restarts. This can be useful when running Uvicorn in a production environment.
|
||||
|
||||
To install Uvicorn and Gunicorn, use the following::
|
||||
To install Uvicorn and Gunicorn, use the following:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
python -m pip install uvicorn gunicorn
|
||||
|
||||
Then start Gunicorn using the Uvicorn worker class like this::
|
||||
Then start Gunicorn using the Uvicorn worker class like this:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
python -m gunicorn myproject.asgi:application -k uvicorn.workers.UvicornWorker
|
||||
|
||||
|
@ -2,8 +2,6 @@
|
||||
How to use Django with Gunicorn
|
||||
===============================
|
||||
|
||||
.. highlight:: bash
|
||||
|
||||
Gunicorn_ ('Green Unicorn') is a pure-Python WSGI server for UNIX. It has no
|
||||
dependencies and can be installed using ``pip``.
|
||||
|
||||
@ -23,7 +21,9 @@ Running Django in Gunicorn as a generic WSGI application
|
||||
When Gunicorn is installed, a ``gunicorn`` command is available which starts
|
||||
the Gunicorn server process. The simplest invocation of gunicorn is to pass the
|
||||
location of a module containing a WSGI application object named
|
||||
``application``, which for a typical Django project would look like::
|
||||
``application``, which for a typical Django project would look like:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
gunicorn myproject.wsgi
|
||||
|
||||
|
@ -85,7 +85,9 @@ should put in this file, and what else you can add to it.
|
||||
|
||||
If you get a ``UnicodeEncodeError`` when uploading or writing files with
|
||||
file names or content that contains non-ASCII characters, make sure Apache
|
||||
is configured to support UTF-8 encoding::
|
||||
is configured to support UTF-8 encoding:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
export LANG='en_US.UTF-8'
|
||||
export LC_ALL='en_US.UTF-8'
|
||||
@ -94,7 +96,9 @@ should put in this file, and what else you can add to it.
|
||||
|
||||
Alternatively, if you are :ref:`using mod_wsgi daemon mode<daemon-mode>`
|
||||
you can add ``lang`` and ``locale`` options to the ``WSGIDaemonProcess``
|
||||
directive::
|
||||
directive:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
WSGIDaemonProcess example.com lang='en_US.UTF-8' locale='en_US.UTF-8'
|
||||
|
||||
|
@ -2,8 +2,6 @@
|
||||
How to use Django with uWSGI
|
||||
============================
|
||||
|
||||
.. highlight:: bash
|
||||
|
||||
uWSGI_ is a fast, self-healing and developer/sysadmin-friendly application
|
||||
container server coded in pure C.
|
||||
|
||||
@ -48,7 +46,9 @@ uWSGI supports multiple ways to configure the process. See uWSGI's
|
||||
|
||||
.. _configuration documentation: https://uwsgi.readthedocs.io/en/latest/Configuration.html
|
||||
|
||||
Here's an example command to start a uWSGI server::
|
||||
Here's an example command to start a uWSGI server:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
uwsgi --chdir=/path/to/your/project \
|
||||
--module=mysite.wsgi:application \
|
||||
@ -80,7 +80,9 @@ The Django-specific options here are:
|
||||
* ``env``: Should probably contain at least :envvar:`DJANGO_SETTINGS_MODULE`.
|
||||
* ``home``: Optional path to your project virtual environment.
|
||||
|
||||
Example ini configuration file::
|
||||
Example ini configuration file:
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
[uwsgi]
|
||||
chdir=/path/to/your/project
|
||||
@ -91,7 +93,9 @@ Example ini configuration file::
|
||||
max-requests=5000
|
||||
daemonize=/var/log/uwsgi/yourproject.log
|
||||
|
||||
Example ini configuration file usage::
|
||||
Example ini configuration file usage:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
uwsgi --ini uwsgi.ini
|
||||
|
||||
@ -99,7 +103,9 @@ Example ini configuration file usage::
|
||||
|
||||
If you get a ``UnicodeEncodeError`` when uploading files with file names
|
||||
that contain non-ASCII characters, make sure uWSGI is configured to accept
|
||||
non-ASCII file names by adding this to your ``uwsgi.ini``::
|
||||
non-ASCII file names by adding this to your ``uwsgi.ini``:
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
env = LANG=en_US.UTF-8
|
||||
|
||||
|
@ -30,15 +30,17 @@ connection:
|
||||
Auto-generate the models
|
||||
========================
|
||||
|
||||
.. highlight:: bash
|
||||
|
||||
Django comes with a utility called :djadmin:`inspectdb` that can create models
|
||||
by introspecting an existing database. You can view the output by running this
|
||||
command::
|
||||
command:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
$ python manage.py inspectdb
|
||||
|
||||
Save this as a file by using standard Unix output redirection::
|
||||
Save this as a file by using standard Unix output redirection:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
$ python manage.py inspectdb > models.py
|
||||
|
||||
@ -68,7 +70,9 @@ Install the core Django tables
|
||||
==============================
|
||||
|
||||
Next, run the :djadmin:`migrate` command to install any extra needed database
|
||||
records such as admin permissions and content types::
|
||||
records such as admin permissions and content types:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
$ python manage.py migrate
|
||||
|
||||
|
@ -28,7 +28,9 @@ You can install ReportLab with ``pip``:
|
||||
|
||||
$ python -m pip install reportlab
|
||||
|
||||
Test your installation by importing it in the Python interactive interpreter::
|
||||
Test your installation by importing it in the Python interactive interpreter:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> import reportlab
|
||||
|
||||
|
@ -172,7 +172,9 @@ for gathering static files in a single directory so you can serve them easily.
|
||||
|
||||
STATIC_ROOT = "/var/www/example.com/static/"
|
||||
|
||||
#. Run the :djadmin:`collectstatic` management command::
|
||||
#. Run the :djadmin:`collectstatic` management command:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
$ python manage.py collectstatic
|
||||
|
||||
|
@ -2,8 +2,6 @@
|
||||
How to install Django on Windows
|
||||
================================
|
||||
|
||||
.. highlight:: doscon
|
||||
|
||||
This document will guide you through installing Python 3.11 and Django on
|
||||
Windows. It also provides instructions for setting up a virtual environment,
|
||||
which makes it easier to work on Python projects. This is meant as a beginner's
|
||||
@ -28,7 +26,9 @@ Download the executable installer and run it. Check the boxes next to "Install
|
||||
launcher for all users (recommended)" then click "Install Now".
|
||||
|
||||
After installation, open the command prompt and check that the Python version
|
||||
matches the version you installed by executing::
|
||||
matches the version you installed by executing:
|
||||
|
||||
.. code-block:: doscon
|
||||
|
||||
...\> py --version
|
||||
|
||||
@ -60,12 +60,16 @@ environments which we will use for this guide.
|
||||
|
||||
To create a virtual environment for your project, open a new command prompt,
|
||||
navigate to the folder where you want to create your project and then enter the
|
||||
following::
|
||||
following:
|
||||
|
||||
.. code-block:: doscon
|
||||
|
||||
...\> py -m venv project-name
|
||||
|
||||
This will create a folder called 'project-name' if it does not already exist
|
||||
and set up the virtual environment. To activate the environment, run::
|
||||
and set up the virtual environment. To activate the environment, run:
|
||||
|
||||
.. code-block:: doscon
|
||||
|
||||
...\> project-name\Scripts\activate.bat
|
||||
|
||||
@ -79,7 +83,9 @@ Install Django
|
||||
Django can be installed easily using ``pip`` within your virtual environment.
|
||||
|
||||
In the command prompt, ensure your virtual environment is active, and execute
|
||||
the following command::
|
||||
the following command:
|
||||
|
||||
.. code-block:: doscon
|
||||
|
||||
...\> py -m pip install Django
|
||||
|
||||
@ -100,7 +106,9 @@ for some reason this needs to be disabled, set the environmental variable
|
||||
:envvar:`DJANGO_COLORS` to ``nocolor``.
|
||||
|
||||
On older Windows versions, or legacy terminals, colorama_ must be installed to
|
||||
enable syntax coloring::
|
||||
enable syntax coloring:
|
||||
|
||||
.. code-block:: doscon
|
||||
|
||||
...\> py -m pip install colorama
|
||||
|
||||
@ -119,7 +127,9 @@ Common pitfalls
|
||||
|
||||
* If you are connecting to the internet behind a proxy, there might be problems
|
||||
in running the command ``py -m pip install Django``. Set the environment
|
||||
variables for proxy configuration in the command prompt as follows::
|
||||
variables for proxy configuration in the command prompt as follows:
|
||||
|
||||
.. code-block:: doscon
|
||||
|
||||
...\> set http_proxy=http://username:password@proxyserver:proxyport
|
||||
...\> set https_proxy=https://username:password@proxyserver:proxyport
|
||||
|
@ -16,7 +16,7 @@ requests.
|
||||
|
||||
When committing a pull request, make sure each individual commit matches the
|
||||
commit guidelines described below. Contributors are expected to provide the
|
||||
best pull requests possible. In practice mergers - who will likely be more
|
||||
best pull requests possible. In practice mergers - who will likely be more
|
||||
familiar with the commit guidelines - may decide to bring a commit up to
|
||||
standard themselves.
|
||||
|
||||
@ -27,7 +27,9 @@ Selenium. See the `CI wiki page`_ for instructions.
|
||||
.. _CI wiki page: https://code.djangoproject.com/wiki/CI
|
||||
|
||||
If you find yourself checking out pull requests locally more often, this git
|
||||
alias will be helpful::
|
||||
alias will be helpful:
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
[alias]
|
||||
pr = !sh -c \"git fetch upstream pull/${1}/head:pr/${1} && git checkout pr/${1}\"
|
||||
|
@ -413,8 +413,6 @@ the ticket database:
|
||||
Bisecting a regression
|
||||
======================
|
||||
|
||||
.. highlight:: console
|
||||
|
||||
A regression is a bug that's present in some newer version of Django but not in
|
||||
an older one. An extremely helpful piece of information is the commit that
|
||||
introduced the regression. Knowing the commit that caused the change in
|
||||
@ -425,11 +423,15 @@ Begin by writing a regression test for Django's test suite for the issue. For
|
||||
example, we'll pretend we're debugging a regression in migrations. After you've
|
||||
written the test and confirmed that it fails on the latest main branch, put it
|
||||
in a separate file that you can run standalone. For our example, we'll pretend
|
||||
we created ``tests/migrations/test_regression.py``, which can be run with::
|
||||
we created ``tests/migrations/test_regression.py``, which can be run with:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
$ ./runtests.py migrations.test_regression
|
||||
|
||||
Next, we mark the current point in history as being "bad" since the test fails::
|
||||
Next, we mark the current point in history as being "bad" since the test fails:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
$ git bisect bad
|
||||
You need to start by "git bisect start"
|
||||
@ -440,14 +442,18 @@ introduced (i.e. a point where the test passes). Use something like
|
||||
``git checkout HEAD~100`` to check out an earlier revision (100 commits earlier,
|
||||
in this case). Check if the test fails. If so, mark that point as "bad"
|
||||
(``git bisect bad``), then check out an earlier revision and recheck. Once you
|
||||
find a revision where your test passes, mark it as "good"::
|
||||
find a revision where your test passes, mark it as "good":
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
$ git bisect good
|
||||
Bisecting: X revisions left to test after this (roughly Y steps)
|
||||
...
|
||||
|
||||
Now we're ready for the fun part: using ``git bisect run`` to automate the rest
|
||||
of the process::
|
||||
of the process:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
$ git bisect run tests/runtests.py migrations.test_regression
|
||||
|
||||
|
@ -396,13 +396,17 @@ Ensure you have the latest point release of a :ref:`supported Python version
|
||||
that may cause the test suite to fail or hang.
|
||||
|
||||
On **macOS** (High Sierra and newer versions), you might see this message
|
||||
logged, after which the tests hang::
|
||||
logged, after which the tests hang:
|
||||
|
||||
.. code-block:: pytb
|
||||
|
||||
objc[42074]: +[__NSPlaceholderDate initialize] may have been in progress in
|
||||
another thread when fork() was called.
|
||||
|
||||
To avoid this set a ``OBJC_DISABLE_INITIALIZE_FORK_SAFETY`` environment
|
||||
variable, for example::
|
||||
variable, for example:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
$ OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YES ./runtests.py
|
||||
|
||||
@ -515,8 +519,6 @@ this purpose.
|
||||
Tips for writing tests
|
||||
======================
|
||||
|
||||
.. highlight:: python
|
||||
|
||||
Isolating model registration
|
||||
----------------------------
|
||||
|
||||
|
@ -25,7 +25,9 @@ Django's `Git repository`_ is hosted on `GitHub`_, and it is recommended
|
||||
that you also work using GitHub.
|
||||
|
||||
After installing Git, the first thing you should do is set up your name and
|
||||
email::
|
||||
email:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
$ git config --global user.name "Your Real Name"
|
||||
$ git config --global user.email "you@email.com"
|
||||
@ -43,25 +45,33 @@ Setting up local repository
|
||||
|
||||
When you have created your GitHub account, with the nick "GitHub_nick", and
|
||||
`forked Django's repository <https://github.com/django/django/fork>`__,
|
||||
create a local copy of your fork::
|
||||
create a local copy of your fork:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
git clone https://github.com/GitHub_nick/django.git
|
||||
|
||||
This will create a new directory "django", containing a clone of your GitHub
|
||||
repository. The rest of the git commands on this page need to be run within the
|
||||
cloned directory, so switch to it now::
|
||||
cloned directory, so switch to it now:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
cd django
|
||||
|
||||
Your GitHub repository will be called "origin" in Git.
|
||||
|
||||
You should also set up ``django/django`` as an "upstream" remote (that is, tell
|
||||
git that the reference Django repository was the source of your fork of it)::
|
||||
git that the reference Django repository was the source of your fork of it):
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
git remote add upstream https://github.com/django/django.git
|
||||
git fetch upstream
|
||||
|
||||
You can add other remotes similarly, for example::
|
||||
You can add other remotes similarly, for example:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
git remote add akaariai https://github.com/akaariai/django.git
|
||||
|
||||
@ -69,19 +79,25 @@ Working on a ticket
|
||||
===================
|
||||
|
||||
When working on a ticket, create a new branch for the work, and base that work
|
||||
on ``upstream/main``::
|
||||
on ``upstream/main``:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
git checkout -b ticket_xxxxx upstream/main
|
||||
|
||||
The -b flag creates a new branch for you locally. Don't hesitate to create new
|
||||
branches even for the smallest things - that's what they are there for.
|
||||
|
||||
If instead you were working for a fix on the 1.4 branch, you would do::
|
||||
If instead you were working for a fix on the 1.4 branch, you would do:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
git checkout -b ticket_xxxxx_1_4 upstream/stable/1.4.x
|
||||
|
||||
Assume the work is carried on the ticket_xxxxx branch. Make some changes and
|
||||
commit them::
|
||||
commit them:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
git commit
|
||||
|
||||
@ -91,14 +107,18 @@ uncomfortable with English, try at least to describe precisely what the commit
|
||||
does.
|
||||
|
||||
If you need to do additional work on your branch, commit as often as
|
||||
necessary::
|
||||
necessary:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
git commit -m 'Added two more tests for edge cases'
|
||||
|
||||
Publishing work
|
||||
---------------
|
||||
|
||||
You can publish your work on GitHub by running::
|
||||
You can publish your work on GitHub by running:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
git push origin ticket_xxxxx
|
||||
|
||||
@ -154,7 +174,9 @@ repository. Your commit "Added two more tests" would be unhelpful noise.
|
||||
Instead, we would rather only have one commit containing all your work.
|
||||
|
||||
To rework the history of your branch you can squash the commits into one by
|
||||
using interactive rebase::
|
||||
using interactive rebase:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
git rebase -i HEAD~2
|
||||
|
||||
@ -167,7 +189,9 @@ the editor. A second editor window should open, so you can reword the
|
||||
commit message for the commit now that it includes both your steps.
|
||||
|
||||
You can also use the "edit" option in rebase. This way you can change a single
|
||||
commit, for example to fix a typo in a docstring::
|
||||
commit, for example to fix a typo in a docstring:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
git rebase -i HEAD~3
|
||||
# Choose edit, pick, pick for the commits
|
||||
@ -180,7 +204,9 @@ commit, for example to fix a typo in a docstring::
|
||||
|
||||
If your topic branch is already published at GitHub, for example if you're
|
||||
making minor changes to take into account a review, you will need to force-push
|
||||
the changes::
|
||||
the changes:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
git push -f origin ticket_xxxxx
|
||||
|
||||
@ -193,7 +219,9 @@ After upstream has changed
|
||||
--------------------------
|
||||
|
||||
When upstream (``django/django``) has changed, you should rebase your work. To
|
||||
do this, use::
|
||||
do this, use:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
git fetch upstream
|
||||
git rebase upstream/main
|
||||
@ -225,12 +253,16 @@ easily check what changes you have done.
|
||||
|
||||
In this case, do the changes required by the reviewer. Commit as often as
|
||||
necessary. Before publishing the changes, rebase your work. If you added two
|
||||
commits, you would run::
|
||||
commits, you would run:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
git rebase -i HEAD~2
|
||||
|
||||
Squash the second commit into the first. Write a commit message along the lines
|
||||
of::
|
||||
of:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
Made changes asked in review by <reviewer>
|
||||
|
||||
@ -238,7 +270,9 @@ of::
|
||||
- Reworded the docstring of bar()
|
||||
|
||||
Finally, push your work back to your GitHub repository. Since you didn't touch
|
||||
the public commits during the rebase, you should not need to force-push::
|
||||
the public commits during the rebase, you should not need to force-push:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
git push origin ticket_xxxxx
|
||||
|
||||
@ -252,7 +286,9 @@ Working on a patch
|
||||
|
||||
One of the ways that developers can contribute to Django is by reviewing
|
||||
patches. Those patches will typically exist as pull requests on GitHub and
|
||||
can be easily integrated into your local repository::
|
||||
can be easily integrated into your local repository:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
git checkout -b pull_xxxxx upstream/main
|
||||
curl -L https://github.com/django/django/pull/xxxxx.patch | git am
|
||||
|
@ -192,11 +192,15 @@ documentation:
|
||||
good reason.
|
||||
|
||||
* The main thing to keep in mind as you write and edit docs is that the
|
||||
more semantic markup you can add the better. So::
|
||||
more semantic markup you can add the better. So:
|
||||
|
||||
.. code-block:: rst
|
||||
|
||||
Add ``django.contrib.auth`` to your ``INSTALLED_APPS``...
|
||||
|
||||
Isn't nearly as helpful as::
|
||||
Isn't nearly as helpful as:
|
||||
|
||||
.. code-block:: rst
|
||||
|
||||
Add :mod:`django.contrib.auth` to your :setting:`INSTALLED_APPS`...
|
||||
|
||||
@ -219,7 +223,9 @@ documentation:
|
||||
* To improve readability, use ``.. admonition:: Descriptive title`` rather than
|
||||
``.. note::``. Use these boxes sparingly.
|
||||
|
||||
* Use these heading styles::
|
||||
* Use these heading styles:
|
||||
|
||||
.. code-block:: rst
|
||||
|
||||
===
|
||||
One
|
||||
@ -258,44 +264,58 @@ Django-specific markup
|
||||
Besides :ref:`Sphinx's built-in markup <sphinx:rst-index>`, Django's docs
|
||||
define some extra description units:
|
||||
|
||||
* Settings::
|
||||
* Settings:
|
||||
|
||||
.. code-block:: rst
|
||||
|
||||
.. setting:: INSTALLED_APPS
|
||||
|
||||
To link to a setting, use ``:setting:`INSTALLED_APPS```.
|
||||
|
||||
* Template tags::
|
||||
* Template tags:
|
||||
|
||||
.. code-block:: rst
|
||||
|
||||
.. templatetag:: regroup
|
||||
|
||||
To link, use ``:ttag:`regroup```.
|
||||
|
||||
* Template filters::
|
||||
* Template filters:
|
||||
|
||||
.. code-block:: rst
|
||||
|
||||
.. templatefilter:: linebreaksbr
|
||||
|
||||
To link, use ``:tfilter:`linebreaksbr```.
|
||||
|
||||
* Field lookups (i.e. ``Foo.objects.filter(bar__exact=whatever)``)::
|
||||
* Field lookups (i.e. ``Foo.objects.filter(bar__exact=whatever)``):
|
||||
|
||||
.. code-block:: rst
|
||||
|
||||
.. fieldlookup:: exact
|
||||
|
||||
To link, use ``:lookup:`exact```.
|
||||
|
||||
* ``django-admin`` commands::
|
||||
* ``django-admin`` commands:
|
||||
|
||||
.. code-block:: rst
|
||||
|
||||
.. django-admin:: migrate
|
||||
|
||||
To link, use ``:djadmin:`migrate```.
|
||||
|
||||
* ``django-admin`` command-line options::
|
||||
* ``django-admin`` command-line options:
|
||||
|
||||
.. code-block:: rst
|
||||
|
||||
.. django-admin-option:: --traceback
|
||||
|
||||
To link, use ``:option:`command_name --traceback``` (or omit ``command_name``
|
||||
for the options shared by all commands like ``--verbosity``).
|
||||
|
||||
* Links to Trac tickets (typically reserved for patch release notes)::
|
||||
* Links to Trac tickets (typically reserved for patch release notes):
|
||||
|
||||
.. code-block:: rst
|
||||
|
||||
:ticket:`12345`
|
||||
|
||||
@ -304,7 +324,9 @@ command-line examples involving ``django-admin``, ``manage.py``, ``python``,
|
||||
etc.). In the HTML documentation, it renders a two-tab UI, with one tab showing
|
||||
a Unix-style command prompt and a second tab showing a Windows prompt.
|
||||
|
||||
For example, you can replace this fragment::
|
||||
For example, you can replace this fragment:
|
||||
|
||||
.. code-block:: rst
|
||||
|
||||
use this command:
|
||||
|
||||
@ -312,7 +334,9 @@ For example, you can replace this fragment::
|
||||
|
||||
$ python manage.py shell
|
||||
|
||||
with this one::
|
||||
with this one:
|
||||
|
||||
.. code-block:: rst
|
||||
|
||||
use this command:
|
||||
|
||||
@ -368,7 +392,9 @@ In other words, since we only keep these annotations around for two releases,
|
||||
it's nice to be able to remove the annotation and its contents without having
|
||||
to reflow, reindent, or edit the surrounding text. For example, instead of
|
||||
putting the entire description of a new or changed feature in a block, do
|
||||
something like this::
|
||||
something like this:
|
||||
|
||||
.. code-block:: rst
|
||||
|
||||
.. class:: Author(first_name, last_name, middle_name=None)
|
||||
|
||||
@ -392,7 +418,9 @@ redundant to do so as these annotations render as "New in Django A.B:" and
|
||||
"Changed in Django A.B", respectively.
|
||||
|
||||
If a function, attribute, etc. is added, it's also okay to use a
|
||||
``versionadded`` annotation like this::
|
||||
``versionadded`` annotation like this:
|
||||
|
||||
.. code-block:: rst
|
||||
|
||||
.. attribute:: Author.middle_name
|
||||
|
||||
|
@ -2,8 +2,6 @@
|
||||
How is Django Formed?
|
||||
=====================
|
||||
|
||||
.. highlight:: console
|
||||
|
||||
This document explains how to release Django.
|
||||
|
||||
**Please, keep these instructions up-to-date if you make changes!** The point
|
||||
@ -56,7 +54,9 @@ You'll need a few things before getting started:
|
||||
``you@example.com`` is the email address associated with the key you want to
|
||||
use.
|
||||
|
||||
* An install of some required Python packages::
|
||||
* An install of some required Python packages:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
$ python -m pip install wheel twine
|
||||
|
||||
@ -117,7 +117,9 @@ any time leading up to the actual release:
|
||||
#. If this is a feature release, ensure translations from Transifex have been
|
||||
integrated. This is typically done by a separate translation's manager
|
||||
rather than the releaser, but here are the steps. Provided you have an
|
||||
account on Transifex::
|
||||
account on Transifex:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
$ python scripts/manage_translations.py fetch
|
||||
|
||||
@ -125,7 +127,9 @@ any time leading up to the actual release:
|
||||
Sometimes there are validation errors which need to be debugged, so avoid
|
||||
doing this task immediately before a release is needed.
|
||||
|
||||
#. :ref:`Update the django-admin manual page <django-admin-manpage>`::
|
||||
#. :ref:`Update the django-admin manual page <django-admin-manpage>`:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
$ cd docs
|
||||
$ make man
|
||||
@ -135,7 +139,9 @@ any time leading up to the actual release:
|
||||
and then commit the changed man page.
|
||||
|
||||
#. If this is the alpha release of a new series, create a new stable branch
|
||||
from main. For example, when releasing Django 3.1::
|
||||
from main. For example, when releasing Django 3.1:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
$ git checkout -b stable/3.1.x origin/main
|
||||
$ git push origin -u stable/3.1.x:stable/3.1.x
|
||||
@ -148,7 +154,9 @@ any time leading up to the actual release:
|
||||
#. If this is the "dot zero" release of a new series, create a new branch from
|
||||
the current stable branch in the `django-docs-translations
|
||||
<https://github.com/django/django-docs-translations>`_ repository. For
|
||||
example, when releasing Django 2.2::
|
||||
example, when releasing Django 2.2:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
$ git checkout -b stable/2.2.x origin/stable/2.1.x
|
||||
$ git push origin stable/2.2.x:stable/2.2.x
|
||||
@ -176,7 +184,9 @@ OK, this is the fun part, where we actually push out a release!
|
||||
__ https://djangoci.com
|
||||
|
||||
#. A release always begins from a release branch, so you should make sure
|
||||
you're on a stable branch and up-to-date. For example::
|
||||
you're on a stable branch and up-to-date. For example:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
$ git checkout stable/1.5.x
|
||||
$ git pull
|
||||
@ -184,7 +194,9 @@ OK, this is the fun part, where we actually push out a release!
|
||||
#. If this is a security release, merge the appropriate patches from
|
||||
``django-security``. Rebase these patches as necessary to make each one a
|
||||
plain commit on the release branch rather than a merge commit. To ensure
|
||||
this, merge them with the ``--ff-only`` flag; for example::
|
||||
this, merge them with the ``--ff-only`` flag; for example:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
$ git checkout stable/1.5.x
|
||||
$ git merge --ff-only security/1.5.x
|
||||
@ -214,7 +226,9 @@ OK, this is the fun part, where we actually push out a release!
|
||||
classifier in ``setup.cfg`` to reflect this. Otherwise, make sure the
|
||||
classifier is set to ``Development Status :: 5 - Production/Stable``.
|
||||
|
||||
#. Tag the release using ``git tag``. For example::
|
||||
#. Tag the release using ``git tag``. For example:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
$ git tag --sign --message="Tag 1.5.1" 1.5.1
|
||||
|
||||
@ -227,7 +241,9 @@ OK, this is the fun part, where we actually push out a release!
|
||||
#. Run ``make -f extras/Makefile`` to generate the release packages. This will
|
||||
create the release packages in a ``dist/`` directory.
|
||||
|
||||
#. Generate the hashes of the release packages::
|
||||
#. Generate the hashes of the release packages:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
$ cd dist
|
||||
$ md5sum *
|
||||
@ -303,19 +319,25 @@ Making the release(s) available to the public
|
||||
Now you're ready to actually put the release out there. To do this:
|
||||
|
||||
#. Upload the release package(s) to the djangoproject server, replacing
|
||||
A.B. with the appropriate version number, e.g. 1.5 for a 1.5.x release::
|
||||
A.B. with the appropriate version number, e.g. 1.5 for a 1.5.x release:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
$ scp Django-* djangoproject.com:/home/www/www/media/releases/A.B
|
||||
|
||||
If this is the alpha release of a new series, you will need to create the
|
||||
directory A.B.
|
||||
|
||||
#. Upload the checksum file(s)::
|
||||
#. Upload the checksum file(s):
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
$ scp Django-A.B.C.checksum.txt.asc djangoproject.com:/home/www/www/media/pgp/Django-A.B.C.checksum.txt
|
||||
|
||||
#. Test that the release packages install correctly using ``pip``. Here's one
|
||||
method::
|
||||
method:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
$ RELEASE_VERSION='1.7.2'
|
||||
$ MAJOR_VERSION=`echo $RELEASE_VERSION| cut -c 1-3`
|
||||
@ -340,7 +362,9 @@ Now you're ready to actually put the release out there. To do this:
|
||||
files).
|
||||
|
||||
#. Upload the release packages to PyPI (for pre-releases, only upload the wheel
|
||||
file)::
|
||||
file):
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
$ twine upload -s dist/*
|
||||
|
||||
@ -368,7 +392,9 @@ Now you're ready to actually put the release out there. To do this:
|
||||
for the previous release. Update djangoproject.com's `robots.docs.txt`__
|
||||
file by copying entries from ``manage_translations.py robots_txt`` from the
|
||||
current stable branch in the ``django-docs-translations`` repository. For
|
||||
example, when releasing Django 2.2::
|
||||
example, when releasing Django 2.2:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
$ git checkout stable/2.2.x
|
||||
$ git pull
|
||||
|
@ -357,7 +357,9 @@ 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::
|
||||
method we added, with this error:
|
||||
|
||||
.. code-block:: pytb
|
||||
|
||||
ImportError: cannot import name 'make_toast' from 'django.shortcuts'
|
||||
|
||||
@ -407,7 +409,9 @@ Writing Documentation
|
||||
|
||||
This is a new feature, so it should be documented. Open the file
|
||||
``docs/topics/http/shortcuts.txt`` and add the following at the end of the
|
||||
file::
|
||||
file:
|
||||
|
||||
.. code-block:: rst
|
||||
|
||||
``make_toast()``
|
||||
================
|
||||
@ -421,7 +425,9 @@ file::
|
||||
Since this new feature will be in an upcoming release it is also added to the
|
||||
release notes for the next version of Django. Open the release notes for the
|
||||
latest version in ``docs/releases/``, which at time of writing is ``2.2.txt``.
|
||||
Add a note under the "Minor Features" header::
|
||||
Add a note under the "Minor Features" header:
|
||||
|
||||
.. code-block:: rst
|
||||
|
||||
:mod:`django.shortcuts`
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
@ -20,7 +20,9 @@ Get the latest version of Python at https://www.python.org/downloads/ or with
|
||||
your operating system's package manager.
|
||||
|
||||
You can verify that Python is installed by typing ``python`` from your shell;
|
||||
you should see something like::
|
||||
you should see something like:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
Python 3.x.y
|
||||
[GCC 4.x] on linux
|
||||
|
@ -66,7 +66,9 @@ Enjoy the free API
|
||||
|
||||
With that, you've got a free, and rich, :doc:`Python API </topics/db/queries>`
|
||||
to access your data. The API is created on the fly, no code generation
|
||||
necessary::
|
||||
necessary:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
# Import the models we created from our "news" app
|
||||
>>> from news.models import Article, Reporter
|
||||
|
@ -53,7 +53,9 @@ projects and ready to publish for others to install and use.
|
||||
Your project and your reusable app
|
||||
==================================
|
||||
|
||||
After the previous tutorials, our project should look like this::
|
||||
After the previous tutorials, our project should look like this:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
mysite/
|
||||
manage.py
|
||||
@ -256,9 +258,11 @@ this. For a small app like polls, this process isn't too difficult.
|
||||
|
||||
#. It's optional, but recommended, to include detailed documentation with your
|
||||
app. Create an empty directory ``django-polls/docs`` for future
|
||||
documentation. Add an additional line to ``django-polls/MANIFEST.in``::
|
||||
documentation. Add an additional line to ``django-polls/MANIFEST.in``:
|
||||
|
||||
recursive-include docs *
|
||||
.. code-block:: text
|
||||
|
||||
recursive-include docs *
|
||||
|
||||
Note that the ``docs`` directory won't be included in your package unless
|
||||
you add some files to it. Many Django apps also provide their documentation
|
||||
@ -291,16 +295,20 @@ working. We'll now fix this by installing our new ``django-polls`` package.
|
||||
solution (see below).
|
||||
|
||||
#. To install the package, use pip (you already :ref:`installed it
|
||||
<installing-reusable-apps-prerequisites>`, right?)::
|
||||
<installing-reusable-apps-prerequisites>`, right?):
|
||||
|
||||
python -m pip install --user django-polls/dist/django-polls-0.1.tar.gz
|
||||
.. code-block:: shell
|
||||
|
||||
python -m pip install --user django-polls/dist/django-polls-0.1.tar.gz
|
||||
|
||||
#. With luck, your Django project should now work correctly again. Run the
|
||||
server again to confirm this.
|
||||
|
||||
#. To uninstall the package, use pip::
|
||||
#. To uninstall the package, use pip:
|
||||
|
||||
python -m pip uninstall django-polls
|
||||
.. code-block:: shell
|
||||
|
||||
python -m pip uninstall django-polls
|
||||
|
||||
Publishing your app
|
||||
===================
|
||||
|
@ -76,7 +76,9 @@ work, see :ref:`troubleshooting-django-admin`.
|
||||
Put your code in some directory **outside** of the document root, such as
|
||||
:file:`/home/mycode`.
|
||||
|
||||
Let's look at what :djadmin:`startproject` created::
|
||||
Let's look at what :djadmin:`startproject` created:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
mysite/
|
||||
manage.py
|
||||
@ -224,7 +226,9 @@ and type this command:
|
||||
|
||||
$ python manage.py startapp polls
|
||||
|
||||
That'll create a directory :file:`polls`, which is laid out like this::
|
||||
That'll create a directory :file:`polls`, which is laid out like this:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
polls/
|
||||
__init__.py
|
||||
@ -257,7 +261,9 @@ This is the simplest view possible in Django. To call the view, we need to map
|
||||
it to a URL - and for this we need a URLconf.
|
||||
|
||||
To create a URLconf in the polls directory, create a file called ``urls.py``.
|
||||
Your app directory should now look like::
|
||||
Your app directory should now look like:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
polls/
|
||||
__init__.py
|
||||
|
@ -381,7 +381,9 @@ We're using this instead of simply typing "python", because :file:`manage.py`
|
||||
sets the :envvar:`DJANGO_SETTINGS_MODULE` environment variable, which gives
|
||||
Django the Python import path to your :file:`mysite/settings.py` file.
|
||||
|
||||
Once you're in the shell, explore the :doc:`database API </topics/db/queries>`::
|
||||
Once you're in the shell, explore the :doc:`database API </topics/db/queries>`:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from polls.models import Choice, Question # Import the model classes we just wrote.
|
||||
|
||||
@ -468,7 +470,9 @@ you aren't familiar with time zone handling in Python, you can learn more in
|
||||
the :doc:`time zone support docs </topics/i18n/timezones>`.
|
||||
|
||||
Save these changes and start a new Python interactive shell by running
|
||||
``python manage.py shell`` again::
|
||||
``python manage.py shell`` again:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from polls.models import Choice, Question
|
||||
|
||||
|
@ -206,7 +206,9 @@ In the terminal, we can run our test:
|
||||
|
||||
$ python manage.py test polls
|
||||
|
||||
and you'll see something like::
|
||||
and you'll see something like:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
Creating test database for alias 'default'...
|
||||
System check identified no issues (0 silenced).
|
||||
@ -267,7 +269,9 @@ past:
|
||||
now = timezone.now()
|
||||
return now - datetime.timedelta(days=1) <= self.pub_date <= now
|
||||
|
||||
and run the test again::
|
||||
and run the test again:
|
||||
|
||||
.. code-block:: pytb
|
||||
|
||||
Creating test database for alias 'default'...
|
||||
System check identified no issues (0 silenced).
|
||||
@ -376,13 +380,17 @@ it earlier, check it before continuing.
|
||||
|
||||
Next we need to import the test client class (later in ``tests.py`` we will use
|
||||
the :class:`django.test.TestCase` class, which comes with its own client, so
|
||||
this won't be required)::
|
||||
this won't be required):
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.test import Client
|
||||
>>> # create an instance of the client for our use
|
||||
>>> client = Client()
|
||||
|
||||
With that ready, we can ask the client to do some work for us::
|
||||
With that ready, we can ask the client to do some work for us:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> # get a response from '/'
|
||||
>>> response = client.get('/')
|
||||
|
@ -9,7 +9,9 @@ and provides introspection. It also maintains a list of available :doc:`models
|
||||
</topics/db/models>`.
|
||||
|
||||
This registry is called :attr:`~django.apps.apps` and it's available in
|
||||
:mod:`django.apps`::
|
||||
:mod:`django.apps`:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.apps import apps
|
||||
>>> apps.get_app_config('admin').verbose_name
|
||||
|
@ -18,9 +18,11 @@ Multiple object mixins
|
||||
path('objects/page<int:page>/', PaginatedView.as_view()),
|
||||
|
||||
* Pass the page number via the ``page`` query-string parameter. For
|
||||
example, a URL would look like this::
|
||||
example, a URL would look like this:
|
||||
|
||||
/objects/?page=3
|
||||
.. code-block:: text
|
||||
|
||||
/objects/?page=3
|
||||
|
||||
These values and lists are 1-based, not 0-based, so the first page would be
|
||||
represented as page ``1``.
|
||||
@ -29,7 +31,9 @@ Multiple object mixins
|
||||
</topics/pagination>`.
|
||||
|
||||
As a special case, you are also permitted to use ``last`` as a value for
|
||||
``page``::
|
||||
``page``:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
/objects/?page=last
|
||||
|
||||
|
@ -3201,7 +3201,9 @@ with an instance namespace corresponding to the name of the Site instance.
|
||||
|
||||
So - if you wanted to get a reference to the Change view for a particular
|
||||
``Choice`` object (from the polls application) in the default admin, you would
|
||||
call::
|
||||
call:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.urls import reverse
|
||||
>>> c = Choice.objects.get(...)
|
||||
@ -3214,7 +3216,9 @@ This will find the first registered instance of the admin application
|
||||
If you want to find a URL in a specific admin instance, provide the name of
|
||||
that instance as a ``current_app`` hint to the reverse call. For example,
|
||||
if you specifically wanted the admin view from the admin instance named
|
||||
``custom``, you would need to call::
|
||||
``custom``, you would need to call:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> change_url = reverse('admin:polls_choice_change', args=(c.id,), current_app='custom')
|
||||
|
||||
|
@ -121,7 +121,9 @@ model it represents, or to retrieve objects from that model:
|
||||
|
||||
For example, we could look up the
|
||||
:class:`~django.contrib.contenttypes.models.ContentType` for the
|
||||
:class:`~django.contrib.auth.models.User` model::
|
||||
:class:`~django.contrib.auth.models.User` model:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.contrib.contenttypes.models import ContentType
|
||||
>>> user_type = ContentType.objects.get(app_label='auth', model='user')
|
||||
@ -130,7 +132,9 @@ For example, we could look up the
|
||||
|
||||
And then use it to query for a particular
|
||||
:class:`~django.contrib.auth.models.User`, or to get access
|
||||
to the ``User`` model class::
|
||||
to the ``User`` model class:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> user_type.model_class()
|
||||
<class 'django.contrib.auth.models.User'>
|
||||
@ -219,7 +223,9 @@ The :meth:`~ContentTypeManager.get_for_model()` method is especially
|
||||
useful when you know you need to work with a
|
||||
:class:`ContentType <django.contrib.contenttypes.models.ContentType>` but don't
|
||||
want to go to the trouble of obtaining the model's metadata to perform a manual
|
||||
lookup::
|
||||
lookup:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.contrib.auth.models import User
|
||||
>>> ContentType.objects.get_for_model(User)
|
||||
@ -340,7 +346,9 @@ This will enable an API similar to the one used for a normal
|
||||
:class:`~django.db.models.ForeignKey`;
|
||||
each ``TaggedItem`` will have a ``content_object`` field that returns the
|
||||
object it's related to, and you can also assign to that field or use it when
|
||||
creating a ``TaggedItem``::
|
||||
creating a ``TaggedItem``:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.contrib.auth.models import User
|
||||
>>> guido = User.objects.get(username='Guido')
|
||||
@ -351,7 +359,9 @@ creating a ``TaggedItem``::
|
||||
|
||||
If the related object is deleted, the ``content_type`` and ``object_id`` fields
|
||||
remain set to their original values and the ``GenericForeignKey`` returns
|
||||
``None``::
|
||||
``None``:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> guido.delete()
|
||||
>>> t.content_object # returns None
|
||||
@ -360,7 +370,9 @@ Due to the way :class:`~django.contrib.contenttypes.fields.GenericForeignKey`
|
||||
is implemented, you cannot use such fields directly with filters (``filter()``
|
||||
and ``exclude()``, for example) via the database API. Because a
|
||||
:class:`~django.contrib.contenttypes.fields.GenericForeignKey` isn't a
|
||||
normal field object, these examples will *not* work::
|
||||
normal field object, these examples will *not* work:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
# This will fail
|
||||
>>> TaggedItem.objects.filter(content_object=guido)
|
||||
@ -393,7 +405,9 @@ a "reverse" generic relationship to enable an additional API. For example::
|
||||
tags = GenericRelation(TaggedItem)
|
||||
|
||||
``Bookmark`` instances will each have a ``tags`` attribute, which can
|
||||
be used to retrieve their associated ``TaggedItems``::
|
||||
be used to retrieve their associated ``TaggedItems``:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> b = Bookmark(url='https://www.djangoproject.com/')
|
||||
>>> b.save()
|
||||
@ -405,7 +419,9 @@ be used to retrieve their associated ``TaggedItems``::
|
||||
<QuerySet [<TaggedItem: django>, <TaggedItem: python>]>
|
||||
|
||||
You can also use ``add()``, ``create()``, or ``set()`` to create
|
||||
relationships::
|
||||
relationships:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> t3 = TaggedItem(tag='Web development')
|
||||
>>> b.tags.add(t3, bulk=False)
|
||||
@ -417,7 +433,9 @@ relationships::
|
||||
>>> b.tags.all()
|
||||
<QuerySet [<TaggedItem: django>, <TaggedItem: Web development>]>
|
||||
|
||||
The ``remove()`` call will bulk delete the specified model objects::
|
||||
The ``remove()`` call will bulk delete the specified model objects:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> b.tags.remove(t3)
|
||||
>>> b.tags.all()
|
||||
@ -426,7 +444,9 @@ The ``remove()`` call will bulk delete the specified model objects::
|
||||
<QuerySet [<TaggedItem: django>]>
|
||||
|
||||
The ``clear()`` method can be used to bulk delete all related objects for an
|
||||
instance::
|
||||
instance:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> b.tags.clear()
|
||||
>>> b.tags.all()
|
||||
@ -440,14 +460,18 @@ Defining :class:`~django.contrib.contenttypes.fields.GenericRelation` with
|
||||
tags = GenericRelation(TaggedItem, related_query_name='bookmark')
|
||||
|
||||
This enables filtering, ordering, and other query operations on ``Bookmark``
|
||||
from ``TaggedItem``::
|
||||
from ``TaggedItem``:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> # Get all tags belonging to bookmarks containing `django` in the url
|
||||
>>> TaggedItem.objects.filter(bookmark__url__contains='django')
|
||||
<QuerySet [<TaggedItem: django>, <TaggedItem: python>]>
|
||||
|
||||
If you don't add the ``related_query_name``, you can do the same types of
|
||||
lookups manually::
|
||||
lookups manually:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> bookmarks = Bookmark.objects.filter(url__contains='django')
|
||||
>>> bookmark_type = ContentType.objects.get_for_model(Bookmark)
|
||||
@ -491,7 +515,9 @@ Generic relations and aggregation
|
||||
|
||||
:doc:`Django's database aggregation API </topics/db/aggregation>` works with a
|
||||
:class:`~django.contrib.contenttypes.fields.GenericRelation`. For example, you
|
||||
can find out how many tags all the bookmarks have::
|
||||
can find out how many tags all the bookmarks have:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Bookmark.objects.aggregate(Count('tags'))
|
||||
{'tags__count': 3}
|
||||
|
@ -37,13 +37,17 @@ Creating and Saving Models with Geometry Fields
|
||||
===============================================
|
||||
|
||||
Here is an example of how to create a geometry object (assuming the ``Zipcode``
|
||||
model)::
|
||||
model):
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from zipcode.models import Zipcode
|
||||
>>> z = Zipcode(code=77096, poly='POLYGON(( 10 10, 10 20, 20 20, 20 15, 10 10))')
|
||||
>>> z.save()
|
||||
|
||||
:class:`~django.contrib.gis.geos.GEOSGeometry` objects may also be used to save geometric models::
|
||||
:class:`~django.contrib.gis.geos.GEOSGeometry` objects may also be used to save geometric models:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.contrib.gis.geos import GEOSGeometry
|
||||
>>> poly = GEOSGeometry('POLYGON(( 10 10, 10 20, 20 20, 20 15, 10 10))')
|
||||
@ -53,7 +57,9 @@ model)::
|
||||
Moreover, if the ``GEOSGeometry`` is in a different coordinate system (has a
|
||||
different SRID value) than that of the field, then it will be implicitly
|
||||
transformed into the SRID of the model's field, using the spatial database's
|
||||
transform procedure::
|
||||
transform procedure:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> poly_3084 = GEOSGeometry('POLYGON(( 10 10, 10 20, 20 20, 20 15, 10 10))', srid=3084) # SRID 3084 is 'NAD83(HARN) / Texas Centric Lambert Conformal'
|
||||
>>> z = Zipcode(code=78212, poly=poly_3084)
|
||||
@ -82,14 +88,18 @@ The raster field will therefore accept any input that is accepted by the
|
||||
:class:`~django.contrib.gis.gdal.GDALRaster` constructor.
|
||||
|
||||
Here is an example of how to create a raster object from a raster file
|
||||
``volcano.tif`` (assuming the ``Elevation`` model)::
|
||||
``volcano.tif`` (assuming the ``Elevation`` model):
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from elevation.models import Elevation
|
||||
>>> dem = Elevation(name='Volcano', rast='/path/to/raster/volcano.tif')
|
||||
>>> dem.save()
|
||||
|
||||
:class:`~django.contrib.gis.gdal.GDALRaster` objects may also be used to save
|
||||
raster models::
|
||||
raster models:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.contrib.gis.gdal import GDALRaster
|
||||
>>> rast = GDALRaster({'width': 10, 'height': 10, 'name': 'Canyon', 'srid': 4326,
|
||||
@ -97,7 +107,9 @@ raster models::
|
||||
>>> dem = Elevation(name='Canyon', rast=rast)
|
||||
>>> dem.save()
|
||||
|
||||
Note that this equivalent to::
|
||||
Note that this equivalent to:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> dem = Elevation.objects.create(
|
||||
... name='Canyon',
|
||||
@ -125,12 +137,16 @@ Geometry Lookups
|
||||
----------------
|
||||
|
||||
Geographic queries with geometries take the following general form (assuming
|
||||
the ``Zipcode`` model used in the :doc:`model-api`)::
|
||||
the ``Zipcode`` model used in the :doc:`model-api`):
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> qs = Zipcode.objects.filter(<field>__<lookup_type>=<parameter>)
|
||||
>>> qs = Zipcode.objects.exclude(...)
|
||||
|
||||
For example::
|
||||
For example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> qs = Zipcode.objects.filter(poly__contains=pnt)
|
||||
>>> qs = Elevation.objects.filter(poly__contains=rst)
|
||||
@ -157,13 +173,17 @@ used to pass a band index. On the right hand side, a tuple of the raster and
|
||||
band index can be specified.
|
||||
|
||||
This results in the following general form for lookups involving rasters
|
||||
(assuming the ``Elevation`` model used in the :doc:`model-api`)::
|
||||
(assuming the ``Elevation`` model used in the :doc:`model-api`):
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> qs = Elevation.objects.filter(<field>__<lookup_type>=<parameter>)
|
||||
>>> qs = Elevation.objects.filter(<field>__<band_index>__<lookup_type>=<parameter>)
|
||||
>>> qs = Elevation.objects.filter(<field>__<lookup_type>=(<raster_input, <band_index>)
|
||||
|
||||
For example::
|
||||
For example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> qs = Elevation.objects.filter(rast__contains=geom)
|
||||
>>> qs = Elevation.objects.filter(rast__contains=rst)
|
||||
@ -256,7 +276,9 @@ For example, let's say we have a ``SouthTexasCity`` model (from the
|
||||
# is used, units are in meters.
|
||||
point = models.PointField(srid=32140)
|
||||
|
||||
Then distance queries may be performed as follows::
|
||||
Then distance queries may be performed as follows:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.contrib.gis.geos import GEOSGeometry
|
||||
>>> from django.contrib.gis.measure import D # ``D`` is a shortcut for ``Distance``
|
||||
@ -273,7 +295,9 @@ Then distance queries may be performed as follows::
|
||||
Raster queries work the same way by replacing the geometry field ``point`` with
|
||||
a raster field, or the ``pnt`` object with a raster object, or both. To specify
|
||||
the band index of a raster input on the right hand side, a 3-tuple can be
|
||||
passed to the lookup as follows::
|
||||
passed to the lookup as follows:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> qs = SouthTexasCity.objects.filter(point__distance_gte=(rst, 2, D(km=7)))
|
||||
|
||||
|
@ -8,7 +8,9 @@ Geographic Database Functions
|
||||
The functions documented on this page allow users to access geographic database
|
||||
functions to be used in annotations, aggregations, or filters in Django.
|
||||
|
||||
Example::
|
||||
Example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.contrib.gis.db.models.functions import Length
|
||||
>>> Track.objects.annotate(length=Length('line')).filter(length__gt=100)
|
||||
@ -61,7 +63,9 @@ Accepts a single geographic field or expression and returns a `GeoJSON
|
||||
is not a complete GeoJSON structure but only the ``geometry`` key content of a
|
||||
GeoJSON structure. See also :doc:`/ref/contrib/gis/serializers`.
|
||||
|
||||
Example::
|
||||
Example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> City.objects.annotate(json=AsGeoJSON('point')).get(name='Chicago').json
|
||||
{"type":"Point","coordinates":[-87.65018,41.85039]}
|
||||
@ -94,7 +98,9 @@ SpatiaLite
|
||||
Accepts a single geographic field or expression and returns a `Geographic Markup
|
||||
Language (GML)`__ representation of the geometry.
|
||||
|
||||
Example::
|
||||
Example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> qs = Zipcode.objects.annotate(gml=AsGML('poly'))
|
||||
>>> print(qs[0].gml)
|
||||
@ -123,7 +129,9 @@ __ https://en.wikipedia.org/wiki/Geography_Markup_Language
|
||||
Accepts a single geographic field or expression and returns a `Keyhole Markup
|
||||
Language (KML)`__ representation of the geometry.
|
||||
|
||||
Example::
|
||||
Example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> qs = Zipcode.objects.annotate(kml=AsKML('poly'))
|
||||
>>> print(qs[0].kml)
|
||||
@ -176,7 +184,9 @@ Oracle, `PostGIS <https://postgis.net/docs/ST_AsBinary.html>`__, SpatiaLite
|
||||
Accepts a single geographic field or expression and returns a `Well-known
|
||||
binary (WKB)`_ representation of the geometry.
|
||||
|
||||
Example::
|
||||
Example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> bytes(City.objects.annotate(wkb=AsWKB('point')).get(name='Chelyabinsk').wkb)
|
||||
b'\x01\x01\x00\x00\x00]3\xf9f\x9b\x91K@\x00X\x1d9\xd2\xb9N@'
|
||||
@ -193,7 +203,9 @@ Oracle, `PostGIS <https://postgis.net/docs/ST_AsText.html>`__, SpatiaLite
|
||||
Accepts a single geographic field or expression and returns a `Well-known text
|
||||
(WKT)`_ representation of the geometry.
|
||||
|
||||
Example::
|
||||
Example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> City.objects.annotate(wkt=AsWKT('point')).get(name='Chelyabinsk').wkt
|
||||
'POINT (55.137555 61.451728)'
|
||||
@ -289,7 +301,9 @@ resource-intensive).
|
||||
|
||||
In the following example, the distance from the city of Hobart to every other
|
||||
:class:`~django.contrib.gis.db.models.PointField` in the ``AustraliaCity``
|
||||
queryset is calculated::
|
||||
queryset is calculated:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.contrib.gis.db.models.functions import Distance
|
||||
>>> pnt = AustraliaCity.objects.get(name='Hobart').point
|
||||
|
@ -36,7 +36,9 @@ The GDAL/OGR tools described here are designed to help you read in
|
||||
your geospatial data, in order for most of them to be useful you have
|
||||
to have some data to work with. If you're starting out and don't yet
|
||||
have any data of your own to use, GeoDjango tests contain a number of
|
||||
data sets that you can use for testing. You can download them here::
|
||||
data sets that you can use for testing. You can download them here:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
$ wget https://raw.githubusercontent.com/django/django/main/tests/gis_tests/data/cities/cities.{shp,prj,shx,dbf}
|
||||
$ wget https://raw.githubusercontent.com/django/django/main/tests/gis_tests/data/rasters/raster.tif
|
||||
@ -75,7 +77,9 @@ each feature in that layer.
|
||||
Once you've created your ``DataSource``, you can find out how many layers
|
||||
of data it contains by accessing the :attr:`layer_count` property, or
|
||||
(equivalently) by using the ``len()`` function. For information on
|
||||
accessing the layers of data themselves, see the next section::
|
||||
accessing the layers of data themselves, see the next section:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.contrib.gis.gdal import DataSource
|
||||
>>> ds = DataSource('/path/to/your/cities.shp')
|
||||
@ -110,7 +114,9 @@ __ https://gdal.org/drivers/vector/
|
||||
Typically, all the features in a given layer have the same geometry type.
|
||||
The :attr:`geom_type` property of a layer is an :class:`OGRGeomType` that
|
||||
identifies the feature type. We can use it to print out some basic
|
||||
information about each layer in a :class:`DataSource`::
|
||||
information about each layer in a :class:`DataSource`:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> for layer in ds:
|
||||
... print('Layer "%s": %i %ss' % (layer.name, len(layer), layer.geom_type.name))
|
||||
@ -120,7 +126,9 @@ __ https://gdal.org/drivers/vector/
|
||||
The example output is from the cities data source, loaded above, which
|
||||
evidently contains one layer, called ``"cities"``, which contains three
|
||||
point features. For simplicity, the examples below assume that you've
|
||||
stored that layer in the variable ``layer``::
|
||||
stored that layer in the variable ``layer``:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> layer = ds[0]
|
||||
|
||||
@ -128,19 +136,25 @@ __ https://gdal.org/drivers/vector/
|
||||
|
||||
Returns the name of this layer in the data source.
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> layer.name
|
||||
'cities'
|
||||
|
||||
.. attribute:: num_feat
|
||||
|
||||
Returns the number of features in the layer. Same as ``len(layer)``::
|
||||
Returns the number of features in the layer. Same as ``len(layer)``:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> layer.num_feat
|
||||
3
|
||||
|
||||
.. attribute:: geom_type
|
||||
|
||||
Returns the geometry type of the layer, as an :class:`OGRGeomType` object::
|
||||
Returns the geometry type of the layer, as an :class:`OGRGeomType` object:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> layer.geom_type.name
|
||||
'Point'
|
||||
@ -148,14 +162,18 @@ __ https://gdal.org/drivers/vector/
|
||||
.. attribute:: num_fields
|
||||
|
||||
Returns the number of fields in the layer, i.e the number of fields of
|
||||
data associated with each feature in the layer::
|
||||
data associated with each feature in the layer:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> layer.num_fields
|
||||
4
|
||||
|
||||
.. attribute:: fields
|
||||
|
||||
Returns a list of the names of each of the fields in this layer::
|
||||
Returns a list of the names of each of the fields in this layer:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> layer.fields
|
||||
['Name', 'Population', 'Density', 'Created']
|
||||
@ -163,7 +181,9 @@ __ https://gdal.org/drivers/vector/
|
||||
.. attribute field_types
|
||||
|
||||
Returns a list of the data types of each of the fields in this layer. These
|
||||
are subclasses of ``Field``, discussed below::
|
||||
are subclasses of ``Field``, discussed below:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> [ft.__name__ for ft in layer.field_types]
|
||||
['OFTString', 'OFTReal', 'OFTReal', 'OFTDate']
|
||||
@ -171,7 +191,9 @@ __ https://gdal.org/drivers/vector/
|
||||
.. attribute:: field_widths
|
||||
|
||||
Returns a list of the maximum field widths for each of the fields in this
|
||||
layer::
|
||||
layer:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> layer.field_widths
|
||||
[80, 11, 24, 10]
|
||||
@ -179,14 +201,18 @@ __ https://gdal.org/drivers/vector/
|
||||
.. attribute:: field_precisions
|
||||
|
||||
Returns a list of the numeric precisions for each of the fields in this
|
||||
layer. This is meaningless (and set to zero) for non-numeric fields::
|
||||
layer. This is meaningless (and set to zero) for non-numeric fields:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> layer.field_precisions
|
||||
[0, 0, 15, 0]
|
||||
|
||||
.. attribute:: extent
|
||||
|
||||
Returns the spatial extent of this layer, as an :class:`Envelope` object::
|
||||
Returns the spatial extent of this layer, as an :class:`Envelope` object:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> layer.extent.tuple
|
||||
(-104.609252, 29.763374, -95.23506, 38.971823)
|
||||
@ -194,7 +220,9 @@ __ https://gdal.org/drivers/vector/
|
||||
.. attribute:: srs
|
||||
|
||||
Property that returns the :class:`SpatialReference` associated with this
|
||||
layer::
|
||||
layer:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> print(layer.srs)
|
||||
GEOGCS["GCS_WGS_1984",
|
||||
@ -212,7 +240,9 @@ __ https://gdal.org/drivers/vector/
|
||||
layer. A spatial filter can only be set with an :class:`OGRGeometry`
|
||||
instance, a 4-tuple extent, or ``None``. When set with something other than
|
||||
``None``, only features that intersect the filter will be returned when
|
||||
iterating over the layer::
|
||||
iterating over the layer:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> print(layer.spatial_filter)
|
||||
None
|
||||
@ -233,7 +263,9 @@ __ https://gdal.org/drivers/vector/
|
||||
.. method:: get_fields()
|
||||
|
||||
A method that returns a list of the values of a given field for each
|
||||
feature in the layer::
|
||||
feature in the layer:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> layer.get_fields('Name')
|
||||
['Pueblo', 'Lawrence', 'Houston']
|
||||
@ -243,7 +275,9 @@ __ https://gdal.org/drivers/vector/
|
||||
A method that returns a list containing the geometry of each feature in the
|
||||
layer. If the optional argument ``geos`` is set to ``True`` then the
|
||||
geometries are converted to :class:`~django.contrib.gis.geos.GEOSGeometry`
|
||||
objects. Otherwise, they are returned as :class:`OGRGeometry` objects::
|
||||
objects. Otherwise, they are returned as :class:`OGRGeometry` objects:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> [pt.tuple for pt in layer.get_geoms()]
|
||||
[(-104.609252, 38.255001), (-95.23506, 38.971823), (-95.363151, 29.763374)]
|
||||
@ -273,7 +307,9 @@ __ https://gdal.org/drivers/vector/
|
||||
|
||||
.. attribute:: geom
|
||||
|
||||
Returns the geometry for this feature, as an ``OGRGeometry`` object::
|
||||
Returns the geometry for this feature, as an ``OGRGeometry`` object:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> city.geom.tuple
|
||||
(-104.609252, 38.255001)
|
||||
@ -281,7 +317,9 @@ __ https://gdal.org/drivers/vector/
|
||||
.. attribute:: get
|
||||
|
||||
A method that returns the value of the given field (specified by name)
|
||||
for this feature, **not** a ``Field`` wrapper object::
|
||||
for this feature, **not** a ``Field`` wrapper object:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> city.get('Population')
|
||||
102121
|
||||
@ -309,7 +347,9 @@ __ https://gdal.org/drivers/vector/
|
||||
|
||||
.. attribute:: fid
|
||||
|
||||
Returns the feature identifier within the layer::
|
||||
Returns the feature identifier within the layer:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> city.fid
|
||||
0
|
||||
@ -317,7 +357,9 @@ __ https://gdal.org/drivers/vector/
|
||||
.. attribute:: layer_name
|
||||
|
||||
Returns the name of the :class:`Layer` that the feature came from. This
|
||||
will be the same for all features in a given layer::
|
||||
will be the same for all features in a given layer:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> city.layer_name
|
||||
'cities'
|
||||
@ -325,7 +367,9 @@ __ https://gdal.org/drivers/vector/
|
||||
.. attribute:: index
|
||||
|
||||
A method that returns the index of the given field name. This will be the
|
||||
same for all features in a given layer::
|
||||
same for all features in a given layer:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> city.index('Population')
|
||||
1
|
||||
@ -337,7 +381,9 @@ __ https://gdal.org/drivers/vector/
|
||||
|
||||
.. attribute:: name
|
||||
|
||||
Returns the name of this field::
|
||||
Returns the name of this field:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> city['Name'].name
|
||||
'Name'
|
||||
@ -345,14 +391,18 @@ __ https://gdal.org/drivers/vector/
|
||||
.. attribute:: type
|
||||
|
||||
Returns the OGR type of this field, as an integer. The ``FIELD_CLASSES``
|
||||
dictionary maps these values onto subclasses of ``Field``::
|
||||
dictionary maps these values onto subclasses of ``Field``:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> city['Density'].type
|
||||
2
|
||||
|
||||
.. attribute:: type_name
|
||||
|
||||
Returns a string with the name of the data type of this field::
|
||||
Returns a string with the name of the data type of this field:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> city['Name'].type_name
|
||||
'String'
|
||||
@ -361,14 +411,18 @@ __ https://gdal.org/drivers/vector/
|
||||
|
||||
Returns the value of this field. The ``Field`` class itself returns the
|
||||
value as a string, but each subclass returns the value in the most
|
||||
appropriate form::
|
||||
appropriate form:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> city['Population'].value
|
||||
102121
|
||||
|
||||
.. attribute:: width
|
||||
|
||||
Returns the width of this field::
|
||||
Returns the width of this field:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> city['Name'].width
|
||||
80
|
||||
@ -376,35 +430,45 @@ __ https://gdal.org/drivers/vector/
|
||||
.. attribute:: precision
|
||||
|
||||
Returns the numeric precision of this field. This is meaningless (and set
|
||||
to zero) for non-numeric fields::
|
||||
to zero) for non-numeric fields:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> city['Density'].precision
|
||||
15
|
||||
|
||||
.. method:: as_double()
|
||||
|
||||
Returns the value of the field as a double (float)::
|
||||
Returns the value of the field as a double (float):
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> city['Density'].as_double()
|
||||
874.7
|
||||
|
||||
.. method:: as_int()
|
||||
|
||||
Returns the value of the field as an integer::
|
||||
Returns the value of the field as an integer:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> city['Population'].as_int()
|
||||
102121
|
||||
|
||||
.. method:: as_string()
|
||||
|
||||
Returns the value of the field as a string::
|
||||
Returns the value of the field as a string:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> city['Name'].as_string()
|
||||
'Pueblo'
|
||||
|
||||
.. method:: as_datetime()
|
||||
|
||||
Returns the value of the field as a tuple of date and time components::
|
||||
Returns the value of the field as a tuple of date and time components:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> city['Created'].as_datetime()
|
||||
(c_long(1999), c_long(5), c_long(23), c_long(0), c_long(0), c_long(0), c_long(0))
|
||||
@ -432,7 +496,9 @@ OGR Geometries
|
||||
around OGR's internal geometry representation. Thus, they allow for more
|
||||
efficient access to data when using :class:`DataSource`. Unlike its GEOS
|
||||
counterpart, :class:`OGRGeometry` supports spatial reference systems and
|
||||
coordinate transformation::
|
||||
coordinate transformation:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.contrib.gis.gdal import OGRGeometry
|
||||
>>> polygon = OGRGeometry('POLYGON((0 0, 5 0, 5 5, 0 5))')
|
||||
@ -478,7 +544,9 @@ coordinate transformation::
|
||||
.. attribute:: dimension
|
||||
|
||||
Returns the number of coordinated dimensions of the geometry, i.e. 0
|
||||
for points, 1 for lines, and so forth::
|
||||
for points, 1 for lines, and so forth:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>> polygon.dimension
|
||||
2
|
||||
@ -490,14 +558,18 @@ coordinate transformation::
|
||||
|
||||
.. attribute:: geom_count
|
||||
|
||||
Returns the number of elements in this geometry::
|
||||
Returns the number of elements in this geometry:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> polygon.geom_count
|
||||
1
|
||||
|
||||
.. attribute:: point_count
|
||||
|
||||
Returns the number of points used to describe this geometry::
|
||||
Returns the number of points used to describe this geometry:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> polygon.point_count
|
||||
4
|
||||
@ -516,7 +588,9 @@ coordinate transformation::
|
||||
|
||||
.. attribute:: geom_name
|
||||
|
||||
Returns the name of the type of this geometry::
|
||||
Returns the name of the type of this geometry:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> polygon.geom_name
|
||||
'POLYGON'
|
||||
@ -524,7 +598,9 @@ coordinate transformation::
|
||||
.. attribute:: area
|
||||
|
||||
Returns the area of this geometry, or 0 for geometries that do not contain
|
||||
an area::
|
||||
an area:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> polygon.area
|
||||
25.0
|
||||
@ -536,7 +612,9 @@ coordinate transformation::
|
||||
.. attribute:: extent
|
||||
|
||||
Returns the envelope of this geometry as a 4-tuple, instead of as an
|
||||
:class:`Envelope` object::
|
||||
:class:`Envelope` object:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> point.extent
|
||||
(0.0, 0.0, 5.0, 5.0)
|
||||
@ -547,7 +625,9 @@ coordinate transformation::
|
||||
``None`` if no spatial reference system has been assigned to it.
|
||||
If assigned, accessing this property returns a :class:`SpatialReference`
|
||||
object. It may be set with another :class:`SpatialReference` object,
|
||||
or any input that :class:`SpatialReference` accepts. Example::
|
||||
or any input that :class:`SpatialReference` accepts. Example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> city.geom.srs.name
|
||||
'GCS_WGS_1984'
|
||||
@ -566,21 +646,27 @@ coordinate transformation::
|
||||
|
||||
.. attribute:: gml
|
||||
|
||||
Returns a string representation of this geometry in GML format::
|
||||
Returns a string representation of this geometry in GML format:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> OGRGeometry('POINT(1 2)').gml
|
||||
'<gml:Point><gml:coordinates>1,2</gml:coordinates></gml:Point>'
|
||||
|
||||
.. attribute:: hex
|
||||
|
||||
Returns a string representation of this geometry in HEX WKB format::
|
||||
Returns a string representation of this geometry in HEX WKB format:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> OGRGeometry('POINT(1 2)').hex
|
||||
'0101000000000000000000F03F0000000000000040'
|
||||
|
||||
.. attribute:: json
|
||||
|
||||
Returns a string representation of this geometry in JSON format::
|
||||
Returns a string representation of this geometry in JSON format:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> OGRGeometry('POINT(1 2)').json
|
||||
'{ "type": "Point", "coordinates": [ 1.000000, 2.000000 ] }'
|
||||
@ -592,7 +678,9 @@ coordinate transformation::
|
||||
.. attribute:: wkb_size
|
||||
|
||||
Returns the size of the WKB buffer needed to hold a WKB representation
|
||||
of this geometry::
|
||||
of this geometry:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> OGRGeometry('POINT(1 2)').wkb_size
|
||||
21
|
||||
@ -616,7 +704,9 @@ coordinate transformation::
|
||||
.. method:: close_rings()
|
||||
|
||||
If there are any rings within this geometry that have not been closed,
|
||||
this routine will do so by adding the starting point to the end::
|
||||
this routine will do so by adding the starting point to the end:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> triangle = OGRGeometry('LINEARRING (0 0,0 1,1 0)')
|
||||
>>> triangle.close_rings()
|
||||
@ -706,7 +796,9 @@ coordinate transformation::
|
||||
.. attribute:: tuple
|
||||
|
||||
Returns the coordinates of a point geometry as a tuple, the
|
||||
coordinates of a line geometry as a tuple of tuples, and so forth::
|
||||
coordinates of a line geometry as a tuple of tuples, and so forth:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> OGRGeometry('POINT (1 2)').tuple
|
||||
(1.0, 2.0)
|
||||
@ -721,14 +813,18 @@ coordinate transformation::
|
||||
|
||||
.. attribute:: x
|
||||
|
||||
Returns the X coordinate of this point::
|
||||
Returns the X coordinate of this point:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> OGRGeometry('POINT (1 2)').x
|
||||
1.0
|
||||
|
||||
.. attribute:: y
|
||||
|
||||
Returns the Y coordinate of this point::
|
||||
Returns the Y coordinate of this point:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> OGRGeometry('POINT (1 2)').y
|
||||
2.0
|
||||
@ -736,7 +832,9 @@ coordinate transformation::
|
||||
.. attribute:: z
|
||||
|
||||
Returns the Z coordinate of this point, or ``None`` if the point does not
|
||||
have a Z coordinate::
|
||||
have a Z coordinate:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> OGRGeometry('POINT (1 2 3)').z
|
||||
3.0
|
||||
@ -745,14 +843,18 @@ coordinate transformation::
|
||||
|
||||
.. attribute:: x
|
||||
|
||||
Returns a list of X coordinates in this line::
|
||||
Returns a list of X coordinates in this line:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> OGRGeometry('LINESTRING (1 2,3 4)').x
|
||||
[1.0, 3.0]
|
||||
|
||||
.. attribute:: y
|
||||
|
||||
Returns a list of Y coordinates in this line::
|
||||
Returns a list of Y coordinates in this line:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> OGRGeometry('LINESTRING (1 2,3 4)').y
|
||||
[2.0, 4.0]
|
||||
@ -760,7 +862,9 @@ coordinate transformation::
|
||||
.. attribute:: z
|
||||
|
||||
Returns a list of Z coordinates in this line, or ``None`` if the line does
|
||||
not have Z coordinates::
|
||||
not have Z coordinates:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> OGRGeometry('LINESTRING (1 2 3,4 5 6)').z
|
||||
[3.0, 6.0]
|
||||
@ -794,7 +898,9 @@ coordinate transformation::
|
||||
.. class:: OGRGeomType(type_input)
|
||||
|
||||
This class allows for the representation of an OGR geometry type
|
||||
in any of several ways::
|
||||
in any of several ways:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.contrib.gis.gdal import OGRGeomType
|
||||
>>> gt1 = OGRGeomType(3) # Using an integer for the type
|
||||
@ -805,14 +911,18 @@ coordinate transformation::
|
||||
|
||||
.. attribute:: name
|
||||
|
||||
Returns a short-hand string form of the OGR Geometry type::
|
||||
Returns a short-hand string form of the OGR Geometry type:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> gt1.name
|
||||
'Polygon'
|
||||
|
||||
.. attribute:: num
|
||||
|
||||
Returns the number corresponding to the OGR geometry type::
|
||||
Returns the number corresponding to the OGR geometry type:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> gt1.num
|
||||
3
|
||||
@ -820,7 +930,9 @@ coordinate transformation::
|
||||
.. attribute:: django
|
||||
|
||||
Returns the Django field type (a subclass of GeometryField) to use for
|
||||
storing this OGR type, or ``None`` if there is no appropriate Django type::
|
||||
storing this OGR type, or ``None`` if there is no appropriate Django type:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> gt1.django
|
||||
'PolygonField'
|
||||
@ -885,7 +997,9 @@ Coordinate System Objects
|
||||
* A shorthand string for well-known standards (``'WGS84'``, ``'WGS72'``,
|
||||
``'NAD27'``, ``'NAD83'``)
|
||||
|
||||
Example::
|
||||
Example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> wgs84 = SpatialReference('WGS84') # shorthand string
|
||||
>>> wgs84 = SpatialReference(4326) # EPSG code
|
||||
@ -907,7 +1021,9 @@ Coordinate System Objects
|
||||
|
||||
Returns the value of the given string attribute node, ``None`` if the node
|
||||
doesn't exist. Can also take a tuple as a parameter, (target, child), where
|
||||
child is the index of the attribute in the WKT. For example::
|
||||
child is the index of the attribute in the WKT. For example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> wkt = 'GEOGCS["WGS 84", DATUM["WGS_1984, ... AUTHORITY["EPSG","4326"]]')
|
||||
>>> srs = SpatialReference(wkt) # could also use 'WGS84', or 4326
|
||||
@ -1068,7 +1184,9 @@ Coordinate System Objects
|
||||
Represents a coordinate system transform. It is initialized with two
|
||||
:class:`SpatialReference`, representing the source and target coordinate
|
||||
systems, respectively. These objects should be used when performing the same
|
||||
coordinate transformation repeatedly on different geometries::
|
||||
coordinate transformation repeatedly on different geometries:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> ct = CoordTransform(SpatialReference('WGS84'), SpatialReference('NAD83'))
|
||||
>>> for feat in layer:
|
||||
@ -1721,7 +1839,9 @@ Key Default Usage
|
||||
|
||||
The following example uses some of the options available for the
|
||||
`GTiff driver`__. The result is a compressed signed byte raster with an
|
||||
internal tiling scheme. The internal tiles have a block size of 23 by 23::
|
||||
internal tiling scheme. The internal tiles have a block size of 23 by 23:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> GDALRaster({
|
||||
... 'driver': 'GTiff',
|
||||
@ -1787,7 +1907,9 @@ from a remote storage or returned from a view without being written to disk.
|
||||
``/vsimem/``.
|
||||
|
||||
Input provided as ``bytes`` has to be a full binary representation of a file.
|
||||
For instance::
|
||||
For instance:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
# Read a raster as a file object from a remote source.
|
||||
>>> from urllib.request import urlopen
|
||||
@ -1807,7 +1929,9 @@ dictionary representation and provide a ``name`` argument that starts with
|
||||
of the raster.
|
||||
|
||||
Here's how to create a raster and return it as a file in an
|
||||
:class:`~django.http.HttpResponse`::
|
||||
:class:`~django.http.HttpResponse`:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.http import HttpResponse
|
||||
>>> rst = GDALRaster({
|
||||
@ -1838,7 +1962,9 @@ Compressed rasters
|
||||
|
||||
Instead decompressing the file and instantiating the resulting raster, GDAL can
|
||||
directly access compressed files using the ``/vsizip/``, ``/vsigzip/``, or
|
||||
``/vsitar/`` virtual filesystems::
|
||||
``/vsitar/`` virtual filesystems:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.contrib.gis.gdal import GDALRaster
|
||||
>>> rst = GDALRaster('/vsizip/path/to/your/file.zip/path/to/raster.tif')
|
||||
@ -1852,7 +1978,9 @@ GDAL can support online resources and storage providers transparently. As long
|
||||
as it's built with such capabilities.
|
||||
|
||||
To access a public raster file with no authentication, you can use
|
||||
``/vsicurl/``::
|
||||
``/vsicurl/``:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.contrib.gis.gdal import GDALRaster
|
||||
>>> rst = GDALRaster('/vsicurl/https://example.com/raster.tif')
|
||||
|
@ -31,7 +31,9 @@ __ https://github.com/maxmind/libmaxminddb/
|
||||
Example
|
||||
=======
|
||||
|
||||
Here is an example of its usage::
|
||||
Here is an example of its usage:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.contrib.gis.geoip2 import GeoIP2
|
||||
>>> g = GeoIP2()
|
||||
|
@ -856,7 +856,9 @@ Keyword Argument Description
|
||||
__ https://docs.oracle.com/en/database/oracle/oracle-database/21/spatl/
|
||||
spatial-concepts.html#GUID-CE10AB14-D5EA-43BA-A647-DAC9EEF41EE6
|
||||
|
||||
Example::
|
||||
Example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.contrib.gis.db.models import Extent, Union
|
||||
>>> WorldBorder.objects.aggregate(Extent('mpoly'), Union('mpoly'))
|
||||
@ -886,7 +888,9 @@ Oracle, SpatiaLite
|
||||
Returns the extent of all ``geo_field`` in the ``QuerySet`` as a four-tuple,
|
||||
comprising the lower left coordinate and the upper right coordinate.
|
||||
|
||||
Example::
|
||||
Example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> qs = City.objects.filter(name__in=('Houston', 'Dallas')).aggregate(Extent('poly'))
|
||||
>>> print(qs['poly__extent'])
|
||||
@ -903,7 +907,9 @@ Returns the 3D extent of all ``geo_field`` in the ``QuerySet`` as a six-tuple,
|
||||
comprising the lower left coordinate and upper right coordinate (each with x, y,
|
||||
and z coordinates).
|
||||
|
||||
Example::
|
||||
Example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> qs = City.objects.filter(name__in=('Houston', 'Dallas')).aggregate(Extent3D('poly'))
|
||||
>>> print(qs['poly__extent3d'])
|
||||
@ -920,7 +926,9 @@ SpatiaLite
|
||||
Returns a ``LineString`` constructed from the point field geometries in the
|
||||
``QuerySet``. Currently, ordering the queryset has no effect.
|
||||
|
||||
Example::
|
||||
Example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> qs = City.objects.filter(name__in=('Houston', 'Dallas')).aggregate(MakeLine('poly'))
|
||||
>>> print(qs['poly__makeline'])
|
||||
@ -944,7 +952,9 @@ large querysets.
|
||||
If the computation time for using this method is too expensive, consider
|
||||
using :class:`Collect` instead.
|
||||
|
||||
Example::
|
||||
Example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> u = Zipcode.objects.aggregate(Union(poly)) # This may take a long time.
|
||||
>>> u = Zipcode.objects.filter(poly__within=bbox).aggregate(Union(poly)) # A more sensible approach.
|
||||
|
@ -50,7 +50,9 @@ Creating a Geometry
|
||||
|
||||
:class:`GEOSGeometry` objects may be created in a few ways. The first is
|
||||
to simply instantiate the object on some spatial input -- the following
|
||||
are examples of creating the same geometry from WKT, HEX, WKB, and GeoJSON::
|
||||
are examples of creating the same geometry from WKT, HEX, WKB, and GeoJSON:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.contrib.gis.geos import GEOSGeometry
|
||||
>>> pnt = GEOSGeometry('POINT(5 23)') # WKT
|
||||
@ -60,12 +62,16 @@ are examples of creating the same geometry from WKT, HEX, WKB, and GeoJSON::
|
||||
|
||||
Another option is to use the constructor for the specific geometry type
|
||||
that you wish to create. For example, a :class:`Point` object may be
|
||||
created by passing in the X and Y coordinates into its constructor::
|
||||
created by passing in the X and Y coordinates into its constructor:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.contrib.gis.geos import Point
|
||||
>>> pnt = Point(5, 23)
|
||||
|
||||
All these constructors take the keyword argument ``srid``. For example::
|
||||
All these constructors take the keyword argument ``srid``. For example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.contrib.gis.geos import GEOSGeometry, LineString, Point
|
||||
>>> print(GEOSGeometry('POINT (0 0)', srid=4326))
|
||||
@ -76,7 +82,9 @@ All these constructors take the keyword argument ``srid``. For example::
|
||||
SRID=32140;POINT (0 0)
|
||||
|
||||
Finally, there is the :func:`fromfile` factory method which returns a
|
||||
:class:`GEOSGeometry` object from a file::
|
||||
:class:`GEOSGeometry` object from a file:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.contrib.gis.geos import fromfile
|
||||
>>> pnt = fromfile('/path/to/pnt.wkt')
|
||||
@ -97,14 +105,18 @@ Geometries are Pythonic
|
||||
-----------------------
|
||||
:class:`GEOSGeometry` objects are 'Pythonic', in other words components may
|
||||
be accessed, modified, and iterated over using standard Python conventions.
|
||||
For example, you can iterate over the coordinates in a :class:`Point`::
|
||||
For example, you can iterate over the coordinates in a :class:`Point`:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> pnt = Point(5, 23)
|
||||
>>> [coord for coord in pnt]
|
||||
[5.0, 23.0]
|
||||
|
||||
With any geometry object, the :attr:`GEOSGeometry.coords` property
|
||||
may be used to get the geometry coordinates as a Python tuple::
|
||||
may be used to get the geometry coordinates as a Python tuple:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> pnt.coords
|
||||
(5.0, 23.0)
|
||||
@ -112,7 +124,9 @@ may be used to get the geometry coordinates as a Python tuple::
|
||||
You can get/set geometry components using standard Python indexing
|
||||
techniques. However, what is returned depends on the geometry type
|
||||
of the object. For example, indexing on a :class:`LineString`
|
||||
returns a coordinate tuple::
|
||||
returns a coordinate tuple:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.contrib.gis.geos import LineString
|
||||
>>> line = LineString((0, 0), (0, 50), (50, 50), (50, 0), (0, 0))
|
||||
@ -122,7 +136,9 @@ returns a coordinate tuple::
|
||||
(50.0, 0.0)
|
||||
|
||||
Whereas indexing on a :class:`Polygon` will return the ring
|
||||
(a :class:`LinearRing` object) corresponding to the index::
|
||||
(a :class:`LinearRing` object) corresponding to the index:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.contrib.gis.geos import Polygon
|
||||
>>> poly = Polygon( ((0.0, 0.0), (0.0, 50.0), (50.0, 50.0), (50.0, 0.0), (0.0, 0.0)) )
|
||||
@ -132,7 +148,9 @@ Whereas indexing on a :class:`Polygon` will return the ring
|
||||
(50.0, 0.0)
|
||||
|
||||
In addition, coordinates/components of the geometry may added or modified,
|
||||
just like a Python list::
|
||||
just like a Python list:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> line[0] = (1.0, 1.0)
|
||||
>>> line.pop()
|
||||
@ -141,7 +159,9 @@ just like a Python list::
|
||||
>>> line.coords
|
||||
((1.0, 1.0), (0.0, 50.0), (50.0, 50.0), (50.0, 0.0), (1.0, 1.0))
|
||||
|
||||
Geometries support set-like operators::
|
||||
Geometries support set-like operators:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.contrib.gis.geos import LineString
|
||||
>>> ls1 = LineString((0, 0), (2, 2))
|
||||
@ -160,7 +180,9 @@ Geometries support set-like operators::
|
||||
The :class:`~GEOSGeometry` equality operator uses
|
||||
:meth:`~GEOSGeometry.equals_exact`, not :meth:`~GEOSGeometry.equals`, i.e.
|
||||
it requires the compared geometries to have the same coordinates in the
|
||||
same positions with the same SRIDs::
|
||||
same positions with the same SRIDs:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.contrib.gis.geos import LineString
|
||||
>>> ls1 = LineString((0, 0), (1, 1))
|
||||
@ -191,7 +213,9 @@ given ``geo_input`` argument, and then assumes the proper geometry subclass
|
||||
|
||||
The ``srid`` parameter, if given, is set as the SRID of the created geometry if
|
||||
``geo_input`` doesn't have an SRID. If different SRIDs are provided through the
|
||||
``geo_input`` and ``srid`` parameters, ``ValueError`` is raised::
|
||||
``geo_input`` and ``srid`` parameters, ``ValueError`` is raised:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.contrib.gis.geos import GEOSGeometry
|
||||
>>> GEOSGeometry('POINT EMPTY', srid=4326).ewkt
|
||||
@ -246,7 +270,9 @@ Properties
|
||||
|
||||
.. attribute:: GEOSGeometry.geom_type
|
||||
|
||||
Returns a string corresponding to the type of geometry. For example::
|
||||
Returns a string corresponding to the type of geometry. For example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> pnt = GEOSGeometry('POINT(5 23)')
|
||||
>>> pnt.geom_type
|
||||
@ -307,7 +333,9 @@ Properties
|
||||
.. attribute:: GEOSGeometry.srid
|
||||
|
||||
Property that may be used to retrieve or set the SRID associated with the
|
||||
geometry. For example::
|
||||
geometry. For example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> pnt = Point(5, 23)
|
||||
>>> print(pnt.srid)
|
||||
@ -669,7 +697,9 @@ Other Properties & Methods
|
||||
|
||||
Converts this geometry to canonical form. If the ``clone`` keyword is set,
|
||||
then the geometry is not modified and a normalized clone of the geometry is
|
||||
returned instead::
|
||||
returned instead:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> g = MultiPoint(Point(0, 0), Point(2, 2), Point(1, 1))
|
||||
>>> print(g)
|
||||
@ -685,13 +715,17 @@ Other Properties & Methods
|
||||
|
||||
``Point`` objects are instantiated using arguments that represent the
|
||||
component coordinates of the point or with a single sequence coordinates.
|
||||
For example, the following are equivalent::
|
||||
For example, the following are equivalent:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> pnt = Point(5, 23)
|
||||
>>> pnt = Point([5, 23])
|
||||
|
||||
Empty ``Point`` objects may be instantiated by passing no arguments or an
|
||||
empty sequence. The following are equivalent::
|
||||
empty sequence. The following are equivalent:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> pnt = Point()
|
||||
>>> pnt = Point([])
|
||||
@ -703,19 +737,25 @@ Other Properties & Methods
|
||||
|
||||
``LineString`` objects are instantiated using arguments that are either a
|
||||
sequence of coordinates or :class:`Point` objects. For example, the
|
||||
following are equivalent::
|
||||
following are equivalent:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> ls = LineString((0, 0), (1, 1))
|
||||
>>> ls = LineString(Point(0, 0), Point(1, 1))
|
||||
|
||||
In addition, ``LineString`` objects may also be created by passing in a
|
||||
single sequence of coordinate or :class:`Point` objects::
|
||||
single sequence of coordinate or :class:`Point` objects:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> ls = LineString( ((0, 0), (1, 1)) )
|
||||
>>> ls = LineString( [Point(0, 0), Point(1, 1)] )
|
||||
|
||||
Empty ``LineString`` objects may be instantiated by passing no arguments
|
||||
or an empty sequence. The following are equivalent::
|
||||
or an empty sequence. The following are equivalent:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> ls = LineString()
|
||||
>>> ls = LineString([])
|
||||
@ -732,7 +772,9 @@ Other Properties & Methods
|
||||
``LinearRing`` objects are constructed in the exact same way as
|
||||
:class:`LineString` objects, however the coordinates must be *closed*, in
|
||||
other words, the first coordinates must be the same as the last
|
||||
coordinates. For example::
|
||||
coordinates. For example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> ls = LinearRing((0, 0), (0, 1), (1, 1), (0, 0))
|
||||
|
||||
@ -751,7 +793,9 @@ Other Properties & Methods
|
||||
``Polygon`` objects may be instantiated by passing in parameters that
|
||||
represent the rings of the polygon. The parameters must either be
|
||||
:class:`LinearRing` instances, or a sequence that may be used to construct a
|
||||
:class:`LinearRing`::
|
||||
:class:`LinearRing`:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> ext_coords = ((0, 0), (0, 1), (1, 1), (1, 0), (0, 0))
|
||||
>>> int_coords = ((0.4, 0.4), (0.4, 0.6), (0.6, 0.6), (0.6, 0.4), (0.4, 0.4))
|
||||
@ -773,7 +817,9 @@ Other Properties & Methods
|
||||
or ``>``, but as the comparison is made through Polygon's
|
||||
:class:`LineString`, it does not mean much (but is consistent and quick).
|
||||
You can always force the comparison with the :attr:`~GEOSGeometry.area`
|
||||
property::
|
||||
property:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> if poly_1.area > poly_2.area:
|
||||
>>> pass
|
||||
@ -789,7 +835,9 @@ Geometry Collections
|
||||
.. class:: MultiPoint(*args, **kwargs)
|
||||
|
||||
``MultiPoint`` objects may be instantiated by passing in :class:`Point`
|
||||
objects as arguments, or a single sequence of :class:`Point` objects::
|
||||
objects as arguments, or a single sequence of :class:`Point` objects:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> mp = MultiPoint(Point(0, 0), Point(1, 1))
|
||||
>>> mp = MultiPoint( (Point(0, 0), Point(1, 1)) )
|
||||
@ -801,7 +849,9 @@ Geometry Collections
|
||||
|
||||
``MultiLineString`` objects may be instantiated by passing in
|
||||
:class:`LineString` objects as arguments, or a single sequence of
|
||||
:class:`LineString` objects::
|
||||
:class:`LineString` objects:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> ls1 = LineString((0, 0), (1, 1))
|
||||
>>> ls2 = LineString((2, 2), (3, 3))
|
||||
@ -823,7 +873,9 @@ Geometry Collections
|
||||
.. class:: MultiPolygon(*args, **kwargs)
|
||||
|
||||
``MultiPolygon`` objects may be instantiated by passing :class:`Polygon`
|
||||
objects as arguments, or a single sequence of :class:`Polygon` objects::
|
||||
objects as arguments, or a single sequence of :class:`Polygon` objects:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> p1 = Polygon( ((0, 0), (0, 1), (1, 1), (0, 0)) )
|
||||
>>> p2 = Polygon( ((1, 1), (1, 2), (2, 2), (1, 1)) )
|
||||
@ -837,7 +889,9 @@ Geometry Collections
|
||||
|
||||
``GeometryCollection`` objects may be instantiated by passing in other
|
||||
:class:`GEOSGeometry` as arguments, or a single sequence of
|
||||
:class:`GEOSGeometry` objects::
|
||||
:class:`GEOSGeometry` objects:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> poly = Polygon( ((0, 0), (0, 1), (1, 1), (0, 0)) )
|
||||
>>> gc = GeometryCollection(Point(0, 0), MultiPoint(Point(0, 0), Point(1, 1)), poly)
|
||||
@ -856,7 +910,9 @@ geometry can be orders of magnitude faster -- the more complex the geometry
|
||||
that is prepared, the larger the speedup in the operation. For more information,
|
||||
please consult the `GEOS wiki page on prepared geometries <https://trac.osgeo.org/geos/wiki/PreparedGeometry>`_.
|
||||
|
||||
For example::
|
||||
For example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.contrib.gis.geos import Point, Polygon
|
||||
>>> poly = Polygon.from_bbox((0, 0, 5, 5))
|
||||
@ -899,7 +955,9 @@ Geometry Factories
|
||||
:type file_h: a Python ``file`` object or a string path to the file
|
||||
:rtype: a :class:`GEOSGeometry` corresponding to the spatial data in the file
|
||||
|
||||
Example::
|
||||
Example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.contrib.gis.geos import fromfile
|
||||
>>> g = fromfile('/home/bob/geom.wkt')
|
||||
@ -915,7 +973,9 @@ Geometry Factories
|
||||
``fromstr(string, srid)`` is equivalent to
|
||||
:class:`GEOSGeometry(string, srid) <GEOSGeometry>`.
|
||||
|
||||
Example::
|
||||
Example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.contrib.gis.geos import fromstr
|
||||
>>> pnt = fromstr('POINT(-90.5 29.5)', srid=4326)
|
||||
@ -931,7 +991,9 @@ and/or WKT input given to their ``read(geom)`` method.
|
||||
|
||||
.. class:: WKBReader
|
||||
|
||||
Example::
|
||||
Example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.contrib.gis.geos import WKBReader
|
||||
>>> wkb_r = WKBReader()
|
||||
@ -940,7 +1002,9 @@ and/or WKT input given to their ``read(geom)`` method.
|
||||
|
||||
.. class:: WKTReader
|
||||
|
||||
Example::
|
||||
Example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.contrib.gis.geos import WKTReader
|
||||
>>> wkt_r = WKTReader()
|
||||
@ -967,7 +1031,9 @@ include the SRID value (in other words, EWKB).
|
||||
.. method:: WKBWriter.write(geom)
|
||||
|
||||
Returns the WKB of the given geometry as a Python ``buffer`` object.
|
||||
Example::
|
||||
Example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.contrib.gis.geos import Point, WKBWriter
|
||||
>>> pnt = Point(1, 1)
|
||||
@ -977,7 +1043,9 @@ include the SRID value (in other words, EWKB).
|
||||
|
||||
.. method:: WKBWriter.write_hex(geom)
|
||||
|
||||
Returns WKB of the geometry in hexadecimal. Example::
|
||||
Returns WKB of the geometry in hexadecimal. Example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.contrib.gis.geos import Point, WKBWriter
|
||||
>>> pnt = Point(1, 1)
|
||||
@ -997,7 +1065,9 @@ include the SRID value (in other words, EWKB).
|
||||
1 Little Endian (e.g., compatible with x86 systems)
|
||||
=============== =================================================
|
||||
|
||||
Example::
|
||||
Example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.contrib.gis.geos import Point, WKBWriter
|
||||
>>> wkb_w = WKBWriter()
|
||||
@ -1020,7 +1090,9 @@ include the SRID value (in other words, EWKB).
|
||||
3 Output 3D WKB.
|
||||
============ ===========================
|
||||
|
||||
Example::
|
||||
Example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.contrib.gis.geos import Point, WKBWriter
|
||||
>>> wkb_w = WKBWriter()
|
||||
@ -1036,7 +1108,9 @@ include the SRID value (in other words, EWKB).
|
||||
.. attribute:: WKBWriter.srid
|
||||
|
||||
Set this property with a boolean to indicate whether the SRID of the
|
||||
geometry should be included with the WKB representation. Example::
|
||||
geometry should be included with the WKB representation. Example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.contrib.gis.geos import Point, WKBWriter
|
||||
>>> wkb_w = WKBWriter()
|
||||
@ -1055,7 +1129,9 @@ include the SRID value (in other words, EWKB).
|
||||
|
||||
.. method:: WKTWriter.write(geom)
|
||||
|
||||
Returns the WKT of the given geometry. Example::
|
||||
Returns the WKT of the given geometry. Example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.contrib.gis.geos import Point, WKTWriter
|
||||
>>> pnt = Point(1, 1)
|
||||
@ -1072,6 +1148,8 @@ include the SRID value (in other words, EWKB).
|
||||
This property is used to enable or disable trimming of
|
||||
unnecessary decimals.
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.contrib.gis.geos import Point, WKTWriter
|
||||
>>> pnt = Point(1, 1)
|
||||
>>> wkt_w = WKTWriter()
|
||||
|
@ -85,7 +85,9 @@ is required.
|
||||
.. note::
|
||||
|
||||
On Linux platforms, it may be necessary to run the ``ldconfig`` command
|
||||
after installing each library. For example::
|
||||
after installing each library. For example:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
$ sudo make install
|
||||
$ sudo ldconfig
|
||||
@ -106,19 +108,25 @@ internal geometry representation used by GeoDjango (it's behind the "lazy"
|
||||
geometries). Specifically, the C API library is called (e.g., ``libgeos_c.so``)
|
||||
directly from Python using ctypes.
|
||||
|
||||
First, download GEOS from the GEOS website and untar the source archive::
|
||||
First, download GEOS from the GEOS website and untar the source archive:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
$ wget https://download.osgeo.org/geos/geos-X.Y.Z.tar.bz2
|
||||
$ tar xjf geos-X.Y.Z.tar.bz2
|
||||
|
||||
Then step into the GEOS directory, create a ``build`` folder, and step into
|
||||
it::
|
||||
it:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
$ cd geos-X.Y.Z
|
||||
$ mkdir build
|
||||
$ cd build
|
||||
|
||||
Then build and install the package::
|
||||
Then build and install the package:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
$ cmake -DCMAKE_BUILD_TYPE=Release ..
|
||||
$ cmake --build .
|
||||
@ -149,7 +157,9 @@ If using a binary package of GEOS (e.g., on Ubuntu), you may need to :ref:`binut
|
||||
If your GEOS library is in a non-standard location, or you don't want to
|
||||
modify the system's library path then the :setting:`GEOS_LIBRARY_PATH`
|
||||
setting may be added to your Django settings file with the full path to the
|
||||
GEOS C library. For example::
|
||||
GEOS C library. For example:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
GEOS_LIBRARY_PATH = '/home/bob/local/lib/libgeos_c.so'
|
||||
|
||||
@ -168,18 +178,24 @@ PROJ
|
||||
`PROJ`_ is a library for converting geospatial data to different coordinate
|
||||
reference systems.
|
||||
|
||||
First, download the PROJ source code::
|
||||
First, download the PROJ source code:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
$ wget https://download.osgeo.org/proj/proj-X.Y.Z.tar.gz
|
||||
|
||||
... and datum shifting files (download ``proj-datumgrid-X.Y.tar.gz`` for
|
||||
PROJ < 7.x) [#]_::
|
||||
PROJ < 7.x) [#]_:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
$ wget https://download.osgeo.org/proj/proj-data-X.Y.tar.gz
|
||||
|
||||
Next, untar the source code archive, and extract the datum shifting files in the
|
||||
``data`` subdirectory (use ``nad`` subdirectory for PROJ < 6.x). This must be
|
||||
done *prior* to configuration::
|
||||
done *prior* to configuration:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
$ tar xzf proj-X.Y.Z.tar.gz
|
||||
$ cd proj-X.Y.Z/data
|
||||
@ -190,13 +206,17 @@ For PROJ 9.x and greater, releases only support builds using ``CMake`` (see
|
||||
`PROJ RFC-7`_).
|
||||
|
||||
To build with ``CMake`` ensure your system meets the `build requirements`_.
|
||||
Then create a ``build`` folder in the PROJ directory, and step into it::
|
||||
Then create a ``build`` folder in the PROJ directory, and step into it:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
$ cd proj-X.Y.Z
|
||||
$ mkdir build
|
||||
$ cd build
|
||||
|
||||
Finally, configure, make and install PROJ::
|
||||
Finally, configure, make and install PROJ:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
$ cmake ..
|
||||
$ cmake --build .
|
||||
@ -215,20 +235,26 @@ reading most vector and raster spatial data formats. Currently, GeoDjango only
|
||||
supports :doc:`GDAL's vector data <../gdal>` capabilities [#]_.
|
||||
:ref:`geosbuild` and :ref:`proj4` should be installed prior to building GDAL.
|
||||
|
||||
First download the latest GDAL release version and untar the archive::
|
||||
First download the latest GDAL release version and untar the archive:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
$ wget https://download.osgeo.org/gdal/X.Y.Z/gdal-X.Y.Z.tar.gz
|
||||
$ tar xzf gdal-X.Y.Z.tar.gz
|
||||
|
||||
For GDAL 3.6.x and greater, releases only support builds using ``CMake``. To
|
||||
build with ``CMake`` create a ``build`` folder in the GDAL directory, and step
|
||||
into it::
|
||||
into it:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
$ cd gdal-X.Y.Z
|
||||
$ mkdir build
|
||||
$ cd build
|
||||
|
||||
Finally, configure, make and install GDAL::
|
||||
Finally, configure, make and install GDAL:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
$ cmake ..
|
||||
$ cmake --build .
|
||||
@ -258,7 +284,9 @@ When GeoDjango can't find the GDAL library, configure your :ref:`libsettings`
|
||||
If your GDAL library is in a non-standard location, or you don't want to
|
||||
modify the system's library path then the :setting:`GDAL_LIBRARY_PATH`
|
||||
setting may be added to your Django settings file with the full path to
|
||||
the GDAL library. For example::
|
||||
the GDAL library. For example:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
GDAL_LIBRARY_PATH = '/home/sue/local/lib/libgdal.so'
|
||||
|
||||
|
@ -2,8 +2,6 @@
|
||||
GeoDjango Installation
|
||||
======================
|
||||
|
||||
.. highlight:: console
|
||||
|
||||
Overview
|
||||
========
|
||||
In general, GeoDjango installation requires:
|
||||
@ -141,7 +139,9 @@ A user may set this environment variable to customize the library paths
|
||||
they want to use. The typical library directory for software
|
||||
built from source is ``/usr/local/lib``. Thus, ``/usr/local/lib`` needs
|
||||
to be included in the ``LD_LIBRARY_PATH`` variable. For example, the user
|
||||
could place the following in their bash profile::
|
||||
could place the following in their bash profile:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
export LD_LIBRARY_PATH=/usr/local/lib
|
||||
|
||||
@ -151,7 +151,9 @@ Setting system library path
|
||||
On GNU/Linux systems, there is typically a file in ``/etc/ld.so.conf``, which may include
|
||||
additional paths from files in another directory, such as ``/etc/ld.so.conf.d``.
|
||||
As the root user, add the custom library path (like ``/usr/local/lib``) on a
|
||||
new line in ``ld.so.conf``. This is *one* example of how to do so::
|
||||
new line in ``ld.so.conf``. This is *one* example of how to do so:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
$ sudo echo /usr/local/lib >> /etc/ld.so.conf
|
||||
$ sudo ldconfig
|
||||
@ -159,7 +161,9 @@ new line in ``ld.so.conf``. This is *one* example of how to do so::
|
||||
For OpenSolaris users, the system library path may be modified using the
|
||||
``crle`` utility. Run ``crle`` with no options to see the current configuration
|
||||
and use ``crle -l`` to set with the new library path. Be *very* careful when
|
||||
modifying the system library path::
|
||||
modifying the system library path:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
# crle -l $OLD_PATH:/usr/local/lib
|
||||
|
||||
@ -176,11 +180,15 @@ Linux system then Python's ctypes may not be able to find your library even if
|
||||
your library path is set correctly and geospatial libraries were built perfectly.
|
||||
|
||||
The ``binutils`` package may be installed on Debian and Ubuntu systems using the
|
||||
following command::
|
||||
following command:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
$ sudo apt-get install binutils
|
||||
|
||||
Similarly, on Red Hat and CentOS systems::
|
||||
Similarly, on Red Hat and CentOS systems:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
$ sudo yum install binutils
|
||||
|
||||
@ -221,7 +229,9 @@ __ https://www.python.org/ftp/python/
|
||||
|
||||
You will need to modify the ``PATH`` environment variable in your
|
||||
``.profile`` file so that the new version of Python is used when
|
||||
``python`` is entered at the command-line::
|
||||
``python`` is entered at the command-line:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
export PATH=/Library/Frameworks/Python.framework/Versions/Current/bin:$PATH
|
||||
|
||||
@ -255,7 +265,9 @@ It provides recipes for the GeoDjango prerequisites on Macintosh computers
|
||||
running macOS. Because Homebrew still builds the software from source, `Xcode`_
|
||||
is required.
|
||||
|
||||
Summary::
|
||||
Summary:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
$ brew install postgresql
|
||||
$ brew install postgis
|
||||
@ -287,7 +299,9 @@ MacPorts
|
||||
running macOS. Because MacPorts still builds the software from source,
|
||||
`Xcode`_ is required.
|
||||
|
||||
Summary::
|
||||
Summary:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
$ sudo port install postgresql13-server
|
||||
$ sudo port install geos
|
||||
@ -299,12 +313,16 @@ Summary::
|
||||
.. note::
|
||||
|
||||
You will also have to modify the ``PATH`` in your ``.profile`` so
|
||||
that the MacPorts programs are accessible from the command-line::
|
||||
that the MacPorts programs are accessible from the command-line:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
export PATH=/opt/local/bin:/opt/local/lib/postgresql13/bin
|
||||
|
||||
In addition, add the ``DYLD_FALLBACK_LIBRARY_PATH`` setting so that
|
||||
the libraries can be found by Python::
|
||||
the libraries can be found by Python:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
export DYLD_FALLBACK_LIBRARY_PATH=/opt/local/lib:/opt/local/lib/postgresql13
|
||||
|
||||
@ -434,7 +452,9 @@ psycopg
|
||||
|
||||
The ``psycopg`` Python module provides the interface between Python and the
|
||||
PostgreSQL database. ``psycopg`` can be installed via pip within your Python
|
||||
virtual environment::
|
||||
virtual environment:
|
||||
|
||||
.. code-block:: doscon
|
||||
|
||||
...\> py -m pip install psycopg
|
||||
|
||||
|
@ -35,7 +35,9 @@ Creating a spatial database
|
||||
---------------------------
|
||||
|
||||
PostGIS 2 includes an extension for PostgreSQL that's used to enable spatial
|
||||
functionality::
|
||||
functionality:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
$ createdb <db name>
|
||||
$ psql <db name>
|
||||
@ -74,7 +76,9 @@ To administer the database, you can either use the pgAdmin III program
|
||||
(:menuselection:`Start --> PostgreSQL X --> pgAdmin III`) or the SQL Shell
|
||||
(:menuselection:`Start --> PostgreSQL X --> SQL Shell`). For example, to create
|
||||
a ``geodjango`` spatial database and user, the following may be executed from
|
||||
the SQL Shell as the ``postgres`` user::
|
||||
the SQL Shell as the ``postgres`` user:
|
||||
|
||||
.. code-block:: psql
|
||||
|
||||
postgres# CREATE USER geodjango PASSWORD 'my_passwd';
|
||||
postgres# CREATE DATABASE geodjango OWNER geodjango;
|
||||
|
@ -33,7 +33,9 @@ SQLite
|
||||
------
|
||||
|
||||
Check first if SQLite is compiled with the `R*Tree module`__. Run the sqlite3
|
||||
command line interface and enter the following query::
|
||||
command line interface and enter the following query:
|
||||
|
||||
.. code-block:: sqlite3
|
||||
|
||||
sqlite> CREATE VIRTUAL TABLE testrtree USING rtree(id,minX,maxX,minY,maxY);
|
||||
|
||||
@ -41,14 +43,18 @@ If you obtain an error, you will have to recompile SQLite from source. Otherwise
|
||||
skip this section.
|
||||
|
||||
To install from sources, download the latest amalgamation source archive from
|
||||
the `SQLite download page`__, and extract::
|
||||
the `SQLite download page`__, and extract:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
$ wget https://www.sqlite.org/YYYY/sqlite-amalgamation-XXX0000.zip
|
||||
$ unzip sqlite-amalgamation-XXX0000.zip
|
||||
$ cd sqlite-amalgamation-XXX0000
|
||||
|
||||
Next, run the ``configure`` script -- however the ``CFLAGS`` environment variable
|
||||
needs to be customized so that SQLite knows to build the R*Tree module::
|
||||
needs to be customized so that SQLite knows to build the R*Tree module:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
$ CFLAGS="-DSQLITE_ENABLE_RTREE=1" ./configure
|
||||
$ make
|
||||
@ -64,7 +70,9 @@ SpatiaLite library (``libspatialite``)
|
||||
--------------------------------------
|
||||
|
||||
Get the latest SpatiaLite library source bundle from the
|
||||
`download page`__::
|
||||
`download page`__:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
$ wget https://www.gaia-gis.it/gaia-sins/libspatialite-sources/libspatialite-X.Y.Z.tar.gz
|
||||
$ tar xaf libspatialite-X.Y.Z.tar.gz
|
||||
@ -76,7 +84,9 @@ Get the latest SpatiaLite library source bundle from the
|
||||
.. note::
|
||||
|
||||
For macOS users building from source, the SpatiaLite library *and* tools
|
||||
need to have their ``target`` configured::
|
||||
need to have their ``target`` configured:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
$ ./configure --target=macosx
|
||||
|
||||
@ -93,7 +103,9 @@ Homebrew
|
||||
--------
|
||||
|
||||
`Homebrew`_ handles all the SpatiaLite related packages on your behalf,
|
||||
including SQLite, SpatiaLite, PROJ, and GEOS. Install them like this::
|
||||
including SQLite, SpatiaLite, PROJ, and GEOS. Install them like this:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
$ brew update
|
||||
$ brew install spatialite-tools
|
||||
|
@ -32,7 +32,9 @@ Example
|
||||
=======
|
||||
|
||||
#. You need a GDAL-supported data source, like a shapefile (here we're using
|
||||
a simple polygon shapefile, ``test_poly.shp``, with three features)::
|
||||
a simple polygon shapefile, ``test_poly.shp``, with three features):
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.contrib.gis.gdal import DataSource
|
||||
>>> ds = DataSource('test_poly.shp')
|
||||
@ -62,7 +64,9 @@ Example
|
||||
return 'Name: %s' % self.name
|
||||
|
||||
#. Use :class:`LayerMapping` to extract all the features and place them in the
|
||||
database::
|
||||
database:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.contrib.gis.utils import LayerMapping
|
||||
>>> from geoapp.models import TestGeo
|
||||
@ -206,13 +210,17 @@ should stop excessive memory use when running ``LayerMapping`` scripts.
|
||||
MySQL: ``max_allowed_packet`` error
|
||||
-----------------------------------
|
||||
|
||||
If you encounter the following error when using ``LayerMapping`` and MySQL::
|
||||
If you encounter the following error when using ``LayerMapping`` and MySQL:
|
||||
|
||||
.. code-block:: pytb
|
||||
|
||||
OperationalError: (1153, "Got a packet bigger than 'max_allowed_packet' bytes")
|
||||
|
||||
Then the solution is to increase the value of the ``max_allowed_packet``
|
||||
setting in your MySQL configuration. For example, the default value may
|
||||
be something low like one megabyte -- the setting may be modified in MySQL's
|
||||
configuration file (``my.cnf``) in the ``[mysqld]`` section::
|
||||
configuration file (``my.cnf``) in the ``[mysqld]`` section:
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
max_allowed_packet = 10M
|
||||
|
@ -16,7 +16,9 @@ Example
|
||||
|
||||
:class:`Distance` objects may be instantiated using a keyword argument indicating the
|
||||
context of the units. In the example below, two different distance objects are
|
||||
instantiated in units of kilometers (``km``) and miles (``mi``)::
|
||||
instantiated in units of kilometers (``km``) and miles (``mi``):
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.contrib.gis.measure import D, Distance
|
||||
>>> d1 = Distance(km=5)
|
||||
@ -27,7 +29,9 @@ instantiated in units of kilometers (``km``) and miles (``mi``)::
|
||||
5.0 mi
|
||||
|
||||
For conversions, access the preferred unit attribute to get a converted
|
||||
distance quantity::
|
||||
distance quantity:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> print(d1.mi) # Converting 5 kilometers to miles
|
||||
3.10685596119
|
||||
@ -35,7 +39,9 @@ distance quantity::
|
||||
8.04672
|
||||
|
||||
Moreover, arithmetic operations may be performed between the distance
|
||||
objects::
|
||||
objects:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> print(d1 + d2) # Adding 5 miles to 5 kilometers
|
||||
13.04672 km
|
||||
@ -43,14 +49,18 @@ objects::
|
||||
1.89314403881 mi
|
||||
|
||||
Two :class:`Distance` objects multiplied together will yield an :class:`Area`
|
||||
object, which uses squared units of measure::
|
||||
object, which uses squared units of measure:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> a = d1 * d2 # Returns an Area object.
|
||||
>>> print(a)
|
||||
40.2336 sq_km
|
||||
|
||||
To determine what the attribute abbreviation of a unit is, the ``unit_attname``
|
||||
class method may be used::
|
||||
class method may be used:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> print(Distance.unit_attname('US Survey Foot'))
|
||||
survey_ft
|
||||
@ -117,14 +127,18 @@ Measurement API
|
||||
To initialize a distance object, pass in a keyword corresponding to the
|
||||
desired :ref:`unit attribute name <supported_units>` set with desired
|
||||
value. For example, the following creates a distance object representing 5
|
||||
miles::
|
||||
miles:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> dist = Distance(mi=5)
|
||||
|
||||
.. method:: __getattr__(unit_att)
|
||||
|
||||
Returns the distance value in units corresponding to the given unit
|
||||
attribute. For example::
|
||||
attribute. For example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> print(dist.km)
|
||||
8.04672
|
||||
@ -132,7 +146,9 @@ Measurement API
|
||||
.. classmethod:: unit_attname(unit_name)
|
||||
|
||||
Returns the distance unit attribute name for the given full unit name. For
|
||||
example::
|
||||
example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Distance.unit_attname('Mile')
|
||||
'mi'
|
||||
@ -149,14 +165,18 @@ Measurement API
|
||||
To initialize an area object, pass in a keyword corresponding to the
|
||||
desired :ref:`unit attribute name <supported_units>` set with desired
|
||||
value. For example, the following creates an area object representing 5
|
||||
square miles::
|
||||
square miles:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> a = Area(sq_mi=5)
|
||||
|
||||
.. method:: __getattr__(unit_att)
|
||||
|
||||
Returns the area value in units corresponding to the given unit attribute.
|
||||
For example::
|
||||
For example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> print(a.sq_km)
|
||||
12.949940551680001
|
||||
@ -164,7 +184,9 @@ Measurement API
|
||||
.. classmethod:: unit_attname(unit_name)
|
||||
|
||||
Returns the area unit attribute name for the given full unit name. For
|
||||
example::
|
||||
example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Area.unit_attname('Kilometer')
|
||||
'sq_km'
|
||||
|
@ -46,7 +46,9 @@ Create database user
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
To make a database user with the ability to create databases, use the
|
||||
following command::
|
||||
following command:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
$ createuser --createdb -R -S <user_name>
|
||||
|
||||
@ -54,19 +56,25 @@ The ``-R -S`` flags indicate that we do not want the user to have the ability
|
||||
to create additional users (roles) or to be a superuser, respectively.
|
||||
|
||||
Alternatively, you may alter an existing user's role from the SQL shell
|
||||
(assuming this is done from an existing superuser account)::
|
||||
(assuming this is done from an existing superuser account):
|
||||
|
||||
.. code-block:: psql
|
||||
|
||||
postgres# ALTER ROLE <user_name> CREATEDB NOSUPERUSER NOCREATEROLE;
|
||||
|
||||
Create database superuser
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
This may be done at the time the user is created, for example::
|
||||
This may be done at the time the user is created, for example:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
$ createuser --superuser <user_name>
|
||||
|
||||
Or you may alter the user's role from the SQL shell (assuming this
|
||||
is done from an existing superuser account)::
|
||||
is done from an existing superuser account):
|
||||
|
||||
.. code-block:: psql
|
||||
|
||||
postgres# ALTER ROLE <user_name> SUPERUSER;
|
||||
|
||||
@ -114,10 +122,14 @@ in :mod:`django.contrib.gis`::
|
||||
|
||||
Assuming the settings above were in a ``postgis.py`` file in the same
|
||||
directory as ``runtests.py``, then all Django and GeoDjango tests would
|
||||
be performed when executing the command::
|
||||
be performed when executing the command:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
$ ./runtests.py --settings=postgis
|
||||
|
||||
To run only the GeoDjango test suite, specify ``gis_tests``::
|
||||
To run only the GeoDjango test suite, specify ``gis_tests``:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
$ ./runtests.py --settings=postgis gis_tests
|
||||
|
@ -321,14 +321,18 @@ First, invoke the Django shell:
|
||||
$ python manage.py shell
|
||||
|
||||
If you downloaded the :ref:`worldborders` data earlier in the tutorial, then
|
||||
you can determine its path using Python's :class:`pathlib.Path`::
|
||||
you can determine its path using Python's :class:`pathlib.Path`:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from pathlib import Path
|
||||
>>> import world
|
||||
>>> world_shp = Path(world.__file__).resolve().parent / 'data' / 'TM_WORLD_BORDERS-0.3.shp'
|
||||
|
||||
Now, open the world borders shapefile using GeoDjango's
|
||||
:class:`~django.contrib.gis.gdal.DataSource` interface::
|
||||
:class:`~django.contrib.gis.gdal.DataSource` interface:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.contrib.gis.gdal import DataSource
|
||||
>>> ds = DataSource(world_shp)
|
||||
@ -336,7 +340,9 @@ Now, open the world borders shapefile using GeoDjango's
|
||||
/ ... /geodjango/world/data/TM_WORLD_BORDERS-0.3.shp (ESRI Shapefile)
|
||||
|
||||
Data source objects can have different layers of geospatial features; however,
|
||||
shapefiles are only allowed to have one layer::
|
||||
shapefiles are only allowed to have one layer:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> print(len(ds))
|
||||
1
|
||||
@ -344,7 +350,9 @@ shapefiles are only allowed to have one layer::
|
||||
>>> print(lyr)
|
||||
TM_WORLD_BORDERS-0.3
|
||||
|
||||
You can see the layer's geometry type and how many features it contains::
|
||||
You can see the layer's geometry type and how many features it contains:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> print(lyr.geom_type)
|
||||
Polygon
|
||||
@ -363,7 +371,9 @@ You can see the layer's geometry type and how many features it contains::
|
||||
|
||||
The :class:`~django.contrib.gis.gdal.Layer` may also have a spatial reference
|
||||
system associated with it. If it does, the ``srs`` attribute will return a
|
||||
:class:`~django.contrib.gis.gdal.SpatialReference` object::
|
||||
:class:`~django.contrib.gis.gdal.SpatialReference` object:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> srs = lyr.srs
|
||||
>>> print(srs)
|
||||
@ -401,7 +411,9 @@ string) associated with each of the fields:
|
||||
You can iterate over each feature in the layer and extract information from both
|
||||
the feature's geometry (accessed via the ``geom`` attribute) as well as the
|
||||
feature's attribute fields (whose **values** are accessed via ``get()``
|
||||
method)::
|
||||
method):
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> for feat in lyr:
|
||||
... print(feat.get('NAME'), feat.geom.num_points)
|
||||
@ -411,18 +423,24 @@ method)::
|
||||
South Georgia South Sandwich Islands 338
|
||||
Taiwan 363
|
||||
|
||||
:class:`~django.contrib.gis.gdal.Layer` objects may be sliced::
|
||||
:class:`~django.contrib.gis.gdal.Layer` objects may be sliced:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> lyr[0:2]
|
||||
[<django.contrib.gis.gdal.feature.Feature object at 0x2f47690>, <django.contrib.gis.gdal.feature.Feature object at 0x2f47650>]
|
||||
|
||||
And individual features may be retrieved by their feature ID::
|
||||
And individual features may be retrieved by their feature ID:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> feat = lyr[234]
|
||||
>>> print(feat.get('NAME'))
|
||||
San Marino
|
||||
|
||||
Boundary geometries may be exported as WKT and GeoJSON::
|
||||
Boundary geometries may be exported as WKT and GeoJSON:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> geom = feat.geom
|
||||
>>> print(geom.wkt)
|
||||
@ -484,7 +502,9 @@ Afterward, invoke the Django shell from the ``geodjango`` project directory:
|
||||
$ python manage.py shell
|
||||
|
||||
Next, import the ``load`` module, call the ``run`` routine, and watch
|
||||
``LayerMapping`` do the work::
|
||||
``LayerMapping`` do the work:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from world import load
|
||||
>>> load.run()
|
||||
@ -576,7 +596,9 @@ a particular point. First, fire up the management shell:
|
||||
|
||||
$ python manage.py shell
|
||||
|
||||
Now, define a point of interest [#]_::
|
||||
Now, define a point of interest [#]_:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> pnt_wkt = 'POINT(-95.3385 29.7245)'
|
||||
|
||||
@ -584,7 +606,9 @@ The ``pnt_wkt`` string represents the point at -95.3385 degrees longitude,
|
||||
29.7245 degrees latitude. The geometry is in a format known as
|
||||
Well Known Text (WKT), a standard issued by the Open Geospatial
|
||||
Consortium (OGC). [#]_ Import the ``WorldBorder`` model, and perform
|
||||
a ``contains`` lookup using the ``pnt_wkt`` as the parameter::
|
||||
a ``contains`` lookup using the ``pnt_wkt`` as the parameter:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from world.models import WorldBorder
|
||||
>>> WorldBorder.objects.filter(mpoly__contains=pnt_wkt)
|
||||
@ -596,7 +620,9 @@ United States (exactly what you would expect).
|
||||
Similarly, you may also use a :doc:`GEOS geometry object <geos>`.
|
||||
Here, you can combine the ``intersects`` spatial lookup with the ``get``
|
||||
method to retrieve only the ``WorldBorder`` instance for San Marino instead
|
||||
of a queryset::
|
||||
of a queryset:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.contrib.gis.geos import Point
|
||||
>>> pnt = Point(12.4604, 43.9420)
|
||||
@ -614,19 +640,25 @@ When doing spatial queries, GeoDjango automatically transforms
|
||||
geometries if they're in a different coordinate system. In the following
|
||||
example, coordinates will be expressed in `EPSG SRID 32140`__,
|
||||
a coordinate system specific to south Texas **only** and in units of
|
||||
**meters**, not degrees::
|
||||
**meters**, not degrees:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.contrib.gis.geos import GEOSGeometry, Point
|
||||
>>> pnt = Point(954158.1, 4215137.1, srid=32140)
|
||||
|
||||
Note that ``pnt`` may also be constructed with EWKT, an "extended" form of
|
||||
WKT that includes the SRID::
|
||||
WKT that includes the SRID:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> pnt = GEOSGeometry('SRID=32140;POINT(954158.1 4215137.1)')
|
||||
|
||||
GeoDjango's ORM will automatically wrap geometry values
|
||||
in transformation SQL, allowing the developer to work at a higher level
|
||||
of abstraction::
|
||||
of abstraction:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> qs = WorldBorder.objects.filter(mpoly__intersects=pnt)
|
||||
>>> print(qs.query) # Generating the SQL
|
||||
@ -646,7 +678,9 @@ __ https://spatialreference.org/ref/epsg/32140/
|
||||
.. admonition:: Raw queries
|
||||
|
||||
When using :doc:`raw queries </topics/db/sql>`, you must wrap your geometry
|
||||
fields so that the field value can be recognized by GEOS::
|
||||
fields so that the field value can be recognized by GEOS:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
from django.db import connection
|
||||
# or if you're querying a non-default database:
|
||||
@ -663,7 +697,9 @@ GeoDjango loads geometries in a standardized textual representation. When the
|
||||
geometry field is first accessed, GeoDjango creates a
|
||||
:class:`~django.contrib.gis.geos.GEOSGeometry` object, exposing powerful
|
||||
functionality, such as serialization properties for popular geospatial
|
||||
formats::
|
||||
formats:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> sm = WorldBorder.objects.get(name='San Marino')
|
||||
>>> sm.mpoly
|
||||
@ -676,7 +712,9 @@ formats::
|
||||
'{ "type": "MultiPolygon", "coordinates": [ [ [ [ 12.415798, 43.957954 ], [ 12.450554, 43.979721 ], ...
|
||||
|
||||
This includes access to all of the advanced geometric operations provided by
|
||||
the GEOS library::
|
||||
the GEOS library:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> pnt = Point(12.4604, 43.9420)
|
||||
>>> sm.mpoly.contains(pnt)
|
||||
|
@ -180,7 +180,9 @@ Displaying messages
|
||||
-------------------
|
||||
.. function:: get_messages(request)
|
||||
|
||||
**In your template**, use something like::
|
||||
**In your template**, use something like:
|
||||
|
||||
.. code-block:: html+django
|
||||
|
||||
{% if messages %}
|
||||
<ul class="messages">
|
||||
@ -199,7 +201,9 @@ Even if you know there is only one message, you should still iterate over the
|
||||
cleared for the next request.
|
||||
|
||||
The context processor also provides a ``DEFAULT_MESSAGE_LEVELS`` variable which
|
||||
is a mapping of the message level names to their numeric value::
|
||||
is a mapping of the message level names to their numeric value:
|
||||
|
||||
.. code-block:: html+django
|
||||
|
||||
{% if messages %}
|
||||
<ul class="messages">
|
||||
|
@ -12,7 +12,9 @@ module. They are described in more detail in the `PostgreSQL docs
|
||||
.. note::
|
||||
|
||||
All functions come without default aliases, so you must explicitly provide
|
||||
one. For example::
|
||||
one. For example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> SomeModel.objects.aggregate(arr=ArrayAgg('somefield'))
|
||||
{'arr': [0, 1, 2]}
|
||||
@ -97,6 +99,8 @@ General-purpose aggregation functions
|
||||
published = models.BooleanField()
|
||||
rank = models.IntegerField()
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.db.models import Q
|
||||
>>> from django.contrib.postgres.aggregates import BoolAnd
|
||||
>>> Comment.objects.aggregate(booland=BoolAnd('published'))
|
||||
@ -119,6 +123,8 @@ General-purpose aggregation functions
|
||||
published = models.BooleanField()
|
||||
rank = models.IntegerField()
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.db.models import Q
|
||||
>>> from django.contrib.postgres.aggregates import BoolOr
|
||||
>>> Comment.objects.aggregate(boolor=BoolOr('published'))
|
||||
@ -160,6 +166,8 @@ General-purpose aggregation functions
|
||||
end = models.DateTimeField()
|
||||
requirements = models.JSONField(blank=True, null=True)
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.contrib.postgres.aggregates import JSONBAgg
|
||||
>>> Room.objects.annotate(
|
||||
... requirements=JSONBAgg(
|
||||
@ -213,6 +221,8 @@ General-purpose aggregation functions
|
||||
headline = models.CharField(max_length=100)
|
||||
publications = models.ManyToManyField(Publication)
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> article = Article.objects.create(headline="NASA uses Python")
|
||||
>>> article.publications.create(title="The Python Journal")
|
||||
<Publication: Publication object (1)>
|
||||
@ -349,7 +359,9 @@ field or an expression returning a numeric data. Both are required.
|
||||
Usage examples
|
||||
==============
|
||||
|
||||
We will use this example table::
|
||||
We will use this example table:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
| FIELD1 | FIELD2 | FIELD3 |
|
||||
|--------|--------|--------|
|
||||
@ -357,8 +369,9 @@ We will use this example table::
|
||||
| bar | 2 | (null) |
|
||||
| test | 3 | 13 |
|
||||
|
||||
Here's some examples of some of the general-purpose aggregation functions:
|
||||
|
||||
Here's some examples of some of the general-purpose aggregation functions::
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> TestModel.objects.aggregate(result=StringAgg('field1', delimiter=';'))
|
||||
{'result': 'foo;bar;test'}
|
||||
@ -369,7 +382,9 @@ Here's some examples of some of the general-purpose aggregation functions::
|
||||
|
||||
The next example shows the usage of statistical aggregate functions. The
|
||||
underlying math will be not described (you can read about this, for example, at
|
||||
`wikipedia <https://en.wikipedia.org/wiki/Regression_analysis>`_)::
|
||||
`wikipedia <https://en.wikipedia.org/wiki/Regression_analysis>`_):
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> TestModel.objects.aggregate(count=RegrCount(y='field3', x='field2'))
|
||||
{'count': 2}
|
||||
|
@ -22,7 +22,9 @@ in the way that it does not act as an aggregate function and does not require
|
||||
an SQL ``GROUP BY`` clause to build the list of values.
|
||||
|
||||
For example, if you want to annotate all related books to an author as JSON
|
||||
objects::
|
||||
objects:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.db.models import OuterRef
|
||||
>>> from django.db.models.functions import JSONObject
|
||||
|
@ -127,7 +127,9 @@ We will use the following example model::
|
||||
|
||||
The :lookup:`contains` lookup is overridden on :class:`ArrayField`. The
|
||||
returned objects will be those where the values passed are a subset of the
|
||||
data. It uses the SQL operator ``@>``. For example::
|
||||
data. It uses the SQL operator ``@>``. For example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Post.objects.create(name='First post', tags=['thoughts', 'django'])
|
||||
>>> Post.objects.create(name='Second post', tags=['thoughts'])
|
||||
@ -149,7 +151,9 @@ data. It uses the SQL operator ``@>``. For example::
|
||||
|
||||
This is the inverse of the :lookup:`contains <arrayfield.contains>` lookup -
|
||||
the objects returned will be those where the data is a subset of the values
|
||||
passed. It uses the SQL operator ``<@``. For example::
|
||||
passed. It uses the SQL operator ``<@``. For example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Post.objects.create(name='First post', tags=['thoughts', 'django'])
|
||||
>>> Post.objects.create(name='Second post', tags=['thoughts'])
|
||||
@ -167,7 +171,9 @@ passed. It uses the SQL operator ``<@``. For example::
|
||||
~~~~~~~~~~~
|
||||
|
||||
Returns objects where the data shares any results with the values passed. Uses
|
||||
the SQL operator ``&&``. For example::
|
||||
the SQL operator ``&&``. For example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Post.objects.create(name='First post', tags=['thoughts', 'django'])
|
||||
>>> Post.objects.create(name='Second post', tags=['thoughts', 'tutorial'])
|
||||
@ -193,7 +199,9 @@ the SQL operator ``&&``. For example::
|
||||
~~~~~~~
|
||||
|
||||
Returns the length of the array. The lookups available afterward are those
|
||||
available for :class:`~django.db.models.IntegerField`. For example::
|
||||
available for :class:`~django.db.models.IntegerField`. For example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Post.objects.create(name='First post', tags=['thoughts', 'django'])
|
||||
>>> Post.objects.create(name='Second post', tags=['thoughts'])
|
||||
@ -209,7 +217,9 @@ Index transforms
|
||||
Index transforms index into the array. Any non-negative integer can be used.
|
||||
There are no errors if it exceeds the :attr:`size <ArrayField.size>` of the
|
||||
array. The lookups available after the transform are those from the
|
||||
:attr:`base_field <ArrayField.base_field>`. For example::
|
||||
:attr:`base_field <ArrayField.base_field>`. For example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Post.objects.create(name='First post', tags=['thoughts', 'django'])
|
||||
>>> Post.objects.create(name='Second post', tags=['thoughts'])
|
||||
@ -236,7 +246,9 @@ Slice transforms
|
||||
|
||||
Slice transforms take a slice of the array. Any two non-negative integers can
|
||||
be used, separated by a single underscore. The lookups available after the
|
||||
transform do not change. For example::
|
||||
transform do not change. For example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Post.objects.create(name='First post', tags=['thoughts', 'django'])
|
||||
>>> Post.objects.create(name='Second post', tags=['thoughts'])
|
||||
@ -374,7 +386,9 @@ We will use the following example model::
|
||||
Key lookups
|
||||
~~~~~~~~~~~
|
||||
|
||||
To query based on a given key, you can use that key as the lookup name::
|
||||
To query based on a given key, you can use that key as the lookup name:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Dog.objects.create(name='Rufus', data={'breed': 'labrador'})
|
||||
>>> Dog.objects.create(name='Meg', data={'breed': 'collie'})
|
||||
@ -382,12 +396,16 @@ To query based on a given key, you can use that key as the lookup name::
|
||||
>>> Dog.objects.filter(data__breed='collie')
|
||||
<QuerySet [<Dog: Meg>]>
|
||||
|
||||
You can chain other lookups after key lookups::
|
||||
You can chain other lookups after key lookups:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Dog.objects.filter(data__breed__contains='l')
|
||||
<QuerySet [<Dog: Rufus>, <Dog: Meg>]>
|
||||
|
||||
or use ``F()`` expressions to annotate a key value. For example::
|
||||
or use ``F()`` expressions to annotate a key value. For example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.db.models import F
|
||||
>>> rufus = Dog.objects.annotate(breed=F("data__breed"))[0]
|
||||
@ -419,7 +437,9 @@ need to use the :lookup:`hstorefield.contains` lookup instead.
|
||||
The :lookup:`contains` lookup is overridden on
|
||||
:class:`~django.contrib.postgres.fields.HStoreField`. The returned objects are
|
||||
those where the given ``dict`` of key-value pairs are all contained in the
|
||||
field. It uses the SQL operator ``@>``. For example::
|
||||
field. It uses the SQL operator ``@>``. For example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Dog.objects.create(name='Rufus', data={'breed': 'labrador', 'owner': 'Bob'})
|
||||
>>> Dog.objects.create(name='Meg', data={'breed': 'collie', 'owner': 'Bob'})
|
||||
@ -439,7 +459,9 @@ field. It uses the SQL operator ``@>``. For example::
|
||||
This is the inverse of the :lookup:`contains <hstorefield.contains>` lookup -
|
||||
the objects returned will be those where the key-value pairs on the object are
|
||||
a subset of those in the value passed. It uses the SQL operator ``<@``. For
|
||||
example::
|
||||
example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Dog.objects.create(name='Rufus', data={'breed': 'labrador', 'owner': 'Bob'})
|
||||
>>> Dog.objects.create(name='Meg', data={'breed': 'collie', 'owner': 'Bob'})
|
||||
@ -457,7 +479,9 @@ example::
|
||||
~~~~~~~~~~~
|
||||
|
||||
Returns objects where the given key is in the data. Uses the SQL operator
|
||||
``?``. For example::
|
||||
``?``. For example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Dog.objects.create(name='Rufus', data={'breed': 'labrador'})
|
||||
>>> Dog.objects.create(name='Meg', data={'breed': 'collie', 'owner': 'Bob'})
|
||||
@ -471,7 +495,9 @@ Returns objects where the given key is in the data. Uses the SQL operator
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
Returns objects where any of the given keys are in the data. Uses the SQL
|
||||
operator ``?|``. For example::
|
||||
operator ``?|``. For example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Dog.objects.create(name='Rufus', data={'breed': 'labrador'})
|
||||
>>> Dog.objects.create(name='Meg', data={'owner': 'Bob'})
|
||||
@ -486,7 +512,9 @@ operator ``?|``. For example::
|
||||
~~~~~~~~~~~~
|
||||
|
||||
Returns objects where all of the given keys are in the data. Uses the SQL operator
|
||||
``?&``. For example::
|
||||
``?&``. For example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Dog.objects.create(name='Rufus', data={})
|
||||
>>> Dog.objects.create(name='Meg', data={'breed': 'collie', 'owner': 'Bob'})
|
||||
@ -503,7 +531,9 @@ Returns objects where the array of keys is the given value. Note that the order
|
||||
is not guaranteed to be reliable, so this transform is mainly useful for using
|
||||
in conjunction with lookups on
|
||||
:class:`~django.contrib.postgres.fields.ArrayField`. Uses the SQL function
|
||||
``akeys()``. For example::
|
||||
``akeys()``. For example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Dog.objects.create(name='Rufus', data={'toy': 'bone'})
|
||||
>>> Dog.objects.create(name='Meg', data={'breed': 'collie', 'owner': 'Bob'})
|
||||
@ -520,7 +550,9 @@ Returns objects where the array of values is the given value. Note that the
|
||||
order is not guaranteed to be reliable, so this transform is mainly useful for
|
||||
using in conjunction with lookups on
|
||||
:class:`~django.contrib.postgres.fields.ArrayField`. Uses the SQL function
|
||||
``avals()``. For example::
|
||||
``avals()``. For example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Dog.objects.create(name='Rufus', data={'breed': 'labrador'})
|
||||
>>> Dog.objects.create(name='Meg', data={'breed': 'collie', 'owner': 'Bob'})
|
||||
@ -642,7 +674,9 @@ model::
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
We will also use the following example objects::
|
||||
We will also use the following example objects:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> import datetime
|
||||
>>> from django.utils import timezone
|
||||
@ -685,7 +719,9 @@ The ``contained_by`` lookup is also available on the non-range field types:
|
||||
:class:`~django.db.models.BigIntegerField`,
|
||||
:class:`~django.db.models.DecimalField`, :class:`~django.db.models.FloatField`,
|
||||
:class:`~django.db.models.DateField`, and
|
||||
:class:`~django.db.models.DateTimeField`. For example::
|
||||
:class:`~django.db.models.DateTimeField`. For example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.db.backends.postgresql.psycopg_any import DateTimeTZRange
|
||||
>>> Event.objects.filter(
|
||||
|
@ -23,7 +23,9 @@ Fields
|
||||
|
||||
It specifies the underlying form field for the array. This is not used
|
||||
to render any HTML, but it is used to process the submitted data and
|
||||
validate it. For example::
|
||||
validate it. For example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django import forms
|
||||
>>> from django.contrib.postgres.forms import SimpleArrayField
|
||||
@ -45,7 +47,9 @@ Fields
|
||||
|
||||
This is an optional argument which defaults to a comma: ``,``. This
|
||||
value is used to split the submitted data. It allows you to chain
|
||||
``SimpleArrayField`` for multidimensional data::
|
||||
``SimpleArrayField`` for multidimensional data:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django import forms
|
||||
>>> from django.contrib.postgres.forms import SimpleArrayField
|
||||
|
@ -20,7 +20,9 @@ operation to install it.
|
||||
|
||||
.. _pgcrypto extension: https://www.postgresql.org/docs/current/pgcrypto.html
|
||||
|
||||
Usage example::
|
||||
Usage example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.contrib.postgres.functions import RandomUUID
|
||||
>>> Article.objects.update(uuid=RandomUUID())
|
||||
@ -41,7 +43,9 @@ sets up a transaction and thus sets the time that ``TransactionNow()`` will
|
||||
return; nested calls create savepoints which do not affect the transaction
|
||||
time.
|
||||
|
||||
Usage example::
|
||||
Usage example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.contrib.postgres.functions import TransactionNow
|
||||
>>> Article.objects.filter(published__lte=TransactionNow())
|
||||
|
@ -23,7 +23,9 @@ extension using the
|
||||
operation.
|
||||
|
||||
The ``trigram_similar`` lookup can be used on
|
||||
:class:`~django.db.models.CharField` and :class:`~django.db.models.TextField`::
|
||||
:class:`~django.db.models.CharField` and :class:`~django.db.models.TextField`:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> City.objects.filter(name__trigram_similar="Middlesborough")
|
||||
['<City: Middlesbrough>']
|
||||
@ -47,7 +49,9 @@ extension using the
|
||||
operation.
|
||||
|
||||
The ``trigram_word_similar`` lookup can be used on
|
||||
:class:`~django.db.models.CharField` and :class:`~django.db.models.TextField`::
|
||||
:class:`~django.db.models.CharField` and :class:`~django.db.models.TextField`:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Sentence.objects.filter(name__trigram_word_similar='Middlesborough')
|
||||
['<Sentence: Gumby rides on the path of Middlesbrough>']
|
||||
@ -91,7 +95,9 @@ operation is available if you want to perform this activation using migrations).
|
||||
.. _unaccent extension on PostgreSQL: https://www.postgresql.org/docs/current/unaccent.html
|
||||
|
||||
The ``unaccent`` lookup can be used on
|
||||
:class:`~django.db.models.CharField` and :class:`~django.db.models.TextField`::
|
||||
:class:`~django.db.models.CharField` and :class:`~django.db.models.TextField`:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> City.objects.filter(name__unaccent="México")
|
||||
['<City: Mexico>']
|
||||
|
@ -22,7 +22,9 @@ The ``search`` lookup
|
||||
.. fieldlookup:: search
|
||||
|
||||
A common way to use full text search is to search a single term against a
|
||||
single column in the database. For example::
|
||||
single column in the database. For example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Entry.objects.filter(body_text__search='Cheese')
|
||||
[<Entry: Cheese on Toast recipes>, <Entry: Pizza Recipes>]
|
||||
@ -42,7 +44,9 @@ To use the ``search`` lookup, ``'django.contrib.postgres'`` must be in your
|
||||
|
||||
Searching against a single field is great but rather limiting. The ``Entry``
|
||||
instances we're searching belong to a ``Blog``, which has a ``tagline`` field.
|
||||
To query against both fields, use a ``SearchVector``::
|
||||
To query against both fields, use a ``SearchVector``:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.contrib.postgres.search import SearchVector
|
||||
>>> Entry.objects.annotate(
|
||||
@ -56,7 +60,9 @@ arguments will be concatenated together using a space so that the search
|
||||
document includes them all.
|
||||
|
||||
``SearchVector`` objects can be combined together, allowing you to reuse them.
|
||||
For example::
|
||||
For example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Entry.objects.annotate(
|
||||
... search=SearchVector('body_text') + SearchVector('blog__tagline'),
|
||||
@ -96,7 +102,9 @@ Examples:
|
||||
>>> SearchQuery("'tomato' & ('red' | 'green')", search_type='raw') # boolean operators
|
||||
>>> SearchQuery("'tomato' ('red' OR 'green')", search_type='websearch') # websearch operators
|
||||
|
||||
``SearchQuery`` terms can be combined logically to provide more flexibility::
|
||||
``SearchQuery`` terms can be combined logically to provide more flexibility:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.contrib.postgres.search import SearchQuery
|
||||
>>> SearchQuery('meat') & SearchQuery('cheese') # AND
|
||||
@ -117,7 +125,9 @@ sort of relevancy. PostgreSQL provides a ranking function which takes into
|
||||
account how often the query terms appear in the document, how close together
|
||||
the terms are in the document, and how important the part of the document is
|
||||
where they occur. The better the match, the higher the value of the rank. To
|
||||
order by relevancy::
|
||||
order by relevancy:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.contrib.postgres.search import SearchQuery, SearchRank, SearchVector
|
||||
>>> vector = SearchVector('body_text')
|
||||
@ -134,7 +144,9 @@ account.
|
||||
|
||||
Provide an integer to the ``normalization`` parameter to control rank
|
||||
normalization. This integer is a bit mask, so you can combine multiple
|
||||
behaviors::
|
||||
behaviors:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.db.models import Value
|
||||
>>> Entry.objects.annotate(
|
||||
@ -182,7 +194,9 @@ between fragments. PostgreSQL's default is ``" ... "``.
|
||||
The PostgreSQL documentation has more details on `highlighting search
|
||||
results`_.
|
||||
|
||||
Usage example::
|
||||
Usage example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.contrib.postgres.search import SearchHeadline, SearchQuery
|
||||
>>> query = SearchQuery('red tomato')
|
||||
@ -209,7 +223,9 @@ Changing the search configuration
|
||||
|
||||
You can specify the ``config`` attribute to a :class:`SearchVector` and
|
||||
:class:`SearchQuery` to use a different search configuration. This allows using
|
||||
different language parsers and dictionaries as defined by the database::
|
||||
different language parsers and dictionaries as defined by the database:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.contrib.postgres.search import SearchQuery, SearchVector
|
||||
>>> Entry.objects.annotate(
|
||||
@ -217,7 +233,9 @@ different language parsers and dictionaries as defined by the database::
|
||||
... ).filter(search=SearchQuery('œuf', config='french'))
|
||||
[<Entry: Pain perdu>]
|
||||
|
||||
The value of ``config`` could also be stored in another column::
|
||||
The value of ``config`` could also be stored in another column:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.db.models import F
|
||||
>>> Entry.objects.annotate(
|
||||
@ -231,7 +249,9 @@ Weighting queries
|
||||
=================
|
||||
|
||||
Every field may not have the same relevance in a query, so you can set weights
|
||||
of various vectors before you combine them::
|
||||
of various vectors before you combine them:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.contrib.postgres.search import SearchQuery, SearchRank, SearchVector
|
||||
>>> vector = SearchVector('body_text', weight='A') + SearchVector('blog__tagline', weight='B')
|
||||
@ -241,7 +261,9 @@ of various vectors before you combine them::
|
||||
The weight should be one of the following letters: D, C, B, A. By default,
|
||||
these weights refer to the numbers ``0.1``, ``0.2``, ``0.4``, and ``1.0``,
|
||||
respectively. If you wish to weight them differently, pass a list of four
|
||||
floats to :class:`SearchRank` as ``weights`` in the same order above::
|
||||
floats to :class:`SearchRank` as ``weights`` in the same order above:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> rank = SearchRank(vector, query, weights=[0.2, 0.4, 0.6, 0.8])
|
||||
>>> Entry.objects.annotate(rank=rank).filter(rank__gte=0.3).order_by('-rank')
|
||||
@ -277,7 +299,9 @@ The PostgreSQL documentation has details on
|
||||
If this approach becomes too slow, you can add a ``SearchVectorField`` to your
|
||||
model. You'll need to keep it populated with triggers, for example, as
|
||||
described in the `PostgreSQL documentation`_. You can then query the field as
|
||||
if it were an annotated ``SearchVector``::
|
||||
if it were an annotated ``SearchVector``:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Entry.objects.update(search_vector=SearchVector('body_text'))
|
||||
>>> Entry.objects.filter(search_vector='cheese')
|
||||
@ -307,7 +331,9 @@ operation.
|
||||
Accepts a field name or expression, and a string or expression. Returns the
|
||||
trigram similarity between the two arguments.
|
||||
|
||||
Usage example::
|
||||
Usage example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.contrib.postgres.search import TrigramSimilarity
|
||||
>>> Author.objects.create(name='Katy Stevens')
|
||||
@ -326,7 +352,9 @@ Usage example::
|
||||
Accepts a string or expression, and a field name or expression. Returns the
|
||||
trigram word similarity between the two arguments.
|
||||
|
||||
Usage example::
|
||||
Usage example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.contrib.postgres.search import TrigramWordSimilarity
|
||||
>>> Author.objects.create(name='Katy Stevens')
|
||||
@ -357,7 +385,9 @@ extent boundaries to match word boundaries.
|
||||
Accepts a field name or expression, and a string or expression. Returns the
|
||||
trigram distance between the two arguments.
|
||||
|
||||
Usage example::
|
||||
Usage example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.contrib.postgres.search import TrigramDistance
|
||||
>>> Author.objects.create(name='Katy Stevens')
|
||||
@ -376,7 +406,9 @@ Usage example::
|
||||
Accepts a string or expression, and a field name or expression. Returns the
|
||||
trigram word distance between the two arguments.
|
||||
|
||||
Usage example::
|
||||
Usage example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.contrib.postgres.search import TrigramWordDistance
|
||||
>>> Author.objects.create(name='Katy Stevens')
|
||||
|
@ -74,7 +74,9 @@ Via the Python API
|
||||
Redirects are represented by a standard :doc:`Django model </topics/db/models>`,
|
||||
which lives in :source:`django/contrib/redirects/models.py`. You can access
|
||||
redirect objects via the :doc:`Django database API </topics/db/queries>`.
|
||||
For example::
|
||||
For example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.conf import settings
|
||||
>>> from django.contrib.redirects.models import Redirect
|
||||
|
@ -623,7 +623,9 @@ Pinging Google via ``manage.py``
|
||||
.. django-admin:: ping_google [sitemap_url]
|
||||
|
||||
Once the sitemaps application is added to your project, you may also
|
||||
ping Google using the ``ping_google`` management command::
|
||||
ping Google using the ``ping_google`` management command:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
python manage.py ping_google [/sitemap.xml]
|
||||
|
||||
|
@ -241,7 +241,9 @@ Getting the current domain for full URLs
|
||||
Django's ``get_absolute_url()`` convention is nice for getting your objects'
|
||||
URL without the domain name, but in some cases you might want to display the
|
||||
full URL -- with ``http://`` and the domain and everything -- for an object.
|
||||
To do this, you can use the sites framework. An example::
|
||||
To do this, you can use the sites framework. An example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.contrib.sites.models import Site
|
||||
>>> obj = MyModel.objects.get(id=3)
|
||||
|
@ -1004,7 +1004,9 @@ They share this interface:
|
||||
:meth:`.SyndicationFeed.writeString`
|
||||
Returns the feed as a string in the given encoding.
|
||||
|
||||
For example, to create an Atom 1.0 feed and print it to standard output::
|
||||
For example, to create an Atom 1.0 feed and print it to standard output:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.utils import feedgenerator
|
||||
>>> from datetime import datetime
|
||||
|
@ -348,7 +348,9 @@ Django uses PostgreSQL's identity columns to store auto-incrementing primary
|
||||
keys. An identity column is populated with values from a `sequence`_ that keeps
|
||||
track of the next available value. Manually assigning a value to an
|
||||
auto-incrementing field doesn't update the field's sequence, which might later
|
||||
cause a conflict. For example::
|
||||
cause a conflict. For example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.contrib.auth.models import User
|
||||
>>> User.objects.create(username='alice', pk=1)
|
||||
@ -491,7 +493,9 @@ This needs to be done just once for your MySQL server, not per database.
|
||||
Creating your database
|
||||
----------------------
|
||||
|
||||
You can `create your database`_ using the command-line tools and this SQL::
|
||||
You can `create your database`_ using the command-line tools and this SQL:
|
||||
|
||||
.. code-block:: sql
|
||||
|
||||
CREATE DATABASE <dbname> CHARACTER SET utf8;
|
||||
|
||||
@ -572,6 +576,8 @@ Here's a sample configuration which uses a MySQL option file::
|
||||
}
|
||||
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
# my.cnf
|
||||
[client]
|
||||
database = NAME
|
||||
@ -641,7 +647,9 @@ If you're using a hosting service and can't change your server's default
|
||||
storage engine, you have a couple of options.
|
||||
|
||||
* After the tables are created, execute an ``ALTER TABLE`` statement to
|
||||
convert a table to a new storage engine (such as InnoDB)::
|
||||
convert a table to a new storage engine (such as InnoDB):
|
||||
|
||||
.. code-block:: sql
|
||||
|
||||
ALTER TABLE <tablename> ENGINE=INNODB;
|
||||
|
||||
@ -721,7 +729,9 @@ includes a fractional indication (e.g. ``DATETIME(6)``).
|
||||
Django will not upgrade existing columns to include fractional seconds if the
|
||||
database server supports it. If you want to enable them on an existing database,
|
||||
it's up to you to either manually update the column on the target database, by
|
||||
executing a command like::
|
||||
executing a command like:
|
||||
|
||||
.. code-block:: sql
|
||||
|
||||
ALTER TABLE `your_table` MODIFY `your_datetime_column` DATETIME(6)
|
||||
|
||||
@ -1117,7 +1127,9 @@ database backends to modify its behavior, features, or configuration.
|
||||
|
||||
Consider, for example, that you need to change a single database feature.
|
||||
First, you have to create a new directory with a ``base`` module in it. For
|
||||
example::
|
||||
example:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
mysite/
|
||||
...
|
||||
|
@ -65,7 +65,9 @@ Determining the version
|
||||
|
||||
Run ``django-admin version`` to display the current Django version.
|
||||
|
||||
The output follows the schema described in :pep:`440`::
|
||||
The output follows the schema described in :pep:`440`:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
1.4.dev17026
|
||||
1.4a1
|
||||
@ -91,7 +93,9 @@ Uses the :doc:`system check framework </ref/checks>` to inspect the entire
|
||||
Django project for common problems.
|
||||
|
||||
By default, all apps will be checked. You can check a subset of apps by
|
||||
providing a list of app labels as arguments::
|
||||
providing a list of app labels as arguments:
|
||||
|
||||
.. console::
|
||||
|
||||
django-admin check auth admin myapp
|
||||
|
||||
@ -100,13 +104,17 @@ providing a list of app labels as arguments::
|
||||
The system check framework performs many different types of checks that are
|
||||
:ref:`categorized with tags <system-check-builtin-tags>`. You can use these
|
||||
tags to restrict the checks performed to just those in a particular category.
|
||||
For example, to perform only models and compatibility checks, run::
|
||||
For example, to perform only models and compatibility checks, run:
|
||||
|
||||
.. console::
|
||||
|
||||
django-admin check --tag models --tag compatibility
|
||||
|
||||
.. django-admin-option:: --database DATABASE
|
||||
|
||||
Specifies the database to run checks requiring database access::
|
||||
Specifies the database to run checks requiring database access:
|
||||
|
||||
.. console::
|
||||
|
||||
django-admin check --database default --database other
|
||||
|
||||
@ -124,7 +132,9 @@ You can use this option in your local development environment, but since your
|
||||
local development settings module may not have many of your production settings,
|
||||
you will probably want to point the ``check`` command at a different settings
|
||||
module, either by setting the :envvar:`DJANGO_SETTINGS_MODULE` environment
|
||||
variable, or by passing the ``--settings`` option::
|
||||
variable, or by passing the ``--settings`` option:
|
||||
|
||||
.. console::
|
||||
|
||||
django-admin check --deploy --settings=production_settings
|
||||
|
||||
@ -158,7 +168,9 @@ are excluded.
|
||||
|
||||
Includes `fuzzy translations`_ into compiled files.
|
||||
|
||||
Example usage::
|
||||
Example usage:
|
||||
|
||||
.. console::
|
||||
|
||||
django-admin compilemessages --locale=pt_BR
|
||||
django-admin compilemessages --locale=pt_BR --locale=fr -f
|
||||
@ -176,7 +188,9 @@ Example usage::
|
||||
Ignores directories matching the given :mod:`glob`-style pattern. Use
|
||||
multiple times to ignore more.
|
||||
|
||||
Example usage::
|
||||
Example usage:
|
||||
|
||||
.. console::
|
||||
|
||||
django-admin compilemessages --ignore=cache --ignore=outdated/*/locale
|
||||
|
||||
@ -329,7 +343,9 @@ only that model will be excluded, rather than the entire application. You can
|
||||
also mix application names and model names.
|
||||
|
||||
If you want to exclude multiple applications, pass ``--exclude`` more than
|
||||
once::
|
||||
once:
|
||||
|
||||
.. console::
|
||||
|
||||
django-admin dumpdata --exclude=auth --exclude=contenttypes
|
||||
|
||||
@ -370,7 +386,9 @@ Fixtures compression
|
||||
|
||||
The output file can be compressed with one of the ``bz2``, ``gz``, ``lzma``, or
|
||||
``xz`` formats by ending the filename with the corresponding extension.
|
||||
For example, to output the data as a compressed JSON file::
|
||||
For example, to output the data as a compressed JSON file:
|
||||
|
||||
.. console::
|
||||
|
||||
django-admin dumpdata -o mydata.json.gz
|
||||
|
||||
@ -520,7 +538,9 @@ Loading fixtures from ``stdin``
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
You can use a dash as the fixture name to load input from ``sys.stdin``. For
|
||||
example::
|
||||
example:
|
||||
|
||||
.. console::
|
||||
|
||||
django-admin loaddata --format=json -
|
||||
|
||||
@ -529,7 +549,9 @@ is required to specify the :ref:`serialization format <serialization-formats>`
|
||||
of the input (e.g., ``json`` or ``xml``).
|
||||
|
||||
Loading from ``stdin`` is useful with standard input and output redirections.
|
||||
For example::
|
||||
For example:
|
||||
|
||||
.. console::
|
||||
|
||||
django-admin dumpdata --format=json --database=test app_label.ModelName | django-admin loaddata --format=json --database=prod -
|
||||
|
||||
@ -564,12 +586,16 @@ Updates the message files for all available languages.
|
||||
Specifies a list of file extensions to examine (default: ``html``, ``txt``,
|
||||
``py`` or ``js`` if :option:`--domain` is ``js``).
|
||||
|
||||
Example usage::
|
||||
Example usage:
|
||||
|
||||
.. console::
|
||||
|
||||
django-admin makemessages --locale=de --extension xhtml
|
||||
|
||||
Separate multiple extensions with commas or use ``-e`` or ``--extension``
|
||||
multiple times::
|
||||
multiple times:
|
||||
|
||||
.. console::
|
||||
|
||||
django-admin makemessages --locale=de --extension=html,txt --extension xml
|
||||
|
||||
@ -582,7 +608,9 @@ Specifies the locale(s) to process.
|
||||
Specifies the locale(s) to exclude from processing. If not provided, no locales
|
||||
are excluded.
|
||||
|
||||
Example usage::
|
||||
Example usage:
|
||||
|
||||
.. console::
|
||||
|
||||
django-admin makemessages --locale=pt_BR
|
||||
django-admin makemessages --locale=pt_BR --locale=fr
|
||||
@ -604,7 +632,9 @@ Specifies the domain of the messages files. Supported options are:
|
||||
|
||||
Follows symlinks to directories when looking for new translation strings.
|
||||
|
||||
Example usage::
|
||||
Example usage:
|
||||
|
||||
.. console::
|
||||
|
||||
django-admin makemessages --locale=de --symlinks
|
||||
|
||||
@ -615,7 +645,9 @@ multiple times to ignore more.
|
||||
|
||||
These patterns are used by default: ``'CVS'``, ``'.*'``, ``'*~'``, ``'*.pyc'``.
|
||||
|
||||
Example usage::
|
||||
Example usage:
|
||||
|
||||
.. console::
|
||||
|
||||
django-admin makemessages --locale=en_US --ignore=apps/* --ignore=secret/*.html
|
||||
|
||||
@ -919,39 +951,57 @@ Uses IPv6 for the development server. This changes the default IP address from
|
||||
Examples of using different ports and addresses
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Port 8000 on IP address ``127.0.0.1``::
|
||||
Port 8000 on IP address ``127.0.0.1``:
|
||||
|
||||
.. console::
|
||||
|
||||
django-admin runserver
|
||||
|
||||
Port 8000 on IP address ``1.2.3.4``::
|
||||
Port 8000 on IP address ``1.2.3.4``:
|
||||
|
||||
.. console::
|
||||
|
||||
django-admin runserver 1.2.3.4:8000
|
||||
|
||||
Port 7000 on IP address ``127.0.0.1``::
|
||||
Port 7000 on IP address ``127.0.0.1``:
|
||||
|
||||
.. console::
|
||||
|
||||
django-admin runserver 7000
|
||||
|
||||
Port 7000 on IP address ``1.2.3.4``::
|
||||
Port 7000 on IP address ``1.2.3.4``:
|
||||
|
||||
.. console::
|
||||
|
||||
django-admin runserver 1.2.3.4:7000
|
||||
|
||||
Port 8000 on IPv6 address ``::1``::
|
||||
Port 8000 on IPv6 address ``::1``:
|
||||
|
||||
.. console::
|
||||
|
||||
django-admin runserver -6
|
||||
|
||||
Port 7000 on IPv6 address ``::1``::
|
||||
Port 7000 on IPv6 address ``::1``:
|
||||
|
||||
.. console::
|
||||
|
||||
django-admin runserver -6 7000
|
||||
|
||||
Port 7000 on IPv6 address ``2001:0db8:1234:5678::9``::
|
||||
Port 7000 on IPv6 address ``2001:0db8:1234:5678::9``:
|
||||
|
||||
.. console::
|
||||
|
||||
django-admin runserver [2001:0db8:1234:5678::9]:7000
|
||||
|
||||
Port 8000 on IPv4 address of host ``localhost``::
|
||||
Port 8000 on IPv4 address of host ``localhost``:
|
||||
|
||||
.. console::
|
||||
|
||||
django-admin runserver localhost:8000
|
||||
|
||||
Port 8000 on IPv6 address of host ``localhost``::
|
||||
Port 8000 on IPv6 address of host ``localhost``:
|
||||
|
||||
.. console::
|
||||
|
||||
django-admin runserver -6 localhost:8000
|
||||
|
||||
@ -969,7 +1019,9 @@ you want to configure Django to serve static media, read
|
||||
.. django-admin:: sendtestemail [email [email ...]]
|
||||
|
||||
Sends a test email (to confirm email sending through Django is working) to the
|
||||
recipient(s) specified. For example::
|
||||
recipient(s) specified. For example:
|
||||
|
||||
.. console::
|
||||
|
||||
django-admin sendtestemail foo@example.com bar@example.com
|
||||
|
||||
@ -998,16 +1050,22 @@ Starts the Python interactive interpreter.
|
||||
Specifies the shell to use. By default, Django will use IPython_ or bpython_ if
|
||||
either is installed. If both are installed, specify which one you want like so:
|
||||
|
||||
IPython::
|
||||
IPython:
|
||||
|
||||
.. console::
|
||||
|
||||
django-admin shell -i ipython
|
||||
|
||||
bpython::
|
||||
bpython:
|
||||
|
||||
.. console::
|
||||
|
||||
django-admin shell -i bpython
|
||||
|
||||
If you have a "rich" shell installed but want to force use of the "plain"
|
||||
Python interpreter, use ``python`` as the interface name, like so::
|
||||
Python interpreter, use ``python`` as the interface name, like so:
|
||||
|
||||
.. console::
|
||||
|
||||
django-admin shell -i python
|
||||
|
||||
@ -1022,7 +1080,9 @@ variable or the ``~/.pythonrc.py`` script is read.
|
||||
|
||||
.. django-admin-option:: --command COMMAND, -c COMMAND
|
||||
|
||||
Lets you pass a command as a string to execute it as Django, like so::
|
||||
Lets you pass a command as a string to execute it as Django, like so:
|
||||
|
||||
.. console::
|
||||
|
||||
django-admin shell --command="import django; print(django.__version__)"
|
||||
|
||||
@ -1171,7 +1231,9 @@ If the optional destination is provided, Django will use that existing
|
||||
directory rather than creating a new one. You can use '.' to denote the current
|
||||
working directory.
|
||||
|
||||
For example::
|
||||
For example:
|
||||
|
||||
.. console::
|
||||
|
||||
django-admin startapp myapp /Users/jezdez/Code/myapp
|
||||
|
||||
@ -1185,7 +1247,9 @@ an uncompressed archive (``.tar``) or a compressed archive (``.tar.gz``,
|
||||
``.tlz``, ``.zip``) containing the app template files.
|
||||
|
||||
For example, this would look for an app template in the given directory when
|
||||
creating the ``myapp`` app::
|
||||
creating the ``myapp`` app:
|
||||
|
||||
.. console::
|
||||
|
||||
django-admin startapp --template=/Users/jezdez/Code/my_app_template myapp
|
||||
|
||||
@ -1194,7 +1258,9 @@ archives with the app template files, downloading and extracting them on the
|
||||
fly.
|
||||
|
||||
For example, taking advantage of GitHub's feature to expose repositories as
|
||||
zip files, you can use a URL like::
|
||||
zip files, you can use a URL like:
|
||||
|
||||
.. console::
|
||||
|
||||
django-admin startapp --template=https://github.com/githubuser/django-app-template/archive/main.zip myapp
|
||||
|
||||
@ -1277,7 +1343,9 @@ If the optional destination is provided, Django will use that existing
|
||||
directory as the project directory, and create ``manage.py`` and the project
|
||||
package within it. Use '.' to denote the current working directory.
|
||||
|
||||
For example::
|
||||
For example:
|
||||
|
||||
.. console::
|
||||
|
||||
django-admin startproject myproject /Users/jezdez/Code/myproject_repo
|
||||
|
||||
@ -1486,7 +1554,9 @@ Outputs timings, including database setup and total run time.
|
||||
Runs a Django development server (as in :djadmin:`runserver`) using data from
|
||||
the given fixture(s).
|
||||
|
||||
For example, this command::
|
||||
For example, this command:
|
||||
|
||||
.. console::
|
||||
|
||||
django-admin testserver mydata.json
|
||||
|
||||
@ -1524,7 +1594,9 @@ exactly the same function as the argument to the :djadmin:`runserver` command.
|
||||
|
||||
Examples:
|
||||
|
||||
To run the test server on port 7000 with ``fixture1`` and ``fixture2``::
|
||||
To run the test server on port 7000 with ``fixture1`` and ``fixture2``:
|
||||
|
||||
.. console::
|
||||
|
||||
django-admin testserver --addrport 7000 fixture1 fixture2
|
||||
django-admin testserver fixture1 fixture2 --addrport 7000
|
||||
@ -1533,7 +1605,9 @@ To run the test server on port 7000 with ``fixture1`` and ``fixture2``::
|
||||
that it doesn't matter whether the options come before or after the fixture
|
||||
arguments.)
|
||||
|
||||
To run on 1.2.3.4:7000 with a ``test`` fixture::
|
||||
To run on 1.2.3.4:7000 with a ``test`` fixture:
|
||||
|
||||
.. console::
|
||||
|
||||
django-admin testserver --addrport 1.2.3.4:7000 test
|
||||
|
||||
@ -1570,7 +1644,9 @@ the password whose username matches the current user.
|
||||
|
||||
Specifies the database to query for the user. Defaults to ``default``.
|
||||
|
||||
Example usage::
|
||||
Example usage:
|
||||
|
||||
.. console::
|
||||
|
||||
django-admin changepassword ringo
|
||||
|
||||
@ -1724,7 +1800,9 @@ variable.
|
||||
This option is unnecessary in ``manage.py``, because it takes care of setting
|
||||
the Python path for you.
|
||||
|
||||
Example usage::
|
||||
Example usage:
|
||||
|
||||
.. console::
|
||||
|
||||
django-admin migrate --pythonpath='/home/djangoprojects/myproject'
|
||||
|
||||
@ -1740,7 +1818,9 @@ variable.
|
||||
This option is unnecessary in ``manage.py``, because it uses
|
||||
``settings.py`` from the current project by default.
|
||||
|
||||
Example usage::
|
||||
Example usage:
|
||||
|
||||
.. console::
|
||||
|
||||
django-admin migrate --settings=mysite.settings
|
||||
|
||||
@ -1752,7 +1832,9 @@ is raised. By default, ``django-admin`` will show an error message when a
|
||||
|
||||
This option is ignored by :djadmin:`runserver`.
|
||||
|
||||
Example usage::
|
||||
Example usage:
|
||||
|
||||
.. console::
|
||||
|
||||
django-admin migrate --traceback
|
||||
|
||||
@ -1768,7 +1850,9 @@ should print to the console.
|
||||
|
||||
This option is ignored by :djadmin:`runserver`.
|
||||
|
||||
Example usage::
|
||||
Example usage:
|
||||
|
||||
.. console::
|
||||
|
||||
django-admin migrate --verbosity 2
|
||||
|
||||
@ -1778,7 +1862,9 @@ Disables colorized command output. Some commands format their output to be
|
||||
colorized. For example, errors will be printed to the console in red and SQL
|
||||
statements will be syntax highlighted.
|
||||
|
||||
Example usage::
|
||||
Example usage:
|
||||
|
||||
.. console::
|
||||
|
||||
django-admin runserver --no-color
|
||||
|
||||
@ -1795,7 +1881,9 @@ available if the
|
||||
:attr:`~django.core.management.BaseCommand.requires_system_checks` command
|
||||
attribute is not an empty list or tuple.
|
||||
|
||||
Example usage::
|
||||
Example usage:
|
||||
|
||||
.. console::
|
||||
|
||||
django-admin migrate --skip-checks
|
||||
|
||||
@ -1828,7 +1916,9 @@ two third-party libraries are needed:
|
||||
* Install colorama_, a Python package that translates ANSI color codes into
|
||||
Windows API calls. Django commands will detect its presence and will make use
|
||||
of its services to color output just like on Unix-based platforms.
|
||||
``colorama`` can be installed via pip::
|
||||
``colorama`` can be installed via pip:
|
||||
|
||||
.. code-block:: doscon
|
||||
|
||||
...\> py -m pip install colorama
|
||||
|
||||
@ -1863,7 +1953,9 @@ ships with three color palettes:
|
||||
You select a palette by setting a :envvar:`DJANGO_COLORS` environment
|
||||
variable to specify the palette you want to use. For example, to
|
||||
specify the ``light`` palette under a Unix or OS/X BASH shell, you
|
||||
would run the following at a command prompt::
|
||||
would run the following at a command prompt:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
export DJANGO_COLORS="light"
|
||||
|
||||
@ -1919,7 +2011,9 @@ A color specification follows one of the following patterns:
|
||||
where ``role`` is the name of a valid color role, ``fg`` is the
|
||||
foreground color, ``bg`` is the background color and each ``option``
|
||||
is one of the color modifying options. Multiple color specifications
|
||||
are then separated by a semicolon. For example::
|
||||
are then separated by a semicolon. For example:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
export DJANGO_COLORS="error=yellow/blue,blink;notice=magenta"
|
||||
|
||||
@ -1929,7 +2023,9 @@ left uncolored.
|
||||
|
||||
Colors can also be specified by extending a base palette. If you put
|
||||
a palette name in a color specification, all the colors implied by that
|
||||
palette will be loaded. So::
|
||||
palette will be loaded. So:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
export DJANGO_COLORS="light;error=yellow/blue,blink;notice=magenta"
|
||||
|
||||
@ -1961,11 +2057,15 @@ The Python files created by :djadmin:`startproject`, :djadmin:`startapp`,
|
||||
present on your ``PATH``.
|
||||
|
||||
If you have ``black`` globally installed, but do not wish it used for the
|
||||
current project, you can set the ``PATH`` explicitly::
|
||||
current project, you can set the ``PATH`` explicitly:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
PATH=path/to/venv/bin django-admin makemigrations
|
||||
|
||||
For commands using ``stdout`` you can pipe the output to ``black`` if needed::
|
||||
For commands using ``stdout`` you can pipe the output to ``black`` if needed:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
django-admin inspectdb | black -
|
||||
|
||||
|
@ -137,10 +137,14 @@ below) will also have a couple of extra methods:
|
||||
to point to it. If ``save`` is ``True``, the model's ``save()`` method will
|
||||
be called once the file is saved. That is, these two lines::
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> car.photo.save('myphoto.jpg', content, save=False)
|
||||
>>> car.save()
|
||||
|
||||
are equivalent to::
|
||||
are equivalent to:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> car.photo.save('myphoto.jpg', content, save=True)
|
||||
|
||||
|
@ -25,12 +25,16 @@ A :class:`Form` instance is either **bound** to a set of data, or **unbound**.
|
||||
|
||||
.. class:: Form
|
||||
|
||||
To create an unbound :class:`Form` instance, instantiate the class::
|
||||
To create an unbound :class:`Form` instance, instantiate the class:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> f = ContactForm()
|
||||
|
||||
To bind data to a form, pass the data as a dictionary as the first parameter to
|
||||
your :class:`Form` class constructor::
|
||||
your :class:`Form` class constructor:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> data = {'subject': 'hello',
|
||||
... 'message': 'Hi there',
|
||||
@ -47,7 +51,9 @@ in a moment.
|
||||
.. attribute:: Form.is_bound
|
||||
|
||||
If you need to distinguish between bound and unbound form instances at runtime,
|
||||
check the value of the form's :attr:`~Form.is_bound` attribute::
|
||||
check the value of the form's :attr:`~Form.is_bound` attribute:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> f = ContactForm()
|
||||
>>> f.is_bound
|
||||
@ -56,7 +62,9 @@ check the value of the form's :attr:`~Form.is_bound` attribute::
|
||||
>>> f.is_bound
|
||||
True
|
||||
|
||||
Note that passing an empty dictionary creates a *bound* form with empty data::
|
||||
Note that passing an empty dictionary creates a *bound* form with empty data:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> f = ContactForm({})
|
||||
>>> f.is_bound
|
||||
@ -81,7 +89,9 @@ validation for fields that are interdependent. See
|
||||
|
||||
The primary task of a :class:`Form` object is to validate data. With a bound
|
||||
:class:`Form` instance, call the :meth:`~Form.is_valid` method to run validation
|
||||
and return a boolean designating whether the data was valid::
|
||||
and return a boolean designating whether the data was valid:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> data = {'subject': 'hello',
|
||||
... 'message': 'Hi there',
|
||||
@ -93,7 +103,9 @@ and return a boolean designating whether the data was valid::
|
||||
|
||||
Let's try with some invalid data. In this case, ``subject`` is blank (an error,
|
||||
because all fields are required by default) and ``sender`` is not a valid
|
||||
email address::
|
||||
email address:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> data = {'subject': '',
|
||||
... 'message': 'Hi there',
|
||||
@ -106,7 +118,9 @@ email address::
|
||||
.. attribute:: Form.errors
|
||||
|
||||
Access the :attr:`~Form.errors` attribute to get a dictionary of error
|
||||
messages::
|
||||
messages:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> f.errors
|
||||
{'sender': ['Enter a valid email address.'], 'subject': ['This field is required.']}
|
||||
@ -214,7 +228,9 @@ Behavior of unbound forms
|
||||
-------------------------
|
||||
|
||||
It's meaningless to validate a form with no data, but, for the record, here's
|
||||
what happens with unbound forms::
|
||||
what happens with unbound forms:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> f = ContactForm()
|
||||
>>> f.is_valid()
|
||||
@ -236,7 +252,9 @@ username of the current session.
|
||||
To accomplish this, use the :attr:`~Form.initial` argument to a :class:`Form`.
|
||||
This argument, if given, should be a dictionary mapping field names to initial
|
||||
values. Only include the fields for which you're specifying an initial value;
|
||||
it's not necessary to include every field in your form. For example::
|
||||
it's not necessary to include every field in your form. For example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> f = ContactForm(initial={'subject': 'Hi there!'})
|
||||
|
||||
@ -247,7 +265,9 @@ If a :class:`~django.forms.Field` defines :attr:`~Field.initial` *and* you
|
||||
include :attr:`~Form.initial` when instantiating the ``Form``, then the latter
|
||||
``initial`` will have precedence. In this example, ``initial`` is provided both
|
||||
at the field level and at the form instance level, and the latter gets
|
||||
precedence::
|
||||
precedence:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django import forms
|
||||
>>> class CommentForm(forms.Form):
|
||||
@ -271,7 +291,9 @@ It is recommended to use :attr:`BoundField.initial` over
|
||||
simpler interface. Also, unlike :meth:`~Form.get_initial_for_field()`,
|
||||
:attr:`BoundField.initial` caches its values. This is useful especially when
|
||||
dealing with callables whose return values can change (e.g. ``datetime.now`` or
|
||||
``uuid.uuid4``)::
|
||||
``uuid.uuid4``):
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> import uuid
|
||||
>>> class UUIDCommentForm(CommentForm):
|
||||
@ -332,7 +354,9 @@ Accessing the fields from the form
|
||||
.. attribute:: Form.fields
|
||||
|
||||
You can access the fields of :class:`Form` instance from its ``fields``
|
||||
attribute::
|
||||
attribute:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> for row in f.fields.values(): print(row)
|
||||
...
|
||||
@ -343,7 +367,9 @@ attribute::
|
||||
<django.forms.fields.CharField object at 0x7ffaac6324d0>
|
||||
|
||||
You can alter the field and :class:`.BoundField` of :class:`Form` instance to
|
||||
change the way it is presented in the form::
|
||||
change the way it is presented in the form:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> f.as_div().split("</div>")[0]
|
||||
'<div><label for="id_subject">Subject:</label><input type="text" name="subject" maxlength="100" required id="id_subject">'
|
||||
@ -353,7 +379,9 @@ change the way it is presented in the form::
|
||||
|
||||
Beware not to alter the ``base_fields`` attribute because this modification
|
||||
will influence all subsequent ``ContactForm`` instances within the same Python
|
||||
process::
|
||||
process:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> f.base_fields["subject"].label_suffix = "?"
|
||||
>>> another_f = CommentForm(auto_id=False)
|
||||
@ -377,7 +405,9 @@ formats, ``DateField`` will always normalize it to a ``datetime.date`` object
|
||||
as long as it's valid.
|
||||
|
||||
Once you've created a :class:`~Form` instance with a set of data and validated
|
||||
it, you can access the clean data via its ``cleaned_data`` attribute::
|
||||
it, you can access the clean data via its ``cleaned_data`` attribute:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> data = {'subject': 'hello',
|
||||
... 'message': 'Hi there',
|
||||
@ -394,7 +424,9 @@ always cleans the input into a string. We'll cover the encoding implications
|
||||
later in this document.
|
||||
|
||||
If your data does *not* validate, the ``cleaned_data`` dictionary contains
|
||||
only the valid fields::
|
||||
only the valid fields:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> data = {'subject': '',
|
||||
... 'message': 'Hi there',
|
||||
@ -409,7 +441,9 @@ only the valid fields::
|
||||
``cleaned_data`` will always *only* contain a key for fields defined in the
|
||||
``Form``, even if you pass extra data when you define the ``Form``. In this
|
||||
example, we pass a bunch of extra fields to the ``ContactForm`` constructor,
|
||||
but ``cleaned_data`` contains only the form's fields::
|
||||
but ``cleaned_data`` contains only the form's fields:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> data = {'subject': 'hello',
|
||||
... 'message': 'Hi there',
|
||||
@ -427,7 +461,9 @@ but ``cleaned_data`` contains only the form's fields::
|
||||
When the ``Form`` is valid, ``cleaned_data`` will include a key and value for
|
||||
*all* its fields, even if the data didn't include a value for some optional
|
||||
fields. In this example, the data dictionary doesn't include a value for the
|
||||
``nick_name`` field, but ``cleaned_data`` includes it, with an empty value::
|
||||
``nick_name`` field, but ``cleaned_data`` includes it, with an empty value:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django import forms
|
||||
>>> class OptionalPersonForm(forms.Form):
|
||||
@ -458,7 +494,9 @@ Outputting forms as HTML
|
||||
========================
|
||||
|
||||
The second task of a ``Form`` object is to render itself as HTML. To do so,
|
||||
``print`` it::
|
||||
``print`` it:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> f = ContactForm()
|
||||
>>> print(f)
|
||||
@ -471,7 +509,9 @@ If the form is bound to data, the HTML output will include that data
|
||||
appropriately. For example, if a field is represented by an
|
||||
``<input type="text">``, the data will be in the ``value`` attribute. If a
|
||||
field is represented by an ``<input type="checkbox">``, then that HTML will
|
||||
include ``checked`` if appropriate::
|
||||
include ``checked`` if appropriate:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> data = {'subject': 'hello',
|
||||
... 'message': 'Hi there',
|
||||
@ -649,7 +689,9 @@ The template used by ``as_p()``. Default: ``'django/forms/p.html'``.
|
||||
.. method:: Form.as_p()
|
||||
|
||||
``as_p()`` renders the form as a series of ``<p>`` tags, with each ``<p>``
|
||||
containing one field::
|
||||
containing one field:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> f = ContactForm()
|
||||
>>> f.as_p()
|
||||
@ -671,7 +713,9 @@ The template used by ``as_ul()``. Default: ``'django/forms/ul.html'``.
|
||||
|
||||
``as_ul()`` renders the form as a series of ``<li>`` tags, with each ``<li>``
|
||||
containing one field. It does *not* include the ``<ul>`` or ``</ul>``, so that
|
||||
you can specify any HTML attributes on the ``<ul>`` for flexibility::
|
||||
you can specify any HTML attributes on the ``<ul>`` for flexibility:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> f = ContactForm()
|
||||
>>> f.as_ul()
|
||||
@ -691,7 +735,9 @@ The template used by ``as_table()``. Default: ``'django/forms/table.html'``.
|
||||
|
||||
.. method:: Form.as_table()
|
||||
|
||||
``as_table()`` renders the form as an HTML ``<table>``::
|
||||
``as_table()`` renders the form as an HTML ``<table>``:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> f = ContactForm()
|
||||
>>> f.as_table()
|
||||
@ -728,7 +774,9 @@ attributes::
|
||||
# ... and the rest of your fields here
|
||||
|
||||
Once you've done that, rows will be given ``"error"`` and/or ``"required"``
|
||||
classes, as needed. The HTML will look something like::
|
||||
classes, as needed. The HTML will look something like:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> f = ContactForm(data)
|
||||
>>> print(f.as_table())
|
||||
@ -770,7 +818,9 @@ Use the ``auto_id`` argument to the ``Form`` constructor to control the ``id``
|
||||
and label behavior. This argument must be ``True``, ``False`` or a string.
|
||||
|
||||
If ``auto_id`` is ``False``, then the form output will not include ``<label>``
|
||||
tags nor ``id`` attributes::
|
||||
tags nor ``id`` attributes:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> f = ContactForm(auto_id=False)
|
||||
>>> print(f.as_div())
|
||||
@ -781,7 +831,9 @@ tags nor ``id`` attributes::
|
||||
|
||||
If ``auto_id`` is set to ``True``, then the form output *will* include
|
||||
``<label>`` tags and will use the field name as its ``id`` for each form
|
||||
field::
|
||||
field:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> f = ContactForm(auto_id=True)
|
||||
>>> print(f.as_div())
|
||||
@ -794,7 +846,9 @@ If ``auto_id`` is set to a string containing the format character ``'%s'``,
|
||||
then the form output will include ``<label>`` tags, and will generate ``id``
|
||||
attributes based on the format string. For example, for a format string
|
||||
``'field_%s'``, a field named ``subject`` will get the ``id`` value
|
||||
``'field_subject'``. Continuing our example::
|
||||
``'field_subject'``. Continuing our example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> f = ContactForm(auto_id='id_for_%s')
|
||||
>>> print(f.as_div())
|
||||
@ -814,7 +868,9 @@ A translatable string (defaults to a colon (``:``) in English) that will be
|
||||
appended after any label name when a form is rendered.
|
||||
|
||||
It's possible to customize that character, or omit it entirely, using the
|
||||
``label_suffix`` parameter::
|
||||
``label_suffix`` parameter:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> f = ContactForm(auto_id='id_for_%s', label_suffix='')
|
||||
>>> print(f.as_div())
|
||||
@ -907,7 +963,9 @@ If you render a bound ``Form`` object, the act of rendering will automatically
|
||||
run the form's validation if it hasn't already happened, and the HTML output
|
||||
will include the validation errors as a ``<ul class="errorlist">`` near the
|
||||
field. The particular positioning of the error messages depends on the output
|
||||
method you're using::
|
||||
method you're using:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> data = {'subject': '',
|
||||
... 'message': 'Hi there',
|
||||
@ -1029,13 +1087,17 @@ they're not the only way a form object can be displayed.
|
||||
The ``__str__()`` method of this object displays the HTML for this field.
|
||||
|
||||
To retrieve a single ``BoundField``, use dictionary lookup syntax on your form
|
||||
using the field's name as the key::
|
||||
using the field's name as the key:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> form = ContactForm()
|
||||
>>> print(form['subject'])
|
||||
<input id="id_subject" type="text" name="subject" maxlength="100" required>
|
||||
|
||||
To retrieve all ``BoundField`` objects, iterate the form::
|
||||
To retrieve all ``BoundField`` objects, iterate the form:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> form = ContactForm()
|
||||
>>> for boundfield in form: print(boundfield)
|
||||
@ -1044,7 +1106,9 @@ To retrieve all ``BoundField`` objects, iterate the form::
|
||||
<input type="email" name="sender" id="id_sender" required>
|
||||
<input type="checkbox" name="cc_myself" id="id_cc_myself">
|
||||
|
||||
The field-specific output honors the form object's ``auto_id`` setting::
|
||||
The field-specific output honors the form object's ``auto_id`` setting:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> f = ContactForm(auto_id=False)
|
||||
>>> print(f['message'])
|
||||
@ -1065,7 +1129,9 @@ Attributes of ``BoundField``
|
||||
|
||||
This property returns the data for this :class:`~django.forms.BoundField`
|
||||
extracted by the widget's :meth:`~django.forms.Widget.value_from_datadict`
|
||||
method, or ``None`` if it wasn't given::
|
||||
method, or ``None`` if it wasn't given:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> unbound_form = ContactForm()
|
||||
>>> print(unbound_form['subject'].data)
|
||||
@ -1077,7 +1143,9 @@ Attributes of ``BoundField``
|
||||
.. attribute:: BoundField.errors
|
||||
|
||||
A :ref:`list-like object <ref-forms-error-list-format>` that is displayed
|
||||
as an HTML ``<ul class="errorlist">`` when printed::
|
||||
as an HTML ``<ul class="errorlist">`` when printed:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> data = {'subject': 'hi', 'message': '', 'sender': '', 'cc_myself': ''}
|
||||
>>> f = ContactForm(data, auto_id=False)
|
||||
@ -1146,7 +1214,9 @@ Attributes of ``BoundField``
|
||||
|
||||
:attr:`BoundField.initial` caches its return value, which is useful
|
||||
especially when dealing with callables whose return values can change (e.g.
|
||||
``datetime.now`` or ``uuid.uuid4``)::
|
||||
``datetime.now`` or ``uuid.uuid4``):
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from datetime import datetime
|
||||
>>> class DatedCommentForm(CommentForm):
|
||||
@ -1172,7 +1242,9 @@ Attributes of ``BoundField``
|
||||
|
||||
.. attribute:: BoundField.name
|
||||
|
||||
The name of this field in the form::
|
||||
The name of this field in the form:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> f = ContactForm()
|
||||
>>> print(f['subject'].name)
|
||||
@ -1188,7 +1260,9 @@ Attributes of ``BoundField``
|
||||
|
||||
Returns the lowercased class name of the wrapped field's widget, with any
|
||||
trailing ``input`` or ``widget`` removed. This may be used when building
|
||||
forms where the layout is dependent upon the widget type. For example::
|
||||
forms where the layout is dependent upon the widget type. For example:
|
||||
|
||||
.. code-block:: html+django
|
||||
|
||||
{% for field in form %}
|
||||
{% if field.widget_type == 'checkbox' %}
|
||||
@ -1224,7 +1298,9 @@ Methods of ``BoundField``
|
||||
When you use Django's rendering shortcuts, CSS classes are used to
|
||||
indicate required form fields or fields that contain errors. If you're
|
||||
manually rendering a form, you can access these CSS classes using the
|
||||
``css_classes`` method::
|
||||
``css_classes`` method:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> f = ContactForm(data={'message': ''})
|
||||
>>> f['message'].css_classes()
|
||||
@ -1232,7 +1308,9 @@ Methods of ``BoundField``
|
||||
|
||||
If you want to provide some additional classes in addition to the
|
||||
error and required classes that may be required, you can provide
|
||||
those classes as an argument::
|
||||
those classes as an argument:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> f = ContactForm(data={'message': ''})
|
||||
>>> f['message'].css_classes('foo bar')
|
||||
@ -1265,7 +1343,9 @@ Methods of ``BoundField``
|
||||
the field you declare, e.g. ``forms.CharField``.
|
||||
|
||||
To separately render the label tag of a form field, you can call its
|
||||
``label_tag()`` method::
|
||||
``label_tag()`` method:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> f = ContactForm(data={'message': ''})
|
||||
>>> print(f['message'].label_tag())
|
||||
@ -1286,7 +1366,9 @@ Methods of ``BoundField``
|
||||
.. method:: BoundField.value()
|
||||
|
||||
Use this method to render the raw value of this field as it would be rendered
|
||||
by a ``Widget``::
|
||||
by a ``Widget``:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> initial = {'subject': 'welcome'}
|
||||
>>> unbound_form = ContactForm(initial=initial)
|
||||
@ -1346,7 +1428,9 @@ is a little more complicated than a normal form.
|
||||
|
||||
Firstly, in order to upload files, you'll need to make sure that your
|
||||
``<form>`` element correctly defines the ``enctype`` as
|
||||
``"multipart/form-data"``::
|
||||
``"multipart/form-data"``:
|
||||
|
||||
.. code-block:: html
|
||||
|
||||
<form enctype="multipart/form-data" method="post" action="/foo/">
|
||||
|
||||
@ -1355,7 +1439,9 @@ data is handled separately to normal form data, so when your form
|
||||
contains a ``FileField`` and ``ImageField``, you will need to specify
|
||||
a second argument when you bind your form. So if we extend our
|
||||
ContactForm to include an ``ImageField`` called ``mugshot``, we
|
||||
need to bind the file data containing the mugshot image::
|
||||
need to bind the file data containing the mugshot image:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
# Bound form with an image field
|
||||
>>> from django.core.files.uploadedfile import SimpleUploadedFile
|
||||
@ -1368,13 +1454,17 @@ need to bind the file data containing the mugshot image::
|
||||
|
||||
In practice, you will usually specify ``request.FILES`` as the source
|
||||
of file data (just like you use ``request.POST`` as the source of
|
||||
form data)::
|
||||
form data):
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
# Bound form with an image field, data from the request
|
||||
>>> f = ContactFormWithMugshot(request.POST, request.FILES)
|
||||
|
||||
Constructing an unbound form is the same as always -- omit both form data *and*
|
||||
file data::
|
||||
file data:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
# Unbound form with an image field
|
||||
>>> f = ContactFormWithMugshot()
|
||||
@ -1386,13 +1476,17 @@ Testing for multipart forms
|
||||
|
||||
If you're writing reusable views or templates, you may not know ahead of time
|
||||
whether your form is a multipart form or not. The ``is_multipart()`` method
|
||||
tells you whether the form requires multipart encoding for submission::
|
||||
tells you whether the form requires multipart encoding for submission:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> f = ContactFormWithMugshot()
|
||||
>>> f.is_multipart()
|
||||
True
|
||||
|
||||
Here's an example of how you might use this in a template::
|
||||
Here's an example of how you might use this in a template:
|
||||
|
||||
.. code-block:: html+django
|
||||
|
||||
{% if form.is_multipart %}
|
||||
<form enctype="multipart/form-data" method="post" action="/foo/">
|
||||
@ -1414,7 +1508,9 @@ in the subclass.
|
||||
|
||||
In this example, ``ContactFormWithPriority`` contains all the fields from
|
||||
``ContactForm``, plus an additional field, ``priority``. The ``ContactForm``
|
||||
fields are ordered first::
|
||||
fields are ordered first:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> class ContactFormWithPriority(ContactForm):
|
||||
... priority = forms.CharField()
|
||||
@ -1429,7 +1525,9 @@ fields are ordered first::
|
||||
It's possible to subclass multiple forms, treating forms as mixins. In this
|
||||
example, ``BeatleForm`` subclasses both ``PersonForm`` and ``InstrumentForm``
|
||||
(in that order), and its field list includes the fields from the parent
|
||||
classes::
|
||||
classes:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django import forms
|
||||
>>> class PersonForm(forms.Form):
|
||||
@ -1447,7 +1545,9 @@ classes::
|
||||
<div>Haircut type:<input type="text" name="haircut_type" required></div>
|
||||
|
||||
It's possible to declaratively remove a ``Field`` inherited from a parent class
|
||||
by setting the name of the field to ``None`` on the subclass. For example::
|
||||
by setting the name of the field to ``None`` on the subclass. For example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django import forms
|
||||
|
||||
@ -1469,7 +1569,9 @@ Prefixes for forms
|
||||
.. attribute:: Form.prefix
|
||||
|
||||
You can put several Django forms inside one ``<form>`` tag. To give each
|
||||
``Form`` its own namespace, use the ``prefix`` keyword argument::
|
||||
``Form`` its own namespace, use the ``prefix`` keyword argument:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> mother = PersonForm(prefix="mother")
|
||||
>>> father = PersonForm(prefix="father")
|
||||
@ -1480,7 +1582,9 @@ You can put several Django forms inside one ``<form>`` tag. To give each
|
||||
<div><label for="id_father-first_name">First name:</label><input type="text" name="father-first_name" required id="id_father-first_name"></div>
|
||||
<div><label for="id_father-last_name">Last name:</label><input type="text" name="father-last_name" required id="id_father-last_name"></div>
|
||||
|
||||
The prefix can also be specified on the form class::
|
||||
The prefix can also be specified on the form class:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> class PersonForm(forms.Form):
|
||||
... ...
|
||||
|
@ -20,7 +20,9 @@ you can also instantiate them and use them directly to get a better idea of
|
||||
how they work. Each ``Field`` instance has a ``clean()`` method, which takes
|
||||
a single argument and either raises a
|
||||
``django.core.exceptions.ValidationError`` exception or returns the clean
|
||||
value::
|
||||
value:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django import forms
|
||||
>>> f = forms.EmailField()
|
||||
@ -47,7 +49,9 @@ should *always* be accepted:
|
||||
|
||||
By default, each ``Field`` class assumes the value is required, so if you pass
|
||||
an empty value -- either ``None`` or the empty string (``""``) -- then
|
||||
``clean()`` will raise a ``ValidationError`` exception::
|
||||
``clean()`` will raise a ``ValidationError`` exception:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django import forms
|
||||
>>> f = forms.CharField()
|
||||
@ -71,7 +75,9 @@ an empty value -- either ``None`` or the empty string (``""``) -- then
|
||||
'False'
|
||||
|
||||
To specify that a field is *not* required, pass ``required=False`` to the
|
||||
``Field`` constructor::
|
||||
``Field`` constructor:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> f = forms.CharField(required=False)
|
||||
>>> f.clean('foo')
|
||||
@ -112,7 +118,9 @@ spaces and upper-casing the first letter. Specify ``label`` if that default
|
||||
behavior doesn't result in an adequate label.
|
||||
|
||||
Here's a full example ``Form`` that implements ``label`` for two of its fields.
|
||||
We've specified ``auto_id=False`` to simplify the output::
|
||||
We've specified ``auto_id=False`` to simplify the output:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django import forms
|
||||
>>> class CommentForm(forms.Form):
|
||||
@ -131,7 +139,9 @@ We've specified ``auto_id=False`` to simplify the output::
|
||||
.. attribute:: Field.label_suffix
|
||||
|
||||
The ``label_suffix`` argument lets you override the form's
|
||||
:attr:`~django.forms.Form.label_suffix` on a per-field basis::
|
||||
:attr:`~django.forms.Form.label_suffix` on a per-field basis:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> class ContactForm(forms.Form):
|
||||
... age = forms.IntegerField()
|
||||
@ -154,7 +164,9 @@ rendering this ``Field`` in an unbound ``Form``.
|
||||
To specify dynamic initial data, see the :attr:`Form.initial` parameter.
|
||||
|
||||
The use-case for this is when you want to display an "empty" form in which a
|
||||
field is initialized to a particular value. For example::
|
||||
field is initialized to a particular value. For example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django import forms
|
||||
>>> class CommentForm(forms.Form):
|
||||
@ -169,7 +181,9 @@ field is initialized to a particular value. For example::
|
||||
|
||||
You may be thinking, why not just pass a dictionary of the initial values as
|
||||
data when displaying the form? Well, if you do that, you'll trigger validation,
|
||||
and the HTML output will include any validation errors::
|
||||
and the HTML output will include any validation errors:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> class CommentForm(forms.Form):
|
||||
... name = forms.CharField()
|
||||
@ -187,7 +201,9 @@ forms, the HTML output will use the bound data.
|
||||
|
||||
Also note that ``initial`` values are *not* used as "fallback" data in
|
||||
validation if a particular field's value is not given. ``initial`` values are
|
||||
*only* intended for initial form display::
|
||||
*only* intended for initial form display:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> class CommentForm(forms.Form):
|
||||
... name = forms.CharField(initial='Your name')
|
||||
@ -201,7 +217,9 @@ validation if a particular field's value is not given. ``initial`` values are
|
||||
>>> f.errors
|
||||
{'url': ['This field is required.'], 'name': ['This field is required.']}
|
||||
|
||||
Instead of a constant, you can also pass any callable::
|
||||
Instead of a constant, you can also pass any callable:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> import datetime
|
||||
>>> class DateForm(forms.Form):
|
||||
@ -233,7 +251,9 @@ Like the model field's :attr:`~django.db.models.Field.help_text`, this value
|
||||
isn't HTML-escaped in automatically-generated forms.
|
||||
|
||||
Here's a full example ``Form`` that implements ``help_text`` for two of its
|
||||
fields. We've specified ``auto_id=False`` to simplify the output::
|
||||
fields. We've specified ``auto_id=False`` to simplify the output:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django import forms
|
||||
>>> class HelpTextContactForm(forms.Form):
|
||||
@ -265,7 +285,9 @@ fields. We've specified ``auto_id=False`` to simplify the output::
|
||||
|
||||
The ``error_messages`` argument lets you override the default messages that the
|
||||
field will raise. Pass in a dictionary with keys matching the error messages you
|
||||
want to override. For example, here is the default error message::
|
||||
want to override. For example, here is the default error message:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django import forms
|
||||
>>> generic = forms.CharField()
|
||||
@ -274,7 +296,9 @@ want to override. For example, here is the default error message::
|
||||
...
|
||||
ValidationError: ['This field is required.']
|
||||
|
||||
And here is a custom error message::
|
||||
And here is a custom error message:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> name = forms.CharField(error_messages={'required': 'Please enter your name'})
|
||||
>>> name.clean('')
|
||||
@ -463,15 +487,15 @@ For each field, we describe the default widget used if you don't specify
|
||||
|
||||
The field always accepts strings in ISO 8601 formatted dates or similar
|
||||
recognized by :func:`~django.utils.dateparse.parse_datetime`. Some examples
|
||||
are::
|
||||
are:
|
||||
|
||||
* '2006-10-25 14:30:59'
|
||||
* '2006-10-25T14:30:59'
|
||||
* '2006-10-25 14:30'
|
||||
* '2006-10-25T14:30'
|
||||
* '2006-10-25T14:30Z'
|
||||
* '2006-10-25T14:30+02:00'
|
||||
* '2006-10-25'
|
||||
* ``'2006-10-25 14:30:59'``
|
||||
* ``'2006-10-25T14:30:59'``
|
||||
* ``'2006-10-25 14:30'``
|
||||
* ``'2006-10-25T14:30'``
|
||||
* ``'2006-10-25T14:30Z'``
|
||||
* ``'2006-10-25T14:30+02:00'``
|
||||
* ``'2006-10-25'``
|
||||
|
||||
If no ``input_formats`` argument is provided, the default input formats are
|
||||
taken from the active locale format ``DATETIME_INPUT_FORMATS`` and
|
||||
@ -723,7 +747,9 @@ For each field, we describe the default widget used if you don't specify
|
||||
non-image data attributes, such as ``format``, ``height``, and ``width``,
|
||||
are available, methods that access the underlying image data, such as
|
||||
``getdata()`` or ``getpixel()``, cannot be used without reopening the file.
|
||||
For example::
|
||||
For example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from PIL import Image
|
||||
>>> from django import forms
|
||||
|
@ -86,7 +86,9 @@ buttons.
|
||||
:class:`Select` widgets are used by default on :class:`ChoiceField` fields. The
|
||||
choices displayed on the widget are inherited from the :class:`ChoiceField` and
|
||||
changing :attr:`ChoiceField.choices` will update :attr:`Select.choices`. For
|
||||
example::
|
||||
example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django import forms
|
||||
>>> CHOICES = [('1', 'First'), ('2', 'Second')]
|
||||
@ -137,7 +139,9 @@ For example, take the following form::
|
||||
|
||||
This form will include three default :class:`TextInput` widgets, with default
|
||||
rendering -- no CSS class, no extra attributes. This means that the input boxes
|
||||
provided for each widget will be rendered exactly the same::
|
||||
provided for each widget will be rendered exactly the same:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> f = CommentForm(auto_id=False)
|
||||
>>> f.as_table()
|
||||
@ -232,7 +236,9 @@ foundation for custom widgets.
|
||||
'<input title="Your name" type="text" name="name" value="A name" size="10">'
|
||||
|
||||
If you assign a value of ``True`` or ``False`` to an attribute,
|
||||
it will be rendered as an HTML5 boolean attribute::
|
||||
it will be rendered as an HTML5 boolean attribute:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> name = forms.TextInput(attrs={'required': True})
|
||||
>>> name.render('name', 'A name')
|
||||
@ -361,7 +367,9 @@ foundation for custom widgets.
|
||||
|
||||
.. attribute:: MultiWidget.widgets
|
||||
|
||||
An iterable containing the widgets needed. For example::
|
||||
An iterable containing the widgets needed. For example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.forms import MultiWidget, TextInput
|
||||
>>> widget = MultiWidget(widgets=[TextInput, TextInput])
|
||||
@ -373,7 +381,9 @@ foundation for custom widgets.
|
||||
``(key, widget)`` pair, the key will be appended to the ``name`` of the
|
||||
widget in order to generate the attribute value. You may provide the
|
||||
empty string (``''``) for a single key, in order to suppress the suffix
|
||||
for one widget. For example::
|
||||
for one widget. For example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> widget = MultiWidget(widgets={'': TextInput, 'last': TextInput})
|
||||
>>> widget.render('name', ['john', 'paul'])
|
||||
|
@ -48,7 +48,9 @@ objects that have an ``output_field`` that is a
|
||||
:class:`~django.db.models.BooleanField`. The result is provided using the
|
||||
``then`` keyword.
|
||||
|
||||
Some examples::
|
||||
Some examples:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.db.models import F, Q, When
|
||||
>>> # String arguments refer to fields; the following two examples are equivalent:
|
||||
@ -83,7 +85,9 @@ Keep in mind that each of these values can be an expression.
|
||||
Since the ``then`` keyword argument is reserved for the result of the
|
||||
``When()``, there is a potential conflict if a
|
||||
:class:`~django.db.models.Model` has a field named ``then``. This can be
|
||||
resolved in two ways::
|
||||
resolved in two ways:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> When(then__exact=0, then=1)
|
||||
>>> When(Q(then=0), then=1)
|
||||
@ -99,7 +103,9 @@ A ``Case()`` expression is like the :keyword:`if` ... :keyword:`elif` ...
|
||||
truthful value. The ``result`` expression from the matching ``When()`` object
|
||||
is returned.
|
||||
|
||||
An example::
|
||||
An example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>>
|
||||
>>> from datetime import date, timedelta
|
||||
@ -133,7 +139,9 @@ argument is returned. If a ``default`` argument isn't provided, ``None`` is
|
||||
used.
|
||||
|
||||
If we wanted to change our previous query to get the discount based on how long
|
||||
the ``Client`` has been with us, we could do so using lookups::
|
||||
the ``Client`` has been with us, we could do so using lookups:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> a_month_ago = date.today() - timedelta(days=30)
|
||||
>>> a_year_ago = date.today() - timedelta(days=365)
|
||||
@ -156,7 +164,9 @@ the ``Client`` has been with us, we could do so using lookups::
|
||||
|
||||
``Case()`` also works in a ``filter()`` clause. For example, to find gold
|
||||
clients that registered more than a month ago and platinum clients that
|
||||
registered more than a year ago::
|
||||
registered more than a year ago:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> a_month_ago = date.today() - timedelta(days=30)
|
||||
>>> a_year_ago = date.today() - timedelta(days=365)
|
||||
@ -180,7 +190,9 @@ Conditional update
|
||||
|
||||
Let's say we want to change the ``account_type`` for our clients to match
|
||||
their registration dates. We can do this using a conditional expression and the
|
||||
:meth:`~django.db.models.query.QuerySet.update` method::
|
||||
:meth:`~django.db.models.query.QuerySet.update` method:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> a_month_ago = date.today() - timedelta(days=30)
|
||||
>>> a_year_ago = date.today() - timedelta(days=365)
|
||||
@ -204,7 +216,9 @@ Conditional aggregation
|
||||
|
||||
What if we want to find out how many clients there are for each
|
||||
``account_type``? We can use the ``filter`` argument of :ref:`aggregate
|
||||
functions <aggregation-functions>` to achieve this::
|
||||
functions <aggregation-functions>` to achieve this:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> # Create some more Clients first so we can have something to count
|
||||
>>> Client.objects.create(
|
||||
@ -255,7 +269,9 @@ Conditional filter
|
||||
|
||||
When a conditional expression returns a boolean value, it is possible to use it
|
||||
directly in filters. This means that it will not be added to the ``SELECT``
|
||||
columns, but you can still use it to filter results::
|
||||
columns, but you can still use it to filter results:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> non_unique_account_type = Client.objects.filter(
|
||||
... account_type=OuterRef('account_type'),
|
||||
|
@ -35,7 +35,9 @@ Comparison and conversion functions
|
||||
|
||||
Forces the result type of ``expression`` to be the one from ``output_field``.
|
||||
|
||||
Usage example::
|
||||
Usage example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.db.models import FloatField
|
||||
>>> from django.db.models.functions import Cast
|
||||
@ -56,7 +58,9 @@ first non-null value (note that an empty string is not considered a null
|
||||
value). Each argument must be of a similar type, so mixing text and numbers
|
||||
will result in a database error.
|
||||
|
||||
Usage examples::
|
||||
Usage examples:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> # Get a screen name from least to most public
|
||||
>>> from django.db.models import Sum
|
||||
@ -99,12 +103,16 @@ Usage examples::
|
||||
|
||||
Takes an expression and a collation name to query against.
|
||||
|
||||
For example, to filter case-insensitively in SQLite::
|
||||
For example, to filter case-insensitively in SQLite:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Author.objects.filter(name=Collate(Value('john'), 'nocase'))
|
||||
<QuerySet [<Author: John>, <Author: john>]>
|
||||
|
||||
It can also be used when ordering, for example with PostgreSQL::
|
||||
It can also be used when ordering, for example with PostgreSQL:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Author.objects.order_by(Collate('name', 'et-x-icu'))
|
||||
<QuerySet [<Author: Ursula>, <Author: Veronika>, <Author: Ülle>]>
|
||||
@ -129,6 +137,8 @@ Usage example::
|
||||
modified = models.DateTimeField(auto_now=True)
|
||||
blog = models.ForeignKey(Blog, on_delete=models.CASCADE)
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.db.models.functions import Greatest
|
||||
>>> blog = Blog.objects.create(body='Greatest is the best.')
|
||||
>>> comment = Comment.objects.create(body='No, Least is better.', blog=blog)
|
||||
@ -159,7 +169,9 @@ and ``comment.modified``.
|
||||
Takes a list of key-value pairs and returns a JSON object containing those
|
||||
pairs.
|
||||
|
||||
Usage example::
|
||||
Usage example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.db.models import F
|
||||
>>> from django.db.models.functions import JSONObject, Lower
|
||||
@ -272,7 +284,9 @@ returned when this timezone is active will be the same as above except for:
|
||||
databases and from Python's standard functions. This function will return
|
||||
``1`` for Sunday, ``2`` for Monday, through ``7`` for Saturday.
|
||||
|
||||
The equivalent calculation in Python is::
|
||||
The equivalent calculation in Python is:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from datetime import datetime
|
||||
>>> dt = datetime(2015, 6, 15)
|
||||
@ -292,7 +306,9 @@ Each ``lookup_name`` above has a corresponding ``Extract`` subclass (listed
|
||||
below) that should typically be used instead of the more verbose equivalent,
|
||||
e.g. use ``ExtractYear(...)`` rather than ``Extract(..., lookup_name='year')``.
|
||||
|
||||
Usage example::
|
||||
Usage example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from datetime import datetime
|
||||
>>> from django.db.models.functions import Extract
|
||||
@ -356,7 +372,9 @@ class is also a ``Transform`` registered on ``DateField`` and ``DateTimeField``
|
||||
as ``__(lookup_name)``, e.g. ``__year``.
|
||||
|
||||
Since ``DateField``\s don't have a time component, only ``Extract`` subclasses
|
||||
that deal with date-parts can be used with ``DateField``::
|
||||
that deal with date-parts can be used with ``DateField``:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from datetime import datetime, timezone
|
||||
>>> from django.db.models.functions import (
|
||||
@ -406,7 +424,9 @@ These are logically equivalent to ``Extract('datetime_field', lookup_name)``.
|
||||
Each class is also a ``Transform`` registered on ``DateTimeField`` as
|
||||
``__(lookup_name)``, e.g. ``__minute``.
|
||||
|
||||
``DateTimeField`` examples::
|
||||
``DateTimeField`` examples:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from datetime import datetime, timezone
|
||||
>>> from django.db.models.functions import (
|
||||
@ -443,7 +463,9 @@ When :setting:`USE_TZ` is ``True`` then datetimes are stored in the database
|
||||
in UTC. If a different timezone is active in Django, the datetime is converted
|
||||
to that timezone before the value is extracted. The example below converts to
|
||||
the Melbourne timezone (UTC +10:00), which changes the day, weekday, and hour
|
||||
values that are returned::
|
||||
values that are returned:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.utils import timezone
|
||||
>>> import zoneinfo
|
||||
@ -460,7 +482,9 @@ values that are returned::
|
||||
{'day': 16, 'weekday': 3, 'isoweekday': 2, 'hour': 9}
|
||||
|
||||
Explicitly passing the timezone to the ``Extract`` function behaves in the same
|
||||
way, and takes priority over an active timezone::
|
||||
way, and takes priority over an active timezone:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> import zoneinfo
|
||||
>>> melb = zoneinfo.ZoneInfo('Australia/Melbourne')
|
||||
@ -482,7 +506,9 @@ way, and takes priority over an active timezone::
|
||||
Returns the database server's current date and time when the query is executed,
|
||||
typically using the SQL ``CURRENT_TIMESTAMP``.
|
||||
|
||||
Usage example::
|
||||
Usage example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.db.models.functions import Now
|
||||
>>> Article.objects.filter(published__lte=Now())
|
||||
@ -558,7 +584,9 @@ The subclasses are all defined as transforms, but they aren't registered with
|
||||
any fields, because the lookup names are already reserved by the ``Extract``
|
||||
subclasses.
|
||||
|
||||
Usage example::
|
||||
Usage example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from datetime import datetime
|
||||
>>> from django.db.models import Count, DateTimeField
|
||||
@ -610,7 +638,9 @@ with less precision. ``expression`` can have an ``output_field`` of either
|
||||
``DateField`` or ``DateTimeField``.
|
||||
|
||||
Since ``DateField``\s don't have a time component, only ``Trunc`` subclasses
|
||||
that deal with date-parts can be used with ``DateField``::
|
||||
that deal with date-parts can be used with ``DateField``:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from datetime import datetime, timezone
|
||||
>>> from django.db.models import Count
|
||||
@ -684,7 +714,9 @@ truncate all parts of the date up to ``kind`` and allow grouping or filtering
|
||||
datetimes with less precision. ``expression`` must have an ``output_field`` of
|
||||
``DateTimeField``.
|
||||
|
||||
Usage example::
|
||||
Usage example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from datetime import date, datetime, timezone
|
||||
>>> from django.db.models import Count
|
||||
@ -733,7 +765,9 @@ with less precision. ``expression`` can have an ``output_field`` of either
|
||||
``TimeField`` or ``DateTimeField``.
|
||||
|
||||
Since ``TimeField``\s don't have a date component, only ``Trunc`` subclasses
|
||||
that deal with time-parts can be used with ``TimeField``::
|
||||
that deal with time-parts can be used with ``TimeField``:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from datetime import datetime, timezone
|
||||
>>> from django.db.models import Count, TimeField
|
||||
@ -782,7 +816,9 @@ We'll be using the following model in math function examples::
|
||||
|
||||
Returns the absolute value of a numeric field or expression.
|
||||
|
||||
Usage example::
|
||||
Usage example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.db.models.functions import Abs
|
||||
>>> Vector.objects.create(x=-0.5, y=1.1)
|
||||
@ -790,7 +826,9 @@ Usage example::
|
||||
>>> vector.x_abs, vector.y_abs
|
||||
(0.5, 1.1)
|
||||
|
||||
It can also be registered as a transform. For example::
|
||||
It can also be registered as a transform. For example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.db.models import FloatField
|
||||
>>> from django.db.models.functions import Abs
|
||||
@ -806,7 +844,9 @@ It can also be registered as a transform. For example::
|
||||
Returns the arccosine of a numeric field or expression. The expression value
|
||||
must be within the range -1 to 1.
|
||||
|
||||
Usage example::
|
||||
Usage example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.db.models.functions import ACos
|
||||
>>> Vector.objects.create(x=0.5, y=-0.9)
|
||||
@ -814,7 +854,9 @@ Usage example::
|
||||
>>> vector.x_acos, vector.y_acos
|
||||
(1.0471975511965979, 2.6905658417935308)
|
||||
|
||||
It can also be registered as a transform. For example::
|
||||
It can also be registered as a transform. For example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.db.models import FloatField
|
||||
>>> from django.db.models.functions import ACos
|
||||
@ -830,7 +872,9 @@ It can also be registered as a transform. For example::
|
||||
Returns the arcsine of a numeric field or expression. The expression value must
|
||||
be in the range -1 to 1.
|
||||
|
||||
Usage example::
|
||||
Usage example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.db.models.functions import ASin
|
||||
>>> Vector.objects.create(x=0, y=1)
|
||||
@ -838,7 +882,9 @@ Usage example::
|
||||
>>> vector.x_asin, vector.y_asin
|
||||
(0.0, 1.5707963267948966)
|
||||
|
||||
It can also be registered as a transform. For example::
|
||||
It can also be registered as a transform. For example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.db.models import FloatField
|
||||
>>> from django.db.models.functions import ASin
|
||||
@ -853,7 +899,9 @@ It can also be registered as a transform. For example::
|
||||
|
||||
Returns the arctangent of a numeric field or expression.
|
||||
|
||||
Usage example::
|
||||
Usage example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.db.models.functions import ATan
|
||||
>>> Vector.objects.create(x=3.12, y=6.987)
|
||||
@ -861,7 +909,9 @@ Usage example::
|
||||
>>> vector.x_atan, vector.y_atan
|
||||
(1.2606282660069106, 1.428638798133829)
|
||||
|
||||
It can also be registered as a transform. For example::
|
||||
It can also be registered as a transform. For example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.db.models import FloatField
|
||||
>>> from django.db.models.functions import ATan
|
||||
@ -876,7 +926,9 @@ It can also be registered as a transform. For example::
|
||||
|
||||
Returns the arctangent of ``expression1 / expression2``.
|
||||
|
||||
Usage example::
|
||||
Usage example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.db.models.functions import ATan2
|
||||
>>> Vector.objects.create(x=2.5, y=1.9)
|
||||
@ -892,7 +944,9 @@ Usage example::
|
||||
Returns the smallest integer greater than or equal to a numeric field or
|
||||
expression.
|
||||
|
||||
Usage example::
|
||||
Usage example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.db.models.functions import Ceil
|
||||
>>> Vector.objects.create(x=3.12, y=7.0)
|
||||
@ -900,7 +954,9 @@ Usage example::
|
||||
>>> vector.x_ceil, vector.y_ceil
|
||||
(4.0, 7.0)
|
||||
|
||||
It can also be registered as a transform. For example::
|
||||
It can also be registered as a transform. For example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.db.models import FloatField
|
||||
>>> from django.db.models.functions import Ceil
|
||||
@ -915,7 +971,9 @@ It can also be registered as a transform. For example::
|
||||
|
||||
Returns the cosine of a numeric field or expression.
|
||||
|
||||
Usage example::
|
||||
Usage example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.db.models.functions import Cos
|
||||
>>> Vector.objects.create(x=-8.0, y=3.1415926)
|
||||
@ -923,7 +981,9 @@ Usage example::
|
||||
>>> vector.x_cos, vector.y_cos
|
||||
(-0.14550003380861354, -0.9999999999999986)
|
||||
|
||||
It can also be registered as a transform. For example::
|
||||
It can also be registered as a transform. For example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.db.models import FloatField
|
||||
>>> from django.db.models.functions import Cos
|
||||
@ -938,7 +998,9 @@ It can also be registered as a transform. For example::
|
||||
|
||||
Returns the cotangent of a numeric field or expression.
|
||||
|
||||
Usage example::
|
||||
Usage example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.db.models.functions import Cot
|
||||
>>> Vector.objects.create(x=12.0, y=1.0)
|
||||
@ -946,7 +1008,9 @@ Usage example::
|
||||
>>> vector.x_cot, vector.y_cot
|
||||
(-1.5726734063976826, 0.642092615934331)
|
||||
|
||||
It can also be registered as a transform. For example::
|
||||
It can also be registered as a transform. For example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.db.models import FloatField
|
||||
>>> from django.db.models.functions import Cot
|
||||
@ -961,7 +1025,9 @@ It can also be registered as a transform. For example::
|
||||
|
||||
Converts a numeric field or expression from radians to degrees.
|
||||
|
||||
Usage example::
|
||||
Usage example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.db.models.functions import Degrees
|
||||
>>> Vector.objects.create(x=-1.57, y=3.14)
|
||||
@ -969,7 +1035,9 @@ Usage example::
|
||||
>>> vector.x_d, vector.y_d
|
||||
(-89.95437383553924, 179.9087476710785)
|
||||
|
||||
It can also be registered as a transform. For example::
|
||||
It can also be registered as a transform. For example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.db.models import FloatField
|
||||
>>> from django.db.models.functions import Degrees
|
||||
@ -985,7 +1053,9 @@ It can also be registered as a transform. For example::
|
||||
Returns the value of ``e`` (the natural logarithm base) raised to the power of
|
||||
a numeric field or expression.
|
||||
|
||||
Usage example::
|
||||
Usage example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.db.models.functions import Exp
|
||||
>>> Vector.objects.create(x=5.4, y=-2.0)
|
||||
@ -993,7 +1063,9 @@ Usage example::
|
||||
>>> vector.x_exp, vector.y_exp
|
||||
(221.40641620418717, 0.1353352832366127)
|
||||
|
||||
It can also be registered as a transform. For example::
|
||||
It can also be registered as a transform. For example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.db.models import FloatField
|
||||
>>> from django.db.models.functions import Exp
|
||||
@ -1009,7 +1081,9 @@ It can also be registered as a transform. For example::
|
||||
Returns the largest integer value not greater than a numeric field or
|
||||
expression.
|
||||
|
||||
Usage example::
|
||||
Usage example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.db.models.functions import Floor
|
||||
>>> Vector.objects.create(x=5.4, y=-2.3)
|
||||
@ -1017,7 +1091,9 @@ Usage example::
|
||||
>>> vector.x_floor, vector.y_floor
|
||||
(5.0, -3.0)
|
||||
|
||||
It can also be registered as a transform. For example::
|
||||
It can also be registered as a transform. For example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.db.models import FloatField
|
||||
>>> from django.db.models.functions import Floor
|
||||
@ -1032,7 +1108,9 @@ It can also be registered as a transform. For example::
|
||||
|
||||
Returns the natural logarithm a numeric field or expression.
|
||||
|
||||
Usage example::
|
||||
Usage example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.db.models.functions import Ln
|
||||
>>> Vector.objects.create(x=5.4, y=233.0)
|
||||
@ -1040,7 +1118,9 @@ Usage example::
|
||||
>>> vector.x_ln, vector.y_ln
|
||||
(1.6863989535702288, 5.4510384535657)
|
||||
|
||||
It can also be registered as a transform. For example::
|
||||
It can also be registered as a transform. For example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.db.models import FloatField
|
||||
>>> from django.db.models.functions import Ln
|
||||
@ -1056,7 +1136,9 @@ It can also be registered as a transform. For example::
|
||||
Accepts two numeric fields or expressions and returns the logarithm of
|
||||
the first to base of the second.
|
||||
|
||||
Usage example::
|
||||
Usage example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.db.models.functions import Log
|
||||
>>> Vector.objects.create(x=2.0, y=4.0)
|
||||
@ -1072,7 +1154,9 @@ Usage example::
|
||||
Accepts two numeric fields or expressions and returns the remainder of
|
||||
the first divided by the second (modulo operation).
|
||||
|
||||
Usage example::
|
||||
Usage example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.db.models.functions import Mod
|
||||
>>> Vector.objects.create(x=5.4, y=2.3)
|
||||
@ -1095,7 +1179,9 @@ Returns the value of the mathematical constant ``π``.
|
||||
Accepts two numeric fields or expressions and returns the value of the first
|
||||
raised to the power of the second.
|
||||
|
||||
Usage example::
|
||||
Usage example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.db.models.functions import Power
|
||||
>>> Vector.objects.create(x=2, y=-2)
|
||||
@ -1110,7 +1196,9 @@ Usage example::
|
||||
|
||||
Converts a numeric field or expression from degrees to radians.
|
||||
|
||||
Usage example::
|
||||
Usage example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.db.models.functions import Radians
|
||||
>>> Vector.objects.create(x=-90, y=180)
|
||||
@ -1118,7 +1206,9 @@ Usage example::
|
||||
>>> vector.x_r, vector.y_r
|
||||
(-1.5707963267948966, 3.141592653589793)
|
||||
|
||||
It can also be registered as a transform. For example::
|
||||
It can also be registered as a transform. For example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.db.models import FloatField
|
||||
>>> from django.db.models.functions import Radians
|
||||
@ -1142,7 +1232,9 @@ Rounds a numeric field or expression to ``precision`` (must be an integer)
|
||||
decimal places. By default, it rounds to the nearest integer. Whether half
|
||||
values are rounded up or down depends on the database.
|
||||
|
||||
Usage example::
|
||||
Usage example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.db.models.functions import Round
|
||||
>>> Vector.objects.create(x=5.4, y=-2.37)
|
||||
@ -1150,7 +1242,9 @@ Usage example::
|
||||
>>> vector.x_r, vector.y_r
|
||||
(5.0, -2.4)
|
||||
|
||||
It can also be registered as a transform. For example::
|
||||
It can also be registered as a transform. For example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.db.models import FloatField
|
||||
>>> from django.db.models.functions import Round
|
||||
@ -1165,7 +1259,9 @@ It can also be registered as a transform. For example::
|
||||
|
||||
Returns the sign (-1, 0, 1) of a numeric field or expression.
|
||||
|
||||
Usage example::
|
||||
Usage example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.db.models.functions import Sign
|
||||
>>> Vector.objects.create(x=5.4, y=-2.3)
|
||||
@ -1173,7 +1269,9 @@ Usage example::
|
||||
>>> vector.x_sign, vector.y_sign
|
||||
(1, -1)
|
||||
|
||||
It can also be registered as a transform. For example::
|
||||
It can also be registered as a transform. For example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.db.models import FloatField
|
||||
>>> from django.db.models.functions import Sign
|
||||
@ -1188,7 +1286,9 @@ It can also be registered as a transform. For example::
|
||||
|
||||
Returns the sine of a numeric field or expression.
|
||||
|
||||
Usage example::
|
||||
Usage example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.db.models.functions import Sin
|
||||
>>> Vector.objects.create(x=5.4, y=-2.3)
|
||||
@ -1196,7 +1296,9 @@ Usage example::
|
||||
>>> vector.x_sin, vector.y_sin
|
||||
(-0.7727644875559871, -0.7457052121767203)
|
||||
|
||||
It can also be registered as a transform. For example::
|
||||
It can also be registered as a transform. For example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.db.models import FloatField
|
||||
>>> from django.db.models.functions import Sin
|
||||
@ -1211,7 +1313,9 @@ It can also be registered as a transform. For example::
|
||||
|
||||
Returns the square root of a nonnegative numeric field or expression.
|
||||
|
||||
Usage example::
|
||||
Usage example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.db.models.functions import Sqrt
|
||||
>>> Vector.objects.create(x=4.0, y=12.0)
|
||||
@ -1219,7 +1323,9 @@ Usage example::
|
||||
>>> vector.x_sqrt, vector.y_sqrt
|
||||
(2.0, 3.46410)
|
||||
|
||||
It can also be registered as a transform. For example::
|
||||
It can also be registered as a transform. For example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.db.models import FloatField
|
||||
>>> from django.db.models.functions import Sqrt
|
||||
@ -1234,7 +1340,9 @@ It can also be registered as a transform. For example::
|
||||
|
||||
Returns the tangent of a numeric field or expression.
|
||||
|
||||
Usage example::
|
||||
Usage example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.db.models.functions import Tan
|
||||
>>> Vector.objects.create(x=0, y=12)
|
||||
@ -1242,7 +1350,9 @@ Usage example::
|
||||
>>> vector.x_tan, vector.y_tan
|
||||
(0.0, -0.6358599286615808)
|
||||
|
||||
It can also be registered as a transform. For example::
|
||||
It can also be registered as a transform. For example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.db.models import FloatField
|
||||
>>> from django.db.models.functions import Tan
|
||||
@ -1267,7 +1377,9 @@ function.
|
||||
Like :class:`Length`, it can be registered as a transform on ``IntegerField``.
|
||||
The default lookup name is ``chr``.
|
||||
|
||||
Usage example::
|
||||
Usage example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.db.models.functions import Chr
|
||||
>>> Author.objects.create(name='Margaret Smith')
|
||||
@ -1291,7 +1403,9 @@ This function will never have a null result. On backends where a null argument
|
||||
results in the entire expression being null, Django will ensure that each null
|
||||
part is converted to an empty string first.
|
||||
|
||||
Usage example::
|
||||
Usage example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> # Get the display name as "name (goes_by)"
|
||||
>>> from django.db.models import CharField, Value as V
|
||||
@ -1313,7 +1427,9 @@ Usage example::
|
||||
|
||||
Returns the first ``length`` characters of the given text field or expression.
|
||||
|
||||
Usage example::
|
||||
Usage example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.db.models.functions import Left
|
||||
>>> Author.objects.create(name='Margaret Smith')
|
||||
@ -1329,7 +1445,9 @@ Usage example::
|
||||
Accepts a single text field or expression and returns the number of characters
|
||||
the value has. If the expression is null, then the length will also be null.
|
||||
|
||||
Usage example::
|
||||
Usage example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> # Get the length of the name and goes_by fields
|
||||
>>> from django.db.models.functions import Length
|
||||
@ -1340,7 +1458,9 @@ Usage example::
|
||||
>>> print(author.name_length, author.goes_by_length)
|
||||
(14, None)
|
||||
|
||||
It can also be registered as a transform. For example::
|
||||
It can also be registered as a transform. For example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.db.models import CharField
|
||||
>>> from django.db.models.functions import Length
|
||||
@ -1358,7 +1478,9 @@ representation.
|
||||
|
||||
It can also be registered as a transform as described in :class:`Length`.
|
||||
|
||||
Usage example::
|
||||
Usage example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.db.models.functions import Lower
|
||||
>>> Author.objects.create(name='Margaret Smith')
|
||||
@ -1375,7 +1497,9 @@ Returns the value of the given text field or expression padded on the left side
|
||||
with ``fill_text`` so that the resulting value is ``length`` characters long.
|
||||
The default ``fill_text`` is a space.
|
||||
|
||||
Usage example::
|
||||
Usage example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.db.models import Value
|
||||
>>> from django.db.models.functions import LPad
|
||||
@ -1403,7 +1527,9 @@ string.
|
||||
|
||||
It can also be registered as a transform as described in :class:`Length`.
|
||||
|
||||
Usage example::
|
||||
Usage example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.db.models.functions import MD5
|
||||
>>> Author.objects.create(name='Margaret Smith')
|
||||
@ -1424,7 +1550,9 @@ than one character long.
|
||||
It can also be registered as a transform as described in :class:`Length`.
|
||||
The default lookup name is ``ord``.
|
||||
|
||||
Usage example::
|
||||
Usage example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.db.models.functions import Ord
|
||||
>>> Author.objects.create(name='Margaret Smith')
|
||||
@ -1440,7 +1568,9 @@ Usage example::
|
||||
Returns the value of the given text field or expression repeated ``number``
|
||||
times.
|
||||
|
||||
Usage example::
|
||||
Usage example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.db.models.functions import Repeat
|
||||
>>> Author.objects.create(name='John', alias='j')
|
||||
@ -1458,7 +1588,9 @@ Replaces all occurrences of ``text`` with ``replacement`` in ``expression``.
|
||||
The default replacement text is the empty string. The arguments to the function
|
||||
are case-sensitive.
|
||||
|
||||
Usage example::
|
||||
Usage example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.db.models import Value
|
||||
>>> from django.db.models.functions import Replace
|
||||
@ -1480,7 +1612,9 @@ expression in reverse order.
|
||||
It can also be registered as a transform as described in :class:`Length`. The
|
||||
default lookup name is ``reverse``.
|
||||
|
||||
Usage example::
|
||||
Usage example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.db.models.functions import Reverse
|
||||
>>> Author.objects.create(name='Margaret Smith')
|
||||
@ -1495,7 +1629,9 @@ Usage example::
|
||||
|
||||
Returns the last ``length`` characters of the given text field or expression.
|
||||
|
||||
Usage example::
|
||||
Usage example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.db.models.functions import Right
|
||||
>>> Author.objects.create(name='Margaret Smith')
|
||||
@ -1533,7 +1669,9 @@ the string.
|
||||
|
||||
They can also be registered as transforms as described in :class:`Length`.
|
||||
|
||||
Usage example::
|
||||
Usage example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.db.models.functions import SHA1
|
||||
>>> Author.objects.create(name='Margaret Smith')
|
||||
@ -1561,7 +1699,9 @@ Returns a positive integer corresponding to the 1-indexed position of the first
|
||||
occurrence of ``substring`` inside ``string``, or 0 if ``substring`` is not
|
||||
found.
|
||||
|
||||
Usage example::
|
||||
Usage example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.db.models import Value as V
|
||||
>>> from django.db.models.functions import StrIndex
|
||||
@ -1593,7 +1733,9 @@ Returns a substring of length ``length`` from the field or expression starting
|
||||
at position ``pos``. The position is 1-indexed, so the position must be greater
|
||||
than 0. If ``length`` is ``None``, then the rest of the string will be returned.
|
||||
|
||||
Usage example::
|
||||
Usage example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> # Set the alias to the first 5 characters of the name as lowercase
|
||||
>>> from django.db.models.functions import Lower, Substr
|
||||
@ -1611,7 +1753,9 @@ Usage example::
|
||||
Returns the value of the given text field or expression with leading and
|
||||
trailing spaces removed.
|
||||
|
||||
Usage example::
|
||||
Usage example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.db.models.functions import Trim
|
||||
>>> Author.objects.create(name=' John ', alias='j')
|
||||
@ -1630,7 +1774,9 @@ representation.
|
||||
|
||||
It can also be registered as a transform as described in :class:`Length`.
|
||||
|
||||
Usage example::
|
||||
Usage example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.db.models.functions import Upper
|
||||
>>> Author.objects.create(name='Margaret Smith')
|
||||
|
@ -232,7 +232,9 @@ directly support ``output_field`` you will need to wrap the expression with
|
||||
F('active_at') + F('duration'), output_field=DateTimeField()))
|
||||
|
||||
When referencing relational fields such as ``ForeignKey``, ``F()`` returns the
|
||||
primary key value rather than a model instance::
|
||||
primary key value rather than a model instance:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>> car = Company.objects.annotate(built_by=F('manufacturer'))[0]
|
||||
>> car.manufacturer
|
||||
@ -547,7 +549,9 @@ You can add an explicit subquery to a ``QuerySet`` using the ``Subquery``
|
||||
expression.
|
||||
|
||||
For example, to annotate each post with the email address of the author of the
|
||||
newest comment on that post::
|
||||
newest comment on that post:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.db.models import OuterRef, Subquery
|
||||
>>> newest = Comment.objects.filter(post=OuterRef('pk')).order_by('-created_at')
|
||||
@ -584,7 +588,9 @@ outer queryset is resolved.
|
||||
Instances of ``OuterRef`` may be used in conjunction with nested instances
|
||||
of ``Subquery`` to refer to a containing queryset that isn't the immediate
|
||||
parent. For example, this queryset would need to be within a nested pair of
|
||||
``Subquery`` instances to resolve correctly::
|
||||
``Subquery`` instances to resolve correctly:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Book.objects.filter(author=OuterRef(OuterRef('pk')))
|
||||
|
||||
@ -593,7 +599,9 @@ Limiting a subquery to a single column
|
||||
|
||||
There are times when a single column must be returned from a ``Subquery``, for
|
||||
instance, to use a ``Subquery`` as the target of an ``__in`` lookup. To return
|
||||
all comments for posts published within the last day::
|
||||
all comments for posts published within the last day:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from datetime import timedelta
|
||||
>>> from django.utils import timezone
|
||||
@ -608,7 +616,9 @@ Limiting the subquery to a single row
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
To prevent a subquery from returning multiple rows, a slice (``[:1]``) of the
|
||||
queryset is used::
|
||||
queryset is used:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> subquery = Subquery(newest.values('email')[:1])
|
||||
>>> Post.objects.annotate(newest_commenter_email=subquery)
|
||||
@ -630,7 +640,9 @@ many cases it will perform better than a subquery since the database is able to
|
||||
stop evaluation of the subquery when a first matching row is found.
|
||||
|
||||
For example, to annotate each post with whether or not it has a comment from
|
||||
within the last day::
|
||||
within the last day:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.db.models import Exists, OuterRef
|
||||
>>> from datetime import timedelta
|
||||
@ -668,7 +680,9 @@ Filtering on a ``Subquery()`` or ``Exists()`` expressions
|
||||
|
||||
``Subquery()`` that returns a boolean value and ``Exists()`` may be used as a
|
||||
``condition`` in :class:`~django.db.models.expressions.When` expressions, or to
|
||||
directly filter a queryset::
|
||||
directly filter a queryset:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> recent_comments = Comment.objects.filter(...) # From above
|
||||
>>> Post.objects.filter(Exists(recent_comments))
|
||||
@ -684,7 +698,9 @@ combination of :meth:`~.QuerySet.filter`, :meth:`~.QuerySet.values`, and
|
||||
:meth:`~.QuerySet.annotate` to get the subquery grouping correct.
|
||||
|
||||
Assuming both models have a ``length`` field, to find posts where the post
|
||||
length is greater than the total length of all combined comments::
|
||||
length is greater than the total length of all combined comments:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.db.models import OuterRef, Subquery, Sum
|
||||
>>> comments = Comment.objects.filter(post=OuterRef('pk')).order_by().values('post')
|
||||
@ -710,7 +726,9 @@ Raw SQL expressions
|
||||
.. class:: RawSQL(sql, params, output_field=None)
|
||||
|
||||
Sometimes database expressions can't easily express a complex ``WHERE`` clause.
|
||||
In these edge cases, use the ``RawSQL`` expression. For example::
|
||||
In these edge cases, use the ``RawSQL`` expression. For example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.db.models.expressions import RawSQL
|
||||
>>> queryset.annotate(val=RawSQL("select col from sometable where othercol = %s", (param,)))
|
||||
@ -719,7 +737,9 @@ These extra lookups may not be portable to different database engines (because
|
||||
you're explicitly writing SQL code) and violate the DRY principle, so you
|
||||
should avoid them if possible.
|
||||
|
||||
``RawSQL`` expressions can also be used as the target of ``__in`` filters::
|
||||
``RawSQL`` expressions can also be used as the target of ``__in`` filters:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> queryset.filter(id__in=RawSQL("select id from sometable where col = %s", (param,)))
|
||||
|
||||
@ -732,7 +752,9 @@ should avoid them if possible.
|
||||
your SQL with user-provided data.
|
||||
|
||||
You also must not quote placeholders in the SQL string. This example is
|
||||
vulnerable to SQL injection because of the quotes around ``%s``::
|
||||
vulnerable to SQL injection because of the quotes around ``%s``:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
RawSQL("select col from sometable where othercol = '%s'") # unsafe!
|
||||
|
||||
@ -785,7 +807,9 @@ The ``frame`` parameter specifies which other rows that should be used in the
|
||||
computation. See :ref:`window-frames` for details.
|
||||
|
||||
For example, to annotate each movie with the average rating for the movies by
|
||||
the same studio in the same genre and release year::
|
||||
the same studio in the same genre and release year:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.db.models import Avg, F, Window
|
||||
>>> Movie.objects.annotate(
|
||||
@ -803,7 +827,9 @@ same partition and frame. For example, you could modify the previous example
|
||||
to also include the best and worst rating in each movie's group (same studio,
|
||||
genre, and release year) by using three window functions in the same query. The
|
||||
partition and ordering from the previous example is extracted into a dictionary
|
||||
to reduce repetition::
|
||||
to reduce repetition:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.db.models import Avg, F, Max, Min, Window
|
||||
>>> window = {
|
||||
@ -829,7 +855,9 @@ performing aggregation.
|
||||
For example, a query that relies on aggregation and has an ``OR``-ed filter
|
||||
against a window function and a field is not supported. Applying combined
|
||||
predicates post-aggregation could cause rows that would normally be excluded
|
||||
from groups to be included::
|
||||
from groups to be included:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> qs = Movie.objects.annotate(
|
||||
>>> category_rank=Window(
|
||||
@ -878,7 +906,9 @@ ordinary sequence of rows.
|
||||
|
||||
This attribute is set to ``'ROWS'``.
|
||||
|
||||
Both classes return SQL with the template::
|
||||
Both classes return SQL with the template:
|
||||
|
||||
.. code-block:: sql
|
||||
|
||||
%(frame_type)s BETWEEN %(start)s AND %(end)s
|
||||
|
||||
@ -909,7 +939,9 @@ includes both the ``start`` and ``end`` points, this may be expressed with::
|
||||
|
||||
If a movie's "peers" are described as movies released by the same studio in the
|
||||
same genre in the same year, this ``RowRange`` example annotates each movie
|
||||
with the average rating of a movie's two prior and two following peers::
|
||||
with the average rating of a movie's two prior and two following peers:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.db.models import Avg, F, RowRange, Window
|
||||
>>> Movie.objects.annotate(
|
||||
@ -925,7 +957,9 @@ If the database supports it, you can specify the start and end points based on
|
||||
values of an expression in the partition. If the ``released`` field of the
|
||||
``Movie`` model stores the release month of each movies, this ``ValueRange``
|
||||
example annotates each movie with the average rating of a movie's peers
|
||||
released between twelve months before and twelve months after the each movie::
|
||||
released between twelve months before and twelve months after the each movie:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.db.models import Avg, F, ValueRange, Window
|
||||
>>> Movie.objects.annotate(
|
||||
@ -1012,7 +1046,9 @@ calling the appropriate methods on the wrapped expression.
|
||||
|
||||
.. method:: get_source_expressions()
|
||||
|
||||
Returns an ordered list of inner expressions. For example::
|
||||
Returns an ordered list of inner expressions. For example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Sum(F('foo')).get_source_expressions()
|
||||
[F('foo')]
|
||||
@ -1170,7 +1206,9 @@ to play nice with other query expressions::
|
||||
def set_source_expressions(self, expressions):
|
||||
self.expressions = expressions
|
||||
|
||||
Let's see how it works::
|
||||
Let's see how it works:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.db.models import F, Value, CharField
|
||||
>>> qs = Company.objects.annotate(
|
||||
|
@ -249,7 +249,9 @@ the ``.name`` and ``.value`` properties on the members.
|
||||
|
||||
If you don't need to have the human-readable names translated, you can have
|
||||
them inferred from the member name (replacing underscores with spaces and using
|
||||
title-case)::
|
||||
title-case):
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> class Vehicle(models.TextChoices):
|
||||
... CAR = 'C'
|
||||
@ -274,7 +276,9 @@ Django provides an ``IntegerChoices`` class. For example::
|
||||
|
||||
It is also possible to make use of the `Enum Functional API
|
||||
<https://docs.python.org/3/library/enum.html#functional-api>`_ with the caveat
|
||||
that labels are automatically generated as highlighted above::
|
||||
that labels are automatically generated as highlighted above:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> MedalType = models.TextChoices('MedalType', 'GOLD SILVER BRONZE')
|
||||
>>> MedalType.choices
|
||||
@ -1597,7 +1601,9 @@ The possible values for :attr:`~ForeignKey.on_delete` are found in
|
||||
|
||||
``Artist`` can be deleted even if that implies deleting an ``Album``
|
||||
which is referenced by a ``Song``, because ``Song`` also references
|
||||
``Artist`` itself through a cascading relationship. For example::
|
||||
``Artist`` itself through a cascading relationship. For example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> artist_one = Artist.objects.create(name='artist one')
|
||||
>>> artist_two = Artist.objects.create(name='artist two')
|
||||
@ -2025,7 +2031,9 @@ With the following example::
|
||||
related_name='supervisor_of',
|
||||
)
|
||||
|
||||
your resulting ``User`` model will have the following attributes::
|
||||
your resulting ``User`` model will have the following attributes:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> user = User.objects.get(pk=1)
|
||||
>>> hasattr(user, 'myspecialuser')
|
||||
|
@ -125,7 +125,9 @@ Refreshing objects from database
|
||||
================================
|
||||
|
||||
If you delete a field from a model instance, accessing it again reloads the
|
||||
value from the database::
|
||||
value from the database:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> obj = MyModel.objects.first()
|
||||
>>> del obj.field
|
||||
@ -415,7 +417,9 @@ Auto-incrementing primary keys
|
||||
|
||||
If a model has an :class:`~django.db.models.AutoField` — an auto-incrementing
|
||||
primary key — then that auto-incremented value will be calculated and saved as
|
||||
an attribute on your object the first time you call ``save()``::
|
||||
an attribute on your object the first time you call ``save()``:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> b2 = Blog(name='Cheddar Talk', tagline='Thoughts on cheese.')
|
||||
>>> b2.id # Returns None, because b2 doesn't have an ID yet.
|
||||
@ -447,7 +451,9 @@ Explicitly specifying auto-primary-key values
|
||||
|
||||
If a model has an :class:`~django.db.models.AutoField` but you want to define a
|
||||
new object's ID explicitly when saving, define it explicitly before saving,
|
||||
rather than relying on the auto-assignment of the ID::
|
||||
rather than relying on the auto-assignment of the ID:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> b3 = Blog(id=3, name='Cheddar Talk', tagline='Thoughts on cheese.')
|
||||
>>> b3.id # Returns 3.
|
||||
@ -573,7 +579,9 @@ Updating attributes based on existing fields
|
||||
|
||||
Sometimes you'll need to perform a simple arithmetic task on a field, such
|
||||
as incrementing or decrementing the current value. One way of achieving this is
|
||||
doing the arithmetic in Python like::
|
||||
doing the arithmetic in Python like:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> product = Product.objects.get(name='Venezuelan Beaver Cheese')
|
||||
>>> product.number_sold += 1
|
||||
@ -588,7 +596,9 @@ the update relative to the original field value, rather than as an explicit
|
||||
assignment of a new value. Django provides :class:`F expressions
|
||||
<django.db.models.F>` for performing this kind of relative update. Using
|
||||
:class:`F expressions <django.db.models.F>`, the previous example is expressed
|
||||
as::
|
||||
as:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.db.models import F
|
||||
>>> product = Product.objects.get(name='Venezuelan Beaver Cheese')
|
||||
@ -862,7 +872,7 @@ For example::
|
||||
name = models.CharField(max_length=60)
|
||||
shirt_size = models.CharField(max_length=2, choices=SHIRT_SIZES)
|
||||
|
||||
::
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> p = Person(name="Fred Flintstone", shirt_size="L")
|
||||
>>> p.save()
|
||||
|
@ -234,20 +234,26 @@ not be looking at your Django code. For example::
|
||||
and ``set_RELATED_order()``, where ``RELATED`` is the lowercased model name. For
|
||||
example, assuming that a ``Question`` object has multiple related ``Answer``
|
||||
objects, the list returned contains the primary keys of the related ``Answer``
|
||||
objects::
|
||||
objects:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> question = Question.objects.get(id=1)
|
||||
>>> question.get_answer_order()
|
||||
[1, 2, 3]
|
||||
|
||||
The order of a ``Question`` object's related ``Answer`` objects can be set by
|
||||
passing in a list of ``Answer`` primary keys::
|
||||
passing in a list of ``Answer`` primary keys:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> question.set_answer_order([3, 1, 2])
|
||||
|
||||
The related objects also get two methods, ``get_next_in_order()`` and
|
||||
``get_previous_in_order()``, which can be used to access those objects in their
|
||||
proper order. Assuming the ``Answer`` objects are ordered by ``id``::
|
||||
proper order. Assuming the ``Answer`` objects are ordered by ``id``:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> answer = Answer.objects.get(id=2)
|
||||
>>> answer.get_next_in_order()
|
||||
|
@ -103,7 +103,9 @@ than the results that are currently in the database.
|
||||
If you only want to pickle the necessary information to recreate the
|
||||
``QuerySet`` from the database at a later time, pickle the ``query`` attribute
|
||||
of the ``QuerySet``. You can then recreate the original ``QuerySet`` (without
|
||||
any results loaded) using some code like this::
|
||||
any results loaded) using some code like this:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> import pickle
|
||||
>>> query = pickle.loads(s) # Assuming 's' is the pickled string.
|
||||
@ -118,7 +120,9 @@ described here.
|
||||
.. admonition:: Restrictions on ``QuerySet.values_list()``
|
||||
|
||||
If you recreate :meth:`QuerySet.values_list` using the pickled ``query``
|
||||
attribute, it will be converted to :meth:`QuerySet.values`::
|
||||
attribute, it will be converted to :meth:`QuerySet.values`:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> import pickle
|
||||
>>> qs = Blog.objects.values_list('id', 'name')
|
||||
@ -273,7 +277,9 @@ that reference a single field can be anonymous arguments. Everything
|
||||
else must be a keyword argument.
|
||||
|
||||
For example, if you were manipulating a list of blogs, you may want
|
||||
to determine how many entries have been made in each blog::
|
||||
to determine how many entries have been made in each blog:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.db.models import Count
|
||||
>>> q = Blog.objects.annotate(Count('entry'))
|
||||
@ -286,7 +292,9 @@ to determine how many entries have been made in each blog::
|
||||
|
||||
The ``Blog`` model doesn't define an ``entry__count`` attribute by itself,
|
||||
but by using a keyword argument to specify the aggregate function, you can
|
||||
control the name of the annotation::
|
||||
control the name of the annotation:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> q = Blog.objects.annotate(number_of_entries=Count('entry'))
|
||||
# The number of entries on the first blog, using the name provided
|
||||
@ -309,7 +317,9 @@ Not selecting the unused value removes redundant work from the database which
|
||||
should result in better performance.
|
||||
|
||||
For example, if you want to find blogs with more than 5 entries, but are not
|
||||
interested in the exact number of entries, you could do this::
|
||||
interested in the exact number of entries, you could do this:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.db.models import Count
|
||||
>>> blogs = Blog.objects.alias(entries=Count('entry')).filter(entries__gt=5)
|
||||
@ -528,7 +538,9 @@ field names, the database will only compare the specified field names.
|
||||
value in column ``a``. If you don't specify an order, you'll get some
|
||||
arbitrary row.
|
||||
|
||||
Examples (those after the first will only work on PostgreSQL)::
|
||||
Examples (those after the first will only work on PostgreSQL):
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Author.objects.distinct()
|
||||
[...]
|
||||
@ -575,7 +587,9 @@ Each of those dictionaries represents an object, with the keys corresponding to
|
||||
the attribute names of model objects.
|
||||
|
||||
This example compares the dictionaries of ``values()`` with the normal model
|
||||
objects::
|
||||
objects:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
# This list contains a Blog object.
|
||||
>>> Blog.objects.filter(name__startswith='Beatles')
|
||||
@ -591,7 +605,9 @@ the fields, each dictionary will contain only the field keys/values for the
|
||||
fields you specify. If you don't specify the fields, each dictionary will
|
||||
contain a key and value for every field in the database table.
|
||||
|
||||
Example::
|
||||
Example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Blog.objects.values()
|
||||
<QuerySet [{'id': 1, 'name': 'Beatles Blog', 'tagline': 'All the latest Beatles news.'}]>
|
||||
@ -599,14 +615,18 @@ Example::
|
||||
<QuerySet [{'id': 1, 'name': 'Beatles Blog'}]>
|
||||
|
||||
The ``values()`` method also takes optional keyword arguments,
|
||||
``**expressions``, which are passed through to :meth:`annotate`::
|
||||
``**expressions``, which are passed through to :meth:`annotate`:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.db.models.functions import Lower
|
||||
>>> Blog.objects.values(lower_name=Lower('name'))
|
||||
<QuerySet [{'lower_name': 'beatles blog'}]>
|
||||
|
||||
You can use built-in and :doc:`custom lookups </howto/custom-lookups>` in
|
||||
ordering. For example::
|
||||
ordering. For example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.db.models import CharField
|
||||
>>> from django.db.models.functions import Lower
|
||||
@ -616,7 +636,9 @@ ordering. For example::
|
||||
|
||||
An aggregate within a ``values()`` clause is applied before other arguments
|
||||
within the same ``values()`` clause. If you need to group by another value,
|
||||
add it to an earlier ``values()`` clause instead. For example::
|
||||
add it to an earlier ``values()`` clause instead. For example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.db.models import Count
|
||||
>>> Blog.objects.values('entry__authors', entries=Count('entry'))
|
||||
@ -635,7 +657,9 @@ A few subtleties that are worth mentioning:
|
||||
or ``foo_id`` and you will get back the same thing (the dictionary key
|
||||
will match the field name you passed in).
|
||||
|
||||
For example::
|
||||
For example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Entry.objects.values()
|
||||
<QuerySet [{'blog_id': 1, 'headline': 'First Entry', ...}, ...]>
|
||||
@ -662,7 +686,9 @@ A few subtleties that are worth mentioning:
|
||||
* Combining transforms and aggregates requires the use of two :meth:`annotate`
|
||||
calls, either explicitly or as keyword arguments to :meth:`values`. As above,
|
||||
if the transform has been registered on the relevant field type the first
|
||||
:meth:`annotate` can be omitted, thus the following examples are equivalent::
|
||||
:meth:`annotate` can be omitted, thus the following examples are equivalent:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.db.models import CharField, Count
|
||||
>>> from django.db.models.functions import Lower
|
||||
@ -694,7 +720,9 @@ but it doesn't really matter. This is your chance to really flaunt your
|
||||
individualism.
|
||||
|
||||
You can also refer to fields on related models with reverse relations through
|
||||
``OneToOneField``, ``ForeignKey`` and ``ManyToManyField`` attributes::
|
||||
``OneToOneField``, ``ForeignKey`` and ``ManyToManyField`` attributes:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Blog.objects.values('name', 'entry__headline')
|
||||
<QuerySet [{'name': 'My blog', 'entry__headline': 'An entry'},
|
||||
@ -724,7 +752,9 @@ You can also refer to fields on related models with reverse relations through
|
||||
This is similar to ``values()`` except that instead of returning dictionaries,
|
||||
it returns tuples when iterated over. Each tuple contains the value from the
|
||||
respective field or expression passed into the ``values_list()`` call — so the
|
||||
first item is the first field, etc. For example::
|
||||
first item is the first field, etc. For example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Entry.objects.values_list('id', 'headline')
|
||||
<QuerySet [(1, 'First entry'), ...]>
|
||||
@ -734,7 +764,9 @@ first item is the first field, etc. For example::
|
||||
|
||||
If you only pass in a single field, you can also pass in the ``flat``
|
||||
parameter. If ``True``, this will mean the returned results are single values,
|
||||
rather than one-tuples. An example should make the difference clearer::
|
||||
rather than one-tuples. An example should make the difference clearer:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Entry.objects.values_list('id').order_by('id')
|
||||
<QuerySet[(1,), (2,), (3,), ...]>
|
||||
@ -745,7 +777,9 @@ rather than one-tuples. An example should make the difference clearer::
|
||||
It is an error to pass in ``flat`` when there is more than one field.
|
||||
|
||||
You can pass ``named=True`` to get results as a
|
||||
:func:`~python:collections.namedtuple`::
|
||||
:func:`~python:collections.namedtuple`:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Entry.objects.values_list('id', 'headline', named=True)
|
||||
<QuerySet [Row(id=1, headline='First entry'), ...]>
|
||||
@ -757,7 +791,9 @@ If you don't pass any values to ``values_list()``, it will return all the
|
||||
fields in the model, in the order they were declared.
|
||||
|
||||
A common need is to get a specific field value of a certain model instance. To
|
||||
achieve that, use ``values_list()`` followed by a ``get()`` call::
|
||||
achieve that, use ``values_list()`` followed by a ``get()`` call:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Entry.objects.values_list('headline', flat=True).get(pk=1)
|
||||
'First entry'
|
||||
@ -769,7 +805,9 @@ other multivalued relations (such as the one-to-many relation of a reverse
|
||||
foreign key) because the "one row, one object" assumption doesn't hold.
|
||||
|
||||
For example, notice the behavior when querying across a
|
||||
:class:`~django.db.models.ManyToManyField`::
|
||||
:class:`~django.db.models.ManyToManyField`:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Author.objects.values_list('name', 'entry__headline')
|
||||
<QuerySet [('Noam Chomsky', 'Impressions of Gaza'),
|
||||
@ -781,7 +819,9 @@ Authors with multiple entries appear multiple times and authors without any
|
||||
entries have ``None`` for the entry headline.
|
||||
|
||||
Similarly, when querying a reverse foreign key, ``None`` appears for entries
|
||||
not having any author::
|
||||
not having any author:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Entry.objects.values_list('authors')
|
||||
<QuerySet [('Noam Chomsky',), ('George Orwell',), (None,)]>
|
||||
@ -819,7 +859,9 @@ given ``type``.
|
||||
``order``, which defaults to ``'ASC'``, should be either ``'ASC'`` or
|
||||
``'DESC'``. This specifies how to order the results.
|
||||
|
||||
Examples::
|
||||
Examples:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Entry.objects.dates('pub_date', 'year')
|
||||
[datetime.date(2005, 1, 1)]
|
||||
@ -887,7 +929,9 @@ Calling ``none()`` will create a queryset that never returns any objects and no
|
||||
query will be executed when accessing the results. A ``qs.none()`` queryset
|
||||
is an instance of ``EmptyQuerySet``.
|
||||
|
||||
Examples::
|
||||
Examples:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Entry.objects.none()
|
||||
<QuerySet []>
|
||||
@ -929,7 +973,9 @@ of other models. Passing different models works as long as the ``SELECT`` list
|
||||
is the same in all ``QuerySet``\s (at least the types, the names don't matter
|
||||
as long as the types are in the same order). In such cases, you must use the
|
||||
column names from the first ``QuerySet`` in ``QuerySet`` methods applied to the
|
||||
resulting ``QuerySet``. For example::
|
||||
resulting ``QuerySet``. For example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> qs1 = Author.objects.values_list('name')
|
||||
>>> qs2 = Entry.objects.values_list('headline')
|
||||
@ -960,7 +1006,9 @@ See :meth:`union` for some restrictions.
|
||||
.. method:: difference(*other_qs)
|
||||
|
||||
Uses SQL's ``EXCEPT`` operator to keep only elements present in the
|
||||
``QuerySet`` but not in some other ``QuerySet``\s. For example::
|
||||
``QuerySet`` but not in some other ``QuerySet``\s. For example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> qs1.difference(qs2, qs3)
|
||||
|
||||
@ -1066,7 +1114,9 @@ specified. This is not recommended in most cases as it is likely to make the
|
||||
underlying query more complex, and return more data, than is actually needed.
|
||||
|
||||
If you need to clear the list of related fields added by past calls of
|
||||
``select_related`` on a ``QuerySet``, you can pass ``None`` as a parameter::
|
||||
``select_related`` on a ``QuerySet``, you can pass ``None`` as a parameter:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> without_relations = queryset.select_related(None)
|
||||
|
||||
@ -1121,7 +1171,9 @@ For example, suppose you have these models::
|
||||
", ".join(topping.name for topping in self.toppings.all()),
|
||||
)
|
||||
|
||||
and run::
|
||||
and run:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Pizza.objects.all()
|
||||
["Hawaiian (ham, pineapple)", "Seafood (prawns, smoked salmon)"...
|
||||
@ -1191,12 +1243,16 @@ fields. Suppose we have an additional model to the example above::
|
||||
|
||||
The following are all legal:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Restaurant.objects.prefetch_related('pizzas__toppings')
|
||||
|
||||
This will prefetch all pizzas belonging to restaurants, and all toppings
|
||||
belonging to those pizzas. This will result in a total of 3 database queries -
|
||||
one for the restaurants, one for the pizzas, and one for the toppings.
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Restaurant.objects.prefetch_related('best_pizza__toppings')
|
||||
|
||||
This will fetch the best pizza and all the toppings for the best pizza for each
|
||||
@ -1204,7 +1260,9 @@ restaurant. This will be done in 3 database queries - one for the restaurants,
|
||||
one for the 'best pizzas', and one for the toppings.
|
||||
|
||||
The ``best_pizza`` relationship could also be fetched using ``select_related``
|
||||
to reduce the query count to 2::
|
||||
to reduce the query count to 2:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Restaurant.objects.select_related('best_pizza').prefetch_related('best_pizza__toppings')
|
||||
|
||||
@ -1316,7 +1374,9 @@ where prefetching with a custom ``QuerySet`` is useful:
|
||||
|
||||
When using multiple databases, ``Prefetch`` will respect your choice of
|
||||
database. If the inner query does not specify a database, it will use the
|
||||
database selected by the outer query. All of the following are valid::
|
||||
database selected by the outer query. All of the following are valid:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> # Both inner and outer queries will use the 'replica' database
|
||||
>>> Restaurant.objects.prefetch_related('pizzas__toppings').using('replica')
|
||||
@ -1384,14 +1444,18 @@ generated by a ``QuerySet``.
|
||||
that we can enhance the QuerySet API to allow removing ``extra()``. We are
|
||||
no longer improving or fixing bugs for this method.
|
||||
|
||||
For example, this use of ``extra()``::
|
||||
For example, this use of ``extra()``:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> qs.extra(
|
||||
... select={'val': "select col from sometable where othercol = %s"},
|
||||
... select_params=(someparam,),
|
||||
... )
|
||||
|
||||
is equivalent to::
|
||||
is equivalent to:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> qs.annotate(val=RawSQL("select col from sometable where othercol = %s", (someparam,)))
|
||||
|
||||
@ -1758,7 +1822,9 @@ evaluated against if you are using more than one database. The only argument
|
||||
this method takes is the alias of a database, as defined in
|
||||
:setting:`DATABASES`.
|
||||
|
||||
For example::
|
||||
For example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
# queries the database with the 'default' alias.
|
||||
>>> Entry.objects.all()
|
||||
@ -1826,7 +1892,9 @@ lock, that still allows creating rows that merely reference locked rows
|
||||
PostgreSQL documentation has more details about `row-level lock modes
|
||||
<https://www.postgresql.org/docs/current/explicit-locking.html#LOCKING-ROWS>`_.
|
||||
|
||||
You can't use ``select_for_update()`` on nullable relations::
|
||||
You can't use ``select_for_update()`` on nullable relations:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Person.objects.select_related('hometown').select_for_update()
|
||||
Traceback (most recent call last):
|
||||
@ -1834,7 +1902,9 @@ You can't use ``select_for_update()`` on nullable relations::
|
||||
django.db.utils.NotSupportedError: FOR UPDATE cannot be applied to the nullable side of an outer join
|
||||
|
||||
To avoid that restriction, you can exclude null objects if you don't care about
|
||||
them::
|
||||
them:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Person.objects.select_related('hometown').select_for_update().exclude(hometown=None)
|
||||
<QuerySet [<Person: ...)>, ...]>
|
||||
@ -2171,7 +2241,9 @@ whenever a request to a page has a side effect on your data. For more, see
|
||||
chapters = models.ManyToManyField(Chapter)
|
||||
|
||||
You can use ``get_or_create()`` through Book's chapters field, but it only
|
||||
fetches inside the context of that book::
|
||||
fetches inside the context of that book:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> book = Book.objects.create(title="Ulysses")
|
||||
>>> book.chapters.get_or_create(title="Telemachus")
|
||||
@ -2256,7 +2328,9 @@ exists in the database, an :exc:`~django.db.IntegrityError` is raised.
|
||||
|
||||
This method inserts the provided list of objects into the database in an
|
||||
efficient manner (generally only 1 query, no matter how many objects there
|
||||
are), and returns created objects as a list, in the same order as provided::
|
||||
are), and returns created objects as a list, in the same order as provided:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> objs = Entry.objects.bulk_create([
|
||||
... Entry(headline='This is a test'),
|
||||
@ -2328,7 +2402,9 @@ support it).
|
||||
|
||||
This method efficiently updates the given fields on the provided model
|
||||
instances, generally with one query, and returns the number of objects
|
||||
updated::
|
||||
updated:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> objs = [
|
||||
... Entry.objects.create(headline='Entry 1'),
|
||||
@ -2413,7 +2489,9 @@ in the queryset are returned. ``field_name`` must be a unique field or a
|
||||
distinct field (if there's only one field specified in :meth:`distinct`).
|
||||
``field_name`` defaults to the primary key.
|
||||
|
||||
Example::
|
||||
Example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Blog.objects.in_bulk([1])
|
||||
{1: <Blog: Beatles Blog>}
|
||||
@ -2642,14 +2720,18 @@ aggregated. Complex aggregates cannot use anonymous arguments and must specify
|
||||
a keyword argument as an alias.
|
||||
|
||||
For example, when you are working with blog entries, you may want to know the
|
||||
number of authors that have contributed blog entries::
|
||||
number of authors that have contributed blog entries:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.db.models import Count
|
||||
>>> q = Blog.objects.aggregate(Count('entry'))
|
||||
{'entry__count': 16}
|
||||
|
||||
By using a keyword argument to specify the aggregate function, you can
|
||||
control the name of the aggregation value that is returned::
|
||||
control the name of the aggregation value that is returned:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> q = Blog.objects.aggregate(number_of_entries=Count('entry'))
|
||||
{'number_of_entries': 16}
|
||||
@ -2736,31 +2818,41 @@ the number of rows matched (which may not be equal to the number of rows
|
||||
updated if some rows already have the new value).
|
||||
|
||||
For example, to turn comments off for all blog entries published in 2010,
|
||||
you could do this::
|
||||
you could do this:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Entry.objects.filter(pub_date__year=2010).update(comments_on=False)
|
||||
|
||||
(This assumes your ``Entry`` model has fields ``pub_date`` and ``comments_on``.)
|
||||
|
||||
You can update multiple fields — there's no limit on how many. For example,
|
||||
here we update the ``comments_on`` and ``headline`` fields::
|
||||
here we update the ``comments_on`` and ``headline`` fields:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Entry.objects.filter(pub_date__year=2010).update(comments_on=False, headline='This is old')
|
||||
|
||||
The ``update()`` method is applied instantly, and the only restriction on the
|
||||
:class:`.QuerySet` that is updated is that it can only update columns in the
|
||||
model's main table, not on related models. You can't do this, for example::
|
||||
model's main table, not on related models. You can't do this, for example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Entry.objects.update(blog__name='foo') # Won't work!
|
||||
|
||||
Filtering based on related fields is still possible, though::
|
||||
Filtering based on related fields is still possible, though:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Entry.objects.filter(blog__id=1).update(comments_on=True)
|
||||
|
||||
You cannot call ``update()`` on a :class:`.QuerySet` that has had a slice taken
|
||||
or can otherwise no longer be filtered.
|
||||
|
||||
The ``update()`` method returns the number of affected rows::
|
||||
The ``update()`` method returns the number of affected rows:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Entry.objects.filter(id=64).update(comments_on=True)
|
||||
1
|
||||
@ -2830,7 +2922,9 @@ The ``delete()`` is applied instantly. You cannot call ``delete()`` on a
|
||||
:class:`.QuerySet` that has had a slice taken or can otherwise no longer be
|
||||
filtered.
|
||||
|
||||
For example, to delete all the entries in a particular blog::
|
||||
For example, to delete all the entries in a particular blog:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> b = Blog.objects.get(pk=1)
|
||||
|
||||
@ -2841,7 +2935,9 @@ For example, to delete all the entries in a particular blog::
|
||||
By default, Django's :class:`~django.db.models.ForeignKey` emulates the SQL
|
||||
constraint ``ON DELETE CASCADE`` — in other words, any objects with foreign
|
||||
keys pointing at the objects to be deleted will be deleted along with them.
|
||||
For example::
|
||||
For example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> blogs = Blog.objects.all()
|
||||
|
||||
@ -2896,7 +2992,9 @@ database would execute the query, including any indexes or joins that would be
|
||||
used. Knowing these details may help you improve the performance of slow
|
||||
queries.
|
||||
|
||||
For example, when using PostgreSQL::
|
||||
For example, when using PostgreSQL:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> print(Blog.objects.filter(title='My Blog').explain())
|
||||
Seq Scan on blog (cost=0.00..35.50 rows=10 width=12)
|
||||
@ -2915,7 +3013,9 @@ default, which is usually text-based. PostgreSQL supports ``'TEXT'``,
|
||||
PostgreSQL's ``'TEXT'`` output and is used by default, if supported.
|
||||
|
||||
Some databases accept flags that can return more information about the query.
|
||||
Pass these flags as keyword arguments. For example, when using PostgreSQL::
|
||||
Pass these flags as keyword arguments. For example, when using PostgreSQL:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> print(Blog.objects.filter(title='My Blog').explain(verbose=True, analyze=True))
|
||||
Seq Scan on public.blog (cost=0.00..35.50 rows=10 width=12) (actual time=0.004..0.004 rows=10 loops=1)
|
||||
@ -3932,7 +4032,9 @@ in code that receives a list of model instances as opposed to a ``QuerySet``;
|
||||
for example, when fetching models from a cache or instantiating them manually.
|
||||
|
||||
Pass an iterable of model instances (must all be of the same class) and the
|
||||
lookups or :class:`Prefetch` objects you want to prefetch for. For example::
|
||||
lookups or :class:`Prefetch` objects you want to prefetch for. For example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.db.models import prefetch_related_objects
|
||||
>>> restaurants = fetch_top_restaurants_from_cache() # A list of Restaurants
|
||||
@ -3961,7 +4063,9 @@ relationship but on the annotation name (``pizzas_vegetarian`` in example
|
||||
below).
|
||||
|
||||
For example, to find restaurants that have vegetarian pizzas with
|
||||
``'mozzarella'`` in the name::
|
||||
``'mozzarella'`` in the name:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.db.models import FilteredRelation, Q
|
||||
>>> Restaurant.objects.annotate(
|
||||
@ -3970,7 +4074,9 @@ For example, to find restaurants that have vegetarian pizzas with
|
||||
... ),
|
||||
... ).filter(pizzas_vegetarian__name__icontains='mozzarella')
|
||||
|
||||
If there are a large number of pizzas, this queryset performs better than::
|
||||
If there are a large number of pizzas, this queryset performs better than:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Restaurant.objects.filter(
|
||||
... pizzas__vegetarian=True,
|
||||
|
@ -43,7 +43,9 @@ Related objects reference
|
||||
|
||||
Adds the specified model objects to the related object set.
|
||||
|
||||
Example::
|
||||
Example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> b = Blog.objects.get(id=1)
|
||||
>>> e = Entry.objects.get(id=234)
|
||||
@ -88,7 +90,9 @@ Related objects reference
|
||||
*Asynchronous version*: ``acreate``
|
||||
|
||||
Creates a new object, saves it and puts it in the related object set.
|
||||
Returns the newly created object::
|
||||
Returns the newly created object:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> b = Blog.objects.get(id=1)
|
||||
>>> e = b.entry_set.create(
|
||||
@ -99,7 +103,9 @@ Related objects reference
|
||||
|
||||
# No need to call e.save() at this point -- it's already been saved.
|
||||
|
||||
This is equivalent to (but simpler than)::
|
||||
This is equivalent to (but simpler than):
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> b = Blog.objects.get(id=1)
|
||||
>>> e = Entry(
|
||||
@ -125,7 +131,9 @@ Related objects reference
|
||||
|
||||
*Asynchronous version*: ``aremove``
|
||||
|
||||
Removes the specified model objects from the related object set::
|
||||
Removes the specified model objects from the related object set:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> b = Blog.objects.get(id=1)
|
||||
>>> e = Entry.objects.get(id=234)
|
||||
@ -172,7 +180,9 @@ Related objects reference
|
||||
|
||||
*Asynchronous version*: ``aclear``
|
||||
|
||||
Removes all objects from the related object set::
|
||||
Removes all objects from the related object set:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> b = Blog.objects.get(id=1)
|
||||
>>> b.entry_set.clear()
|
||||
@ -196,7 +206,9 @@ Related objects reference
|
||||
|
||||
*Asynchronous version*: ``aset``
|
||||
|
||||
Replace the set of related objects::
|
||||
Replace the set of related objects:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> new_list = [obj1, obj2, obj3]
|
||||
>>> e.related_set.set(new_list)
|
||||
|
@ -179,7 +179,9 @@ All attributes should be considered read-only, unless stated otherwise.
|
||||
the request.
|
||||
|
||||
The name of each header is stylized with title-casing (e.g. ``User-Agent``)
|
||||
when it's displayed. You can access headers case-insensitively::
|
||||
when it's displayed. You can access headers case-insensitively:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> request.headers
|
||||
{'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6', ...}
|
||||
@ -200,7 +202,9 @@ All attributes should be considered read-only, unless stated otherwise.
|
||||
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6)
|
||||
|
||||
For use in, for example, Django templates, headers can also be looked up
|
||||
using underscores in place of hyphens::
|
||||
using underscores in place of hyphens:
|
||||
|
||||
.. code-block:: html+django
|
||||
|
||||
{{ request.headers.user_agent }}
|
||||
|
||||
@ -381,7 +385,9 @@ Methods
|
||||
attached to the cookie value to ensure the cookie is not older than
|
||||
``max_age`` seconds.
|
||||
|
||||
For example::
|
||||
For example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> request.get_signed_cookie('name')
|
||||
'Tony'
|
||||
@ -411,7 +417,9 @@ Methods
|
||||
.. method:: HttpRequest.accepts(mime_type)
|
||||
|
||||
Returns ``True`` if the request ``Accept`` header matches the ``mime_type``
|
||||
argument::
|
||||
argument:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> request.accepts('text/html')
|
||||
True
|
||||
@ -492,7 +500,9 @@ a subclass of dictionary. Exceptions are outlined here:
|
||||
.. classmethod:: QueryDict.fromkeys(iterable, value='', mutable=False, encoding=None)
|
||||
|
||||
Creates a new ``QueryDict`` with keys from ``iterable`` and each value
|
||||
equal to ``value``. For example::
|
||||
equal to ``value``. For example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> QueryDict.fromkeys(['a', 'a', 'b'], value='val')
|
||||
<QueryDict: {'a': ['val', 'val'], 'b': ['val']}>
|
||||
@ -530,7 +540,9 @@ a subclass of dictionary. Exceptions are outlined here:
|
||||
|
||||
Takes either a ``QueryDict`` or a dictionary. Like :meth:`dict.update`,
|
||||
except it *appends* to the current dictionary items rather than replacing
|
||||
them. For example::
|
||||
them. For example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> q = QueryDict('a=1', mutable=True)
|
||||
>>> q.update({'a': '2'})
|
||||
@ -543,7 +555,9 @@ a subclass of dictionary. Exceptions are outlined here:
|
||||
|
||||
Like :meth:`dict.items`, except this uses the same last-value logic as
|
||||
:meth:`__getitem__` and returns an iterator object instead of a view object.
|
||||
For example::
|
||||
For example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> q = QueryDict('a=1&a=2&a=3')
|
||||
>>> list(q.items())
|
||||
@ -553,7 +567,9 @@ a subclass of dictionary. Exceptions are outlined here:
|
||||
|
||||
Like :meth:`dict.values`, except this uses the same last-value logic as
|
||||
:meth:`__getitem__` and returns an iterator instead of a view object. For
|
||||
example::
|
||||
example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> q = QueryDict('a=1&a=2&a=3')
|
||||
>>> list(q.values())
|
||||
@ -588,7 +604,9 @@ In addition, ``QueryDict`` has the following methods:
|
||||
.. method:: QueryDict.lists()
|
||||
|
||||
Like :meth:`items()`, except it includes all values, as a list, for each
|
||||
member of the dictionary. For example::
|
||||
member of the dictionary. For example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> q = QueryDict('a=1&a=2&a=3')
|
||||
>>> q.lists()
|
||||
@ -597,7 +615,9 @@ In addition, ``QueryDict`` has the following methods:
|
||||
.. method:: QueryDict.pop(key)
|
||||
|
||||
Returns a list of values for the given key and removes them from the
|
||||
dictionary. Raises ``KeyError`` if the key does not exist. For example::
|
||||
dictionary. Raises ``KeyError`` if the key does not exist. For example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> q = QueryDict('a=1&a=2&a=3', mutable=True)
|
||||
>>> q.pop('a')
|
||||
@ -608,7 +628,9 @@ In addition, ``QueryDict`` has the following methods:
|
||||
Removes an arbitrary member of the dictionary (since there's no concept
|
||||
of ordering), and returns a two value tuple containing the key and a list
|
||||
of all values for the key. Raises ``KeyError`` when called on an empty
|
||||
dictionary. For example::
|
||||
dictionary. For example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> q = QueryDict('a=1&a=2&a=3', mutable=True)
|
||||
>>> q.popitem()
|
||||
@ -618,7 +640,9 @@ In addition, ``QueryDict`` has the following methods:
|
||||
|
||||
Returns a ``dict`` representation of ``QueryDict``. For every (key, list)
|
||||
pair in ``QueryDict``, ``dict`` will have (key, item), where item is one
|
||||
element of the list, using the same logic as :meth:`QueryDict.__getitem__`::
|
||||
element of the list, using the same logic as :meth:`QueryDict.__getitem__`:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> q = QueryDict('a=1&a=3&a=5')
|
||||
>>> q.dict()
|
||||
@ -626,14 +650,18 @@ In addition, ``QueryDict`` has the following methods:
|
||||
|
||||
.. method:: QueryDict.urlencode(safe=None)
|
||||
|
||||
Returns a string of the data in query string format. For example::
|
||||
Returns a string of the data in query string format. For example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> q = QueryDict('a=2&b=3&b=5')
|
||||
>>> q.urlencode()
|
||||
'a=2&b=3&b=5'
|
||||
|
||||
Use the ``safe`` parameter to pass characters which don't require encoding.
|
||||
For example::
|
||||
For example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> q = QueryDict(mutable=True)
|
||||
>>> q['next'] = '/a&b/'
|
||||
@ -659,7 +687,9 @@ Passing strings
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
Typical usage is to pass the contents of the page, as a string, bytestring,
|
||||
or :class:`memoryview`, to the :class:`HttpResponse` constructor::
|
||||
or :class:`memoryview`, to the :class:`HttpResponse` constructor:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.http import HttpResponse
|
||||
>>> response = HttpResponse("Here's the text of the web page.")
|
||||
@ -668,7 +698,9 @@ or :class:`memoryview`, to the :class:`HttpResponse` constructor::
|
||||
>>> response = HttpResponse(memoryview(b'Memoryview as well.'))
|
||||
|
||||
But if you want to add content incrementally, you can use ``response`` as a
|
||||
file-like object::
|
||||
file-like object:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> response = HttpResponse()
|
||||
>>> response.write("<p>Here's the text of the web page.</p>")
|
||||
@ -691,13 +723,17 @@ Setting header fields
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
To set or remove a header field in your response, use
|
||||
:attr:`HttpResponse.headers`::
|
||||
:attr:`HttpResponse.headers`:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> response = HttpResponse()
|
||||
>>> response.headers['Age'] = 120
|
||||
>>> del response.headers['Age']
|
||||
|
||||
You can also manipulate headers by treating your response like a dictionary::
|
||||
You can also manipulate headers by treating your response like a dictionary:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> response = HttpResponse()
|
||||
>>> response['Age'] = 120
|
||||
@ -709,7 +745,9 @@ by ``HttpResponse``.
|
||||
When using this interface, unlike a dictionary, ``del`` doesn't raise
|
||||
``KeyError`` if the header field doesn't exist.
|
||||
|
||||
You can also set headers on instantiation::
|
||||
You can also set headers on instantiation:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> response = HttpResponse(headers={'Age': 120})
|
||||
|
||||
@ -728,7 +766,9 @@ Telling the browser to treat the response as a file attachment
|
||||
|
||||
To tell the browser to treat the response as a file attachment, set the
|
||||
``Content-Type`` and ``Content-Disposition`` headers. For example, this is how
|
||||
you might return a Microsoft Excel spreadsheet::
|
||||
you might return a Microsoft Excel spreadsheet:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> response = HttpResponse(my_data, headers={
|
||||
... 'Content-Type': 'application/vnd.ms-excel',
|
||||
@ -1025,7 +1065,9 @@ Custom response classes
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
If you find yourself needing a response class that Django doesn't provide, you
|
||||
can create it with the help of :py:class:`http.HTTPStatus`. For example::
|
||||
can create it with the help of :py:class:`http.HTTPStatus`. For example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
from http import HTTPStatus
|
||||
from django.http import HttpResponse
|
||||
@ -1064,7 +1106,9 @@ can create it with the help of :py:class:`http.HTTPStatus`. For example::
|
||||
Usage
|
||||
-----
|
||||
|
||||
Typical usage could look like::
|
||||
Typical usage could look like:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.http import JsonResponse
|
||||
>>> response = JsonResponse({'foo': 'bar'})
|
||||
@ -1075,7 +1119,9 @@ Serializing non-dictionary objects
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
In order to serialize objects other than ``dict`` you must set the ``safe``
|
||||
parameter to ``False``::
|
||||
parameter to ``False``:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> response = JsonResponse([1, 2, 3], safe=False)
|
||||
|
||||
@ -1099,7 +1145,9 @@ Changing the default JSON encoder
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
If you need to use a different JSON encoder class you can pass the ``encoder``
|
||||
parameter to the constructor method::
|
||||
parameter to the constructor method:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> response = JsonResponse(data, encoder=MyJSONEncoder)
|
||||
|
||||
@ -1244,7 +1292,9 @@ Attributes
|
||||
when they can be guessed from contents of ``open_file``.
|
||||
|
||||
``FileResponse`` accepts any file-like object with binary content, for example
|
||||
a file open in binary mode like so::
|
||||
a file open in binary mode like so:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.http import FileResponse
|
||||
>>> response = FileResponse(open('myfile.png', 'rb'))
|
||||
|
@ -1685,7 +1685,9 @@ formats defined in this file.
|
||||
|
||||
For example, if :setting:`FORMAT_MODULE_PATH` is set to ``mysite.formats``,
|
||||
and current language is ``en`` (English), Django will expect a directory tree
|
||||
like::
|
||||
like:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
mysite/
|
||||
formats/
|
||||
|
@ -325,7 +325,9 @@ If we connected a handler like this::
|
||||
|
||||
m2m_changed.connect(toppings_changed, sender=Pizza.toppings.through)
|
||||
|
||||
and then did something like this::
|
||||
and then did something like this:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> p = Pizza.objects.create(...)
|
||||
>>> t = Topping.objects.create(...)
|
||||
@ -355,7 +357,9 @@ Argument Value
|
||||
``using`` ``"default"`` (since the default router sends writes here)
|
||||
============== ============================================================
|
||||
|
||||
And if we would then do something like this::
|
||||
And if we would then do something like this:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> t.pizza_set.remove(p)
|
||||
|
||||
|
@ -218,7 +218,9 @@ subsequent rendering calls do not change the response content.
|
||||
However, when ``response.content`` is explicitly assigned, the
|
||||
change is always applied. If you want to force the content to be
|
||||
re-rendered, you can reevaluate the rendered content, and assign
|
||||
the content of the response manually::
|
||||
the content of the response manually:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
# Set up a rendered TemplateResponse
|
||||
>>> from django.template.response import TemplateResponse
|
||||
|
@ -211,7 +211,9 @@ different contexts.
|
||||
.. method:: Template.render(context)
|
||||
|
||||
Call the :class:`Template` object's ``render()`` method with a
|
||||
:class:`Context` to "fill" the template::
|
||||
:class:`Context` to "fill" the template:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.template import Context, Template
|
||||
>>> template = Template("My name is {{ my_name }}.")
|
||||
@ -243,7 +245,9 @@ interpreted as a literal string and not using the value of the variable "bar",
|
||||
if one exists in the template context.
|
||||
|
||||
The template system uses the first lookup type that works. It's short-circuit
|
||||
logic. Here are a few examples::
|
||||
logic. Here are a few examples:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.template import Context, Template
|
||||
>>> t = Template("My name is {{ person.first_name }}.")
|
||||
@ -264,7 +268,9 @@ logic. Here are a few examples::
|
||||
"The first stooge in the list is Larry."
|
||||
|
||||
If any part of the variable is callable, the template system will try calling
|
||||
it. Example::
|
||||
it. Example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> class PersonClass2:
|
||||
... def name(self):
|
||||
@ -282,7 +288,9 @@ straight lookups. Here are some things to keep in mind:
|
||||
*does* have a ``silent_variable_failure`` attribute whose value is
|
||||
``True``, the variable will render as the value of the engine's
|
||||
``string_if_invalid`` configuration option (an empty string, by default).
|
||||
Example::
|
||||
Example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> t = Template("My name is {{ person.first_name }}.")
|
||||
>>> class PersonClass3:
|
||||
@ -320,9 +328,11 @@ straight lookups. Here are some things to keep in mind:
|
||||
|
||||
A good example is the :meth:`~django.db.models.Model.delete` method on
|
||||
each Django model object. The template system shouldn't be allowed to do
|
||||
something like this::
|
||||
something like this:
|
||||
|
||||
I will now delete this valuable data. {{ data.delete }}
|
||||
.. code-block:: html+django
|
||||
|
||||
I will now delete this valuable data. {{ data.delete }}
|
||||
|
||||
To prevent this, set an ``alters_data`` attribute on the callable
|
||||
variable. The template system won't call a variable if it has
|
||||
@ -395,14 +405,18 @@ A similar issue exists if you want to include these sequences in template filter
|
||||
or tag arguments. For example, when parsing a block tag, Django's template
|
||||
parser looks for the first occurrence of ``%}`` after a ``{%``. This prevents
|
||||
the use of ``"%}"`` as a string literal. For example, a ``TemplateSyntaxError``
|
||||
will be raised for the following expressions::
|
||||
will be raised for the following expressions:
|
||||
|
||||
.. code-block:: html+django
|
||||
|
||||
{% include "template.html" tvar="Some string literal with %} in it." %}
|
||||
|
||||
{% with tvar="Some string literal with %} in it." %}{% endwith %}
|
||||
|
||||
The same issue can be triggered by using a reserved sequence in filter
|
||||
arguments::
|
||||
arguments:
|
||||
|
||||
.. code-block:: html+django
|
||||
|
||||
{{ some.variable|default:"}}" }}
|
||||
|
||||
@ -417,7 +431,9 @@ Playing with ``Context`` objects
|
||||
Most of the time, you'll instantiate :class:`Context` objects by passing in a
|
||||
fully-populated dictionary to ``Context()``. But you can add and delete items
|
||||
from a ``Context`` object once it's been instantiated, too, using standard
|
||||
dictionary syntax::
|
||||
dictionary syntax:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.template import Context
|
||||
>>> c = Context({"foo": "bar"})
|
||||
@ -448,7 +464,9 @@ dictionary syntax::
|
||||
|
||||
A ``Context`` object is a stack. That is, you can ``push()`` and ``pop()`` it.
|
||||
If you ``pop()`` too much, it'll raise
|
||||
``django.template.ContextPopException``::
|
||||
``django.template.ContextPopException``:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> c = Context()
|
||||
>>> c['foo'] = 'first level'
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -34,8 +34,6 @@ or Jinja2_, you should feel right at home with Django's templates.
|
||||
Templates
|
||||
=========
|
||||
|
||||
.. highlight:: html+django
|
||||
|
||||
A template is a text file. It can generate any text-based format (HTML, XML,
|
||||
CSV, etc.).
|
||||
|
||||
@ -100,7 +98,9 @@ Use a dot (``.``) to access attributes of a variable.
|
||||
|
||||
This lookup order can cause some unexpected behavior with objects that
|
||||
override dictionary lookup. For example, consider the following code snippet
|
||||
that attempts to loop over a ``collections.defaultdict``::
|
||||
that attempts to loop over a ``collections.defaultdict``:
|
||||
|
||||
.. code-block:: html+django
|
||||
|
||||
{% for k, v in defaultdict.items %}
|
||||
Do something with k and v here...
|
||||
@ -151,7 +151,9 @@ used template filters:
|
||||
|
||||
:tfilter:`default`
|
||||
If a variable is false or empty, use given default. Otherwise, use the
|
||||
value of the variable. For example::
|
||||
value of the variable. For example:
|
||||
|
||||
.. code-block:: html+django
|
||||
|
||||
{{ value|default:"nothing" }}
|
||||
|
||||
@ -160,7 +162,9 @@ used template filters:
|
||||
|
||||
:tfilter:`length`
|
||||
Returns the length of the value. This works for both strings and lists.
|
||||
For example::
|
||||
For example:
|
||||
|
||||
.. code-block:: html+django
|
||||
|
||||
{{ value|length }}
|
||||
|
||||
@ -168,7 +172,9 @@ used template filters:
|
||||
|
||||
:tfilter:`filesizeformat`
|
||||
Formats the value like a "human-readable" file size (i.e. ``'13 KB'``,
|
||||
``'4.1 MB'``, ``'102 bytes'``, etc.). For example::
|
||||
``'4.1 MB'``, ``'102 bytes'``, etc.). For example:
|
||||
|
||||
.. code-block:: html+django
|
||||
|
||||
{{ value|filesizeformat }}
|
||||
|
||||
@ -203,7 +209,9 @@ tags:
|
||||
|
||||
:ttag:`for`
|
||||
Loop over each item in an array. For example, to display a list of athletes
|
||||
provided in ``athlete_list``::
|
||||
provided in ``athlete_list``:
|
||||
|
||||
.. code-block:: html+django
|
||||
|
||||
<ul>
|
||||
{% for athlete in athlete_list %}
|
||||
@ -213,7 +221,9 @@ tags:
|
||||
|
||||
:ttag:`if`, ``elif``, and ``else``
|
||||
Evaluates a variable, and if that variable is "true" the contents of the
|
||||
block are displayed::
|
||||
block are displayed:
|
||||
|
||||
.. code-block:: html+django
|
||||
|
||||
{% if athlete_list %}
|
||||
Number of athletes: {{ athlete_list|length }}
|
||||
@ -229,7 +239,9 @@ tags:
|
||||
should be out..." will be displayed. If both lists are empty,
|
||||
"No athletes." will be displayed.
|
||||
|
||||
You can also use filters and various operators in the :ttag:`if` tag::
|
||||
You can also use filters and various operators in the :ttag:`if` tag:
|
||||
|
||||
.. code-block:: html+django
|
||||
|
||||
{% if athlete_list|length > 1 %}
|
||||
Team: {% for athlete in athlete_list %} ... {% endfor %}
|
||||
@ -264,11 +276,15 @@ Comments
|
||||
|
||||
To comment-out part of a line in a template, use the comment syntax: ``{# #}``.
|
||||
|
||||
For example, this template would render as ``'hello'``::
|
||||
For example, this template would render as ``'hello'``:
|
||||
|
||||
.. code-block:: html+django
|
||||
|
||||
{# greeting #}hello
|
||||
|
||||
A comment can contain any template code, invalid or not. For example::
|
||||
A comment can contain any template code, invalid or not. For example:
|
||||
|
||||
.. code-block:: html+django
|
||||
|
||||
{# {% if foo %}bar{% else %} #}
|
||||
|
||||
@ -286,7 +302,9 @@ engine is template inheritance. Template inheritance allows you to build a base
|
||||
"skeleton" template that contains all the common elements of your site and
|
||||
defines **blocks** that child templates can override.
|
||||
|
||||
Let's look at template inheritance by starting with an example::
|
||||
Let's look at template inheritance by starting with an example:
|
||||
|
||||
.. code-block:: html+django
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
@ -319,7 +337,9 @@ In this example, the :ttag:`block` tag defines three blocks that child
|
||||
templates can fill in. All the :ttag:`block` tag does is to tell the template
|
||||
engine that a child template may override those portions of the template.
|
||||
|
||||
A child template might look like this::
|
||||
A child template might look like this:
|
||||
|
||||
.. code-block:: html+django
|
||||
|
||||
{% extends "base.html" %}
|
||||
|
||||
@ -339,7 +359,9 @@ this template, first it locates the parent -- in this case, "base.html".
|
||||
At that point, the template engine will notice the three :ttag:`block` tags
|
||||
in ``base.html`` and replace those blocks with the contents of the child
|
||||
template. Depending on the value of ``blog_entries``, the output might look
|
||||
like::
|
||||
like:
|
||||
|
||||
.. code-block:: html+django
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
@ -416,13 +438,17 @@ Here are some tips for working with inheritance:
|
||||
|
||||
* Variables created outside of a :ttag:`{% block %}<block>` using the template
|
||||
tag ``as`` syntax can't be used inside the block. For example, this template
|
||||
doesn't render anything::
|
||||
doesn't render anything:
|
||||
|
||||
.. code-block:: html+django
|
||||
|
||||
{% translate "Title" as title %}
|
||||
{% block content %}{{ title }}{% endblock %}
|
||||
|
||||
* For extra readability, you can optionally give a *name* to your
|
||||
``{% endblock %}`` tag. For example::
|
||||
``{% endblock %}`` tag. For example:
|
||||
|
||||
.. code-block:: html+django
|
||||
|
||||
{% block content %}
|
||||
...
|
||||
@ -434,7 +460,9 @@ Here are some tips for working with inheritance:
|
||||
* :ttag:`{% block %}<block>` tags are evaluated first. That's why the content
|
||||
of a block is always overridden, regardless of the truthiness of surrounding
|
||||
tags. For example, this template will *always* override the content of the
|
||||
``title`` block::
|
||||
``title`` block:
|
||||
|
||||
.. code-block:: html+django
|
||||
|
||||
{% if change_title %}
|
||||
{% block title %}Hello!{% endblock title %}
|
||||
@ -455,16 +483,22 @@ Automatic HTML escaping
|
||||
|
||||
When generating HTML from templates, there's always a risk that a variable will
|
||||
include characters that affect the resulting HTML. For example, consider this
|
||||
template fragment::
|
||||
template fragment:
|
||||
|
||||
.. code-block:: html+django
|
||||
|
||||
Hello, {{ name }}
|
||||
|
||||
At first, this seems like a harmless way to display a user's name, but consider
|
||||
what would happen if the user entered their name as this::
|
||||
what would happen if the user entered their name as this:
|
||||
|
||||
.. code-block:: html+django
|
||||
|
||||
<script>alert('hello')</script>
|
||||
|
||||
With this name value, the template would be rendered as::
|
||||
With this name value, the template would be rendered as:
|
||||
|
||||
.. code-block:: html+django
|
||||
|
||||
Hello, <script>alert('hello')</script>
|
||||
|
||||
@ -476,7 +510,9 @@ Similarly, what if the name contained a ``'<'`` symbol, like this?
|
||||
|
||||
<b>username
|
||||
|
||||
That would result in a rendered template like this::
|
||||
That would result in a rendered template like this:
|
||||
|
||||
.. code-block:: html+django
|
||||
|
||||
Hello, <b>username
|
||||
|
||||
@ -531,14 +567,18 @@ For individual variables
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
To disable auto-escaping for an individual variable, use the :tfilter:`safe`
|
||||
filter::
|
||||
filter:
|
||||
|
||||
.. code-block:: html+django
|
||||
|
||||
This will be escaped: {{ data }}
|
||||
This will not be escaped: {{ data|safe }}
|
||||
|
||||
Think of *safe* as shorthand for *safe from further escaping* or *can be
|
||||
safely interpreted as HTML*. In this example, if ``data`` contains ``'<b>'``,
|
||||
the output will be::
|
||||
the output will be:
|
||||
|
||||
.. code-block:: html+django
|
||||
|
||||
This will be escaped: <b>
|
||||
This will not be escaped: <b>
|
||||
@ -547,7 +587,9 @@ For template blocks
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
To control auto-escaping for a template, wrap the template (or a particular
|
||||
section of the template) in the :ttag:`autoescape` tag, like so::
|
||||
section of the template) in the :ttag:`autoescape` tag, like so:
|
||||
|
||||
.. code-block:: html+django
|
||||
|
||||
{% autoescape off %}
|
||||
Hello {{ name }}
|
||||
@ -555,7 +597,9 @@ section of the template) in the :ttag:`autoescape` tag, like so::
|
||||
|
||||
The :ttag:`autoescape` tag takes either ``on`` or ``off`` as its argument. At
|
||||
times, you might want to force auto-escaping when it would otherwise be
|
||||
disabled. Here is an example template::
|
||||
disabled. Here is an example template:
|
||||
|
||||
.. code-block:: html+django
|
||||
|
||||
Auto-escaping is on by default. Hello {{ name }}
|
||||
|
||||
@ -590,7 +634,9 @@ just like all block tags. For example:
|
||||
|
||||
Because auto-escaping is turned off in the base template, it will also be
|
||||
turned off in the child template, resulting in the following rendered
|
||||
HTML when the ``greeting`` variable contains the string ``<b>Hello!</b>``::
|
||||
HTML when the ``greeting`` variable contains the string ``<b>Hello!</b>``:
|
||||
|
||||
.. code-block:: html+django
|
||||
|
||||
<h1>This & that</h1>
|
||||
<b>Hello!</b>
|
||||
@ -614,7 +660,9 @@ danger of the :tfilter:`escape` filter *double-escaping* data -- the
|
||||
String literals and automatic escaping
|
||||
--------------------------------------
|
||||
|
||||
As we mentioned earlier, filter arguments can be strings::
|
||||
As we mentioned earlier, filter arguments can be strings:
|
||||
|
||||
.. code-block:: html+django
|
||||
|
||||
{{ data|default:"This is a string literal." }}
|
||||
|
||||
@ -624,11 +672,15 @@ filter. The reasoning behind this is that the template author is in control of
|
||||
what goes into the string literal, so they can make sure the text is correctly
|
||||
escaped when the template is written.
|
||||
|
||||
This means you would write ::
|
||||
This means you would write :
|
||||
|
||||
.. code-block:: html+django
|
||||
|
||||
{{ data|default:"3 < 2" }}
|
||||
|
||||
...rather than::
|
||||
...rather than:
|
||||
|
||||
.. code-block:: html+django
|
||||
|
||||
{{ data|default:"3 < 2" }} {# Bad! Don't do this. #}
|
||||
|
||||
@ -647,7 +699,9 @@ This means that templates have access to much more than just class attributes
|
||||
ORM provides the :ref:`"entry_set"<topics-db-queries-related>` syntax for
|
||||
finding a collection of objects related on a foreign key. Therefore, given
|
||||
a model called "comment" with a foreign key relationship to a model called
|
||||
"task" you can loop through all comments attached to a given task like this::
|
||||
"task" you can loop through all comments attached to a given task like this:
|
||||
|
||||
.. code-block:: html+django
|
||||
|
||||
{% for comment in task.comment_set.all %}
|
||||
{{ comment }}
|
||||
@ -655,7 +709,9 @@ a model called "comment" with a foreign key relationship to a model called
|
||||
|
||||
Similarly, :doc:`QuerySets</ref/models/querysets>` provide a ``count()`` method
|
||||
to count the number of objects they contain. Therefore, you can obtain a count
|
||||
of all comments related to the current task with::
|
||||
of all comments related to the current task with:
|
||||
|
||||
.. code-block:: html+django
|
||||
|
||||
{{ task.comment_set.all.count }}
|
||||
|
||||
@ -686,7 +742,9 @@ Custom tag and filter libraries
|
||||
Certain applications provide custom tag and filter libraries. To access them in
|
||||
a template, ensure the application is in :setting:`INSTALLED_APPS` (we'd add
|
||||
``'django.contrib.humanize'`` for this example), and then use the :ttag:`load`
|
||||
tag in a template::
|
||||
tag in a template:
|
||||
|
||||
.. code-block:: html+django
|
||||
|
||||
{% load humanize %}
|
||||
|
||||
@ -698,7 +756,9 @@ makes the ``intcomma`` filter available for use. If you've enabled
|
||||
admin to find the list of custom libraries in your installation.
|
||||
|
||||
The :ttag:`load` tag can take multiple library names, separated by spaces.
|
||||
Example::
|
||||
Example:
|
||||
|
||||
.. code-block:: html+django
|
||||
|
||||
{% load humanize i18n %}
|
||||
|
||||
|
@ -174,7 +174,9 @@ further encoded when passed to ``iri_to_uri()``. This means you can pass a
|
||||
full URL to this function and it will not mess up the query string or anything
|
||||
like that.
|
||||
|
||||
An example might clarify things here::
|
||||
An example might clarify things here:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from urllib.parse import quote
|
||||
>>> from django.utils.encoding import iri_to_uri
|
||||
@ -193,7 +195,9 @@ result.
|
||||
Similarly, Django provides :func:`django.utils.encoding.uri_to_iri()` which
|
||||
implements the conversion from URI to IRI as per :rfc:`3987#section-3.2`.
|
||||
|
||||
An example to demonstrate::
|
||||
An example to demonstrate:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.utils.encoding import uri_to_iri
|
||||
>>> uri_to_iri('/%E2%99%A5%E2%99%A5/?utf8=%E2%9C%93')
|
||||
@ -309,7 +313,9 @@ and application server for the appropriate syntax and location to set this
|
||||
variable. See the :doc:`/howto/deployment/wsgi/modwsgi` for examples.
|
||||
|
||||
In your development environment, you might need to add a setting to your
|
||||
``~.bashrc`` analogous to:::
|
||||
``~.bashrc`` analogous to:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
export LANG="en_US.UTF-8"
|
||||
|
||||
|
@ -36,7 +36,9 @@ If the URL accepts arguments, you may pass them in ``args``. For example::
|
||||
def myview(request):
|
||||
return HttpResponseRedirect(reverse('arch-summary', args=[1945]))
|
||||
|
||||
You can also pass ``kwargs`` instead of ``args``. For example::
|
||||
You can also pass ``kwargs`` instead of ``args``. For example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> reverse('admin:app_list', kwargs={'app_label': 'auth'})
|
||||
'/admin/auth/'
|
||||
@ -65,7 +67,9 @@ use for reversing. By default, the root URLconf for the current thread is used.
|
||||
.. note::
|
||||
|
||||
The string returned by ``reverse()`` is already
|
||||
:ref:`urlquoted <uri-and-iri-handling>`. For example::
|
||||
:ref:`urlquoted <uri-and-iri-handling>`. For example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> reverse('cities', args=['Orléans'])
|
||||
'.../Orl%C3%A9ans/'
|
||||
|
@ -298,7 +298,9 @@ The functions defined in this module share the following properties:
|
||||
.. module:: django.utils.feedgenerator
|
||||
:synopsis: Syndication feed generation library -- used for generating RSS, etc.
|
||||
|
||||
Sample usage::
|
||||
Sample usage:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.utils import feedgenerator
|
||||
>>> feed = feedgenerator.Rss201rev2Feed(
|
||||
@ -655,9 +657,11 @@ escaping HTML.
|
||||
Escapes all HTML/XML special characters with their Unicode escapes, so
|
||||
value is safe for use with JavaScript. Also wraps the escaped JSON in a
|
||||
``<script>`` tag. If the ``element_id`` parameter is not ``None``, the
|
||||
``<script>`` tag is given the passed id. For example::
|
||||
``<script>`` tag is given the passed id. For example:
|
||||
|
||||
>> json_script({"hello": "world"}, element_id="hello-data")
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> json_script({"hello": "world"}, element_id="hello-data")
|
||||
'<script id="hello-data" type="application/json">{"hello": "world"}</script>'
|
||||
|
||||
The ``encoder``, which defaults to
|
||||
@ -797,7 +801,9 @@ appropriate entities.
|
||||
For building up fragments of HTML, you should normally be using
|
||||
:func:`django.utils.html.format_html` instead.
|
||||
|
||||
String marked safe will become unsafe again if modified. For example::
|
||||
String marked safe will become unsafe again if modified. For example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> mystr = '<b>Hello World</b> '
|
||||
>>> mystr = mark_safe(mystr)
|
||||
@ -843,13 +849,17 @@ appropriate entities.
|
||||
#. Replacing any whitespace or repeated dashes with single dashes.
|
||||
#. Removing leading and trailing whitespace, dashes, and underscores.
|
||||
|
||||
For example::
|
||||
For example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> slugify(' Joel is a slug ')
|
||||
'joel-is-a-slug'
|
||||
|
||||
If you want to allow Unicode characters, pass ``allow_unicode=True``. For
|
||||
example::
|
||||
example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> slugify('你好 World', allow_unicode=True)
|
||||
'你好-world'
|
||||
|
@ -2,8 +2,6 @@
|
||||
Porting your apps from Django 0.96 to 1.0
|
||||
=========================================
|
||||
|
||||
.. highlight:: python
|
||||
|
||||
Django 1.0 breaks compatibility with 0.96 in some areas.
|
||||
|
||||
This guide will help you port 0.96 projects and apps to 1.0. The first part of
|
||||
|
@ -166,14 +166,18 @@ running your Django code. For example, Jupyter_ notebooks and IPython_
|
||||
interactive shells both transparently provide an active event loop so that it is
|
||||
easier to interact with asynchronous APIs.
|
||||
|
||||
If you're using an IPython shell, you can disable this event loop by running::
|
||||
If you're using an IPython shell, you can disable this event loop by running:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
%autoawait off
|
||||
|
||||
as a command at the IPython prompt. This will allow you to run synchronous code
|
||||
without generating :exc:`~django.core.exceptions.SynchronousOnlyOperation`
|
||||
errors; however, you also won't be able to ``await`` asynchronous APIs. To turn
|
||||
the event loop back on, run::
|
||||
the event loop back on, run:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
%autoawait on
|
||||
|
||||
|
@ -323,7 +323,9 @@ you might create an Employee model::
|
||||
|
||||
Assuming an existing Employee Fred Smith who has both a User and Employee
|
||||
model, you can access the related information using Django's standard related
|
||||
model conventions::
|
||||
model conventions:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> u = User.objects.get(username='fsmith')
|
||||
>>> freds_department = u.employee.department
|
||||
|
@ -46,7 +46,9 @@ Creating users
|
||||
--------------
|
||||
|
||||
The most direct way to create users is to use the included
|
||||
:meth:`~django.contrib.auth.models.UserManager.create_user` helper function::
|
||||
:meth:`~django.contrib.auth.models.UserManager.create_user` helper function:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.contrib.auth.models import User
|
||||
>>> user = User.objects.create_user('john', 'lennon@thebeatles.com', 'johnpassword')
|
||||
@ -65,7 +67,9 @@ interactively <auth-admin>`.
|
||||
Creating superusers
|
||||
-------------------
|
||||
|
||||
Create superusers using the :djadmin:`createsuperuser` command::
|
||||
Create superusers using the :djadmin:`createsuperuser` command:
|
||||
|
||||
.. console::
|
||||
|
||||
$ python manage.py createsuperuser --username=joe --email=joe@example.com
|
||||
|
||||
@ -330,6 +334,8 @@ inherit the permissions of the concrete model they subclass::
|
||||
proxy = True
|
||||
permissions = [('can_deliver_pizzas', 'Can deliver pizzas')]
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> # Fetch the content type for the proxy model.
|
||||
>>> content_type = ContentType.objects.get_for_model(Student, for_concrete_model=False)
|
||||
>>> student_permissions = Permission.objects.filter(content_type=content_type)
|
||||
@ -1723,13 +1729,17 @@ template-friendly proxy of permissions.
|
||||
Evaluating a single-attribute lookup of ``{{ perms }}`` as a boolean is a proxy
|
||||
to :meth:`User.has_module_perms()
|
||||
<django.contrib.auth.models.User.has_module_perms>`. For example, to check if
|
||||
the logged-in user has any permissions in the ``foo`` app::
|
||||
the logged-in user has any permissions in the ``foo`` app:
|
||||
|
||||
.. code-block:: html+django
|
||||
|
||||
{% if perms.foo %}
|
||||
|
||||
Evaluating a two-level-attribute lookup as a boolean is a proxy to
|
||||
:meth:`User.has_perm() <django.contrib.auth.models.User.has_perm>`. For example,
|
||||
to check if the logged-in user has the permission ``foo.add_vote``::
|
||||
to check if the logged-in user has the permission ``foo.add_vote``:
|
||||
|
||||
.. code-block:: html+django
|
||||
|
||||
{% if perms.foo.add_vote %}
|
||||
|
||||
|
@ -264,7 +264,9 @@ Creating the cache table
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Before using the database cache, you must create the cache table with this
|
||||
command::
|
||||
command:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
python manage.py createcachetable
|
||||
|
||||
@ -840,8 +842,6 @@ a cached item, for example:
|
||||
The low-level cache API
|
||||
=======================
|
||||
|
||||
.. highlight:: python
|
||||
|
||||
Sometimes, caching an entire rendered page doesn't gain you very much and is,
|
||||
in fact, inconvenient overkill.
|
||||
|
||||
@ -884,7 +884,9 @@ Accessing the cache
|
||||
.. data:: django.core.cache.cache
|
||||
|
||||
As a shortcut, the default cache is available as
|
||||
``django.core.cache.cache``::
|
||||
``django.core.cache.cache``:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.core.cache import cache
|
||||
|
||||
@ -916,14 +918,18 @@ It's the number of seconds the value should be stored in the cache. Passing in
|
||||
``None`` for ``timeout`` will cache the value forever. A ``timeout`` of ``0``
|
||||
won't cache the value.
|
||||
|
||||
If the object doesn't exist in the cache, ``cache.get()`` returns ``None``::
|
||||
If the object doesn't exist in the cache, ``cache.get()`` returns ``None``:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> # Wait 30 seconds for 'my_key' to expire...
|
||||
>>> cache.get('my_key')
|
||||
None
|
||||
|
||||
If you need to determine whether the object exists in the cache and you have
|
||||
stored a literal value ``None``, use a sentinel object as the default::
|
||||
stored a literal value ``None``, use a sentinel object as the default:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> sentinel = object()
|
||||
>>> cache.get('my_key', sentinel) is sentinel
|
||||
@ -933,7 +939,9 @@ stored a literal value ``None``, use a sentinel object as the default::
|
||||
True
|
||||
|
||||
``cache.get()`` can take a ``default`` argument. This specifies which value to
|
||||
return if the object doesn't exist in the cache::
|
||||
return if the object doesn't exist in the cache:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> cache.get('my_key', 'has expired')
|
||||
'has expired'
|
||||
@ -942,7 +950,9 @@ return if the object doesn't exist in the cache::
|
||||
|
||||
To add a key only if it doesn't already exist, use the ``add()`` method.
|
||||
It takes the same parameters as ``set()``, but it will not attempt to
|
||||
update the cache if the key specified is already present::
|
||||
update the cache if the key specified is already present:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> cache.set('add_key', 'Initial value')
|
||||
>>> cache.add('add_key', 'New value')
|
||||
@ -958,13 +968,17 @@ check the return value. It will return ``True`` if the value was stored,
|
||||
If you want to get a key's value or set a value if the key isn't in the cache,
|
||||
there is the ``get_or_set()`` method. It takes the same parameters as ``get()``
|
||||
but the default is set as the new cache value for that key, rather than
|
||||
returned::
|
||||
returned:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> cache.get('my_new_key') # returns None
|
||||
>>> cache.get_or_set('my_new_key', 'my new value', 100)
|
||||
'my new value'
|
||||
|
||||
You can also pass any callable as a *default* value::
|
||||
You can also pass any callable as a *default* value:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> import datetime
|
||||
>>> cache.get_or_set('some-timestamp-key', datetime.datetime.now)
|
||||
@ -974,7 +988,9 @@ You can also pass any callable as a *default* value::
|
||||
|
||||
There's also a ``get_many()`` interface that only hits the cache once.
|
||||
``get_many()`` returns a dictionary with all the keys you asked for that
|
||||
actually exist in the cache (and haven't expired)::
|
||||
actually exist in the cache (and haven't expired):
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> cache.set('a', 1)
|
||||
>>> cache.set('b', 2)
|
||||
@ -985,7 +1001,9 @@ actually exist in the cache (and haven't expired)::
|
||||
.. method:: cache.set_many(dict, timeout)
|
||||
|
||||
To set multiple values more efficiently, use ``set_many()`` to pass a dictionary
|
||||
of key-value pairs::
|
||||
of key-value pairs:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> cache.set_many({'a': 1, 'b': 2, 'c': 3})
|
||||
>>> cache.get_many(['a', 'b', 'c'])
|
||||
@ -999,7 +1017,9 @@ failed to be inserted.
|
||||
.. method:: cache.delete(key, version=None)
|
||||
|
||||
You can delete keys explicitly with ``delete()`` to clear the cache for a
|
||||
particular object::
|
||||
particular object:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> cache.delete('a')
|
||||
True
|
||||
@ -1010,7 +1030,9 @@ otherwise.
|
||||
.. method:: cache.delete_many(keys, version=None)
|
||||
|
||||
If you want to clear a bunch of keys at once, ``delete_many()`` can take a list
|
||||
of keys to be cleared::
|
||||
of keys to be cleared:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> cache.delete_many(['a', 'b', 'c'])
|
||||
|
||||
@ -1018,14 +1040,18 @@ of keys to be cleared::
|
||||
|
||||
Finally, if you want to delete all the keys in the cache, use
|
||||
``cache.clear()``. Be careful with this; ``clear()`` will remove *everything*
|
||||
from the cache, not just the keys set by your application. ::
|
||||
from the cache, not just the keys set by your application. :
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> cache.clear()
|
||||
|
||||
.. method:: cache.touch(key, timeout=DEFAULT_TIMEOUT, version=None)
|
||||
|
||||
``cache.touch()`` sets a new expiration for a key. For example, to update a key
|
||||
to expire 10 seconds from now::
|
||||
to expire 10 seconds from now:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> cache.touch('a', 10)
|
||||
True
|
||||
@ -1044,7 +1070,9 @@ You can also increment or decrement a key that already exists using the
|
||||
value will be incremented or decremented by 1. Other increment/decrement values
|
||||
can be specified by providing an argument to the increment/decrement call. A
|
||||
ValueError will be raised if you attempt to increment or decrement a
|
||||
nonexistent cache key.::
|
||||
nonexistent cache key:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> cache.set('num', 1)
|
||||
>>> cache.incr('num')
|
||||
@ -1120,7 +1148,9 @@ prefix and the user-provided cache key to obtain the final cache key.
|
||||
By default, any key request will automatically include the site
|
||||
default cache key version. However, the primitive cache functions all
|
||||
include a ``version`` argument, so you can specify a particular cache
|
||||
key version to set or get. For example::
|
||||
key version to set or get. For example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> # Set version 2 of a cache key
|
||||
>>> cache.set('my_key', 'hello world!', version=2)
|
||||
@ -1134,7 +1164,9 @@ key version to set or get. For example::
|
||||
The version of a specific key can be incremented and decremented using
|
||||
the ``incr_version()`` and ``decr_version()`` methods. This
|
||||
enables specific keys to be bumped to a new version, leaving other
|
||||
keys unaffected. Continuing our previous example::
|
||||
keys unaffected. Continuing our previous example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> # Increment the version of 'my_key'
|
||||
>>> cache.incr_version('my_key')
|
||||
@ -1218,7 +1250,9 @@ yet support asynchronous caching. It will be coming in a future release.
|
||||
``django.core.cache.backends.base.BaseCache`` has async variants of :ref:`all
|
||||
base methods <cache-basic-interface>`. By convention, the asynchronous versions
|
||||
of all methods are prefixed with ``a``. By default, the arguments for both
|
||||
variants are the same::
|
||||
variants are the same:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> await cache.aset('num', 1)
|
||||
>>> await cache.ahas_key('num')
|
||||
|
@ -44,7 +44,9 @@ Cheat sheet
|
||||
===========
|
||||
|
||||
In a hurry? Here's how to do common aggregate queries, assuming the models
|
||||
above::
|
||||
above:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
# Total number of books.
|
||||
>>> Book.objects.count()
|
||||
@ -102,19 +104,25 @@ Generating aggregates over a ``QuerySet``
|
||||
Django provides two ways to generate aggregates. The first way is to generate
|
||||
summary values over an entire ``QuerySet``. For example, say you wanted to
|
||||
calculate the average price of all books available for sale. Django's query
|
||||
syntax provides a means for describing the set of all books::
|
||||
syntax provides a means for describing the set of all books:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Book.objects.all()
|
||||
|
||||
What we need is a way to calculate summary values over the objects that
|
||||
belong to this ``QuerySet``. This is done by appending an ``aggregate()``
|
||||
clause onto the ``QuerySet``::
|
||||
clause onto the ``QuerySet``:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.db.models import Avg
|
||||
>>> Book.objects.all().aggregate(Avg('price'))
|
||||
{'price__avg': 34.35}
|
||||
|
||||
The ``all()`` is redundant in this example, so this could be simplified to::
|
||||
The ``all()`` is redundant in this example, so this could be simplified to:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Book.objects.aggregate(Avg('price'))
|
||||
{'price__avg': 34.35}
|
||||
@ -129,14 +137,18 @@ returns a dictionary of name-value pairs. The name is an identifier for the
|
||||
aggregate value; the value is the computed aggregate. The name is
|
||||
automatically generated from the name of the field and the aggregate function.
|
||||
If you want to manually specify a name for the aggregate value, you can do so
|
||||
by providing that name when you specify the aggregate clause::
|
||||
by providing that name when you specify the aggregate clause:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Book.objects.aggregate(average_price=Avg('price'))
|
||||
{'average_price': 34.35}
|
||||
|
||||
If you want to generate more than one aggregate, you add another argument to
|
||||
the ``aggregate()`` clause. So, if we also wanted to know the maximum and
|
||||
minimum price of all books, we would issue the query::
|
||||
minimum price of all books, we would issue the query:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.db.models import Avg, Max, Min
|
||||
>>> Book.objects.aggregate(Avg('price'), Max('price'), Min('price'))
|
||||
@ -159,7 +171,9 @@ specified values.
|
||||
The syntax for these annotations is identical to that used for the
|
||||
:meth:`~.QuerySet.aggregate` clause. Each argument to ``annotate()`` describes
|
||||
an aggregate that is to be calculated. For example, to annotate books with the
|
||||
number of authors::
|
||||
number of authors:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
# Build an annotated queryset
|
||||
>>> from django.db.models import Count
|
||||
@ -178,7 +192,9 @@ number of authors::
|
||||
As with ``aggregate()``, the name for the annotation is automatically derived
|
||||
from the name of the aggregate function and the name of the field being
|
||||
aggregated. You can override this default name by providing an alias when you
|
||||
specify the annotation::
|
||||
specify the annotation:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> q = Book.objects.annotate(num_authors=Count('authors'))
|
||||
>>> q[0].num_authors
|
||||
@ -239,7 +255,9 @@ filters. Django will then handle any table joins that are required to retrieve
|
||||
and aggregate the related value.
|
||||
|
||||
For example, to find the price range of books offered in each store,
|
||||
you could use the annotation::
|
||||
you could use the annotation:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.db.models import Max, Min
|
||||
>>> Store.objects.annotate(min_price=Min('books__price'), max_price=Max('books__price'))
|
||||
@ -250,13 +268,17 @@ price field of the book model to produce a minimum and maximum value.
|
||||
|
||||
The same rules apply to the ``aggregate()`` clause. If you wanted to
|
||||
know the lowest and highest price of any book that is available for sale
|
||||
in any of the stores, you could use the aggregate::
|
||||
in any of the stores, you could use the aggregate:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Store.objects.aggregate(min_price=Min('books__price'), max_price=Max('books__price'))
|
||||
|
||||
Join chains can be as deep as you require. For example, to extract the
|
||||
age of the youngest author of any book available for sale, you could
|
||||
issue the query::
|
||||
issue the query:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Store.objects.aggregate(youngest_age=Min('books__authors__age'))
|
||||
|
||||
@ -270,7 +292,9 @@ of related models and double-underscores are used here too.
|
||||
|
||||
For example, we can ask for all publishers, annotated with their respective
|
||||
total book stock counters (note how we use ``'book'`` to specify the
|
||||
``Publisher`` -> ``Book`` reverse foreign key hop)::
|
||||
``Publisher`` -> ``Book`` reverse foreign key hop):
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.db.models import Avg, Count, Min, Sum
|
||||
>>> Publisher.objects.annotate(Count('book'))
|
||||
@ -278,7 +302,9 @@ total book stock counters (note how we use ``'book'`` to specify the
|
||||
(Every ``Publisher`` in the resulting ``QuerySet`` will have an extra attribute
|
||||
called ``book__count``.)
|
||||
|
||||
We can also ask for the oldest book of any of those managed by every publisher::
|
||||
We can also ask for the oldest book of any of those managed by every publisher:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Publisher.objects.aggregate(oldest_pubdate=Min('book__pubdate'))
|
||||
|
||||
@ -288,7 +314,9 @@ such alias were specified, it would be the rather long ``'book__pubdate__min'``.
|
||||
This doesn't apply just to foreign keys. It also works with many-to-many
|
||||
relations. For example, we can ask for every author, annotated with the total
|
||||
number of pages considering all the books the author has (co-)authored (note how we
|
||||
use ``'book'`` to specify the ``Author`` -> ``Book`` reverse many-to-many hop)::
|
||||
use ``'book'`` to specify the ``Author`` -> ``Book`` reverse many-to-many hop):
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Author.objects.annotate(total_pages=Sum('book__pages'))
|
||||
|
||||
@ -297,7 +325,9 @@ called ``total_pages``. If no such alias were specified, it would be the rather
|
||||
long ``book__pages__sum``.)
|
||||
|
||||
Or ask for the average rating of all the books written by author(s) we have on
|
||||
file::
|
||||
file:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Author.objects.aggregate(average_rating=Avg('book__rating'))
|
||||
|
||||
@ -317,7 +347,9 @@ constraining the objects that are considered for aggregation.
|
||||
When used with an ``annotate()`` clause, a filter has the effect of
|
||||
constraining the objects for which an annotation is calculated. For example,
|
||||
you can generate an annotated list of all books that have a title starting
|
||||
with "Django" using the query::
|
||||
with "Django" using the query:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.db.models import Avg, Count
|
||||
>>> Book.objects.filter(name__startswith="Django").annotate(num_authors=Count('authors'))
|
||||
@ -325,7 +357,9 @@ with "Django" using the query::
|
||||
When used with an ``aggregate()`` clause, a filter has the effect of
|
||||
constraining the objects over which the aggregate is calculated.
|
||||
For example, you can generate the average price of all books with a
|
||||
title that starts with "Django" using the query::
|
||||
title that starts with "Django" using the query:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Book.objects.filter(name__startswith="Django").aggregate(Avg('price'))
|
||||
|
||||
@ -339,7 +373,9 @@ used in ``filter()`` and ``exclude()`` clauses in the same way as any other
|
||||
model field.
|
||||
|
||||
For example, to generate a list of books that have more than one author,
|
||||
you can issue the query::
|
||||
you can issue the query:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Book.objects.annotate(num_authors=Count('authors')).filter(num_authors__gt=1)
|
||||
|
||||
@ -348,7 +384,9 @@ based upon that annotation.
|
||||
|
||||
If you need two annotations with two separate filters you can use the
|
||||
``filter`` argument with any aggregate. For example, to generate a list of
|
||||
authors with a count of highly rated books::
|
||||
authors with a count of highly rated books:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> highly_rated = Count('book', filter=Q(book__rating__gte=7))
|
||||
>>> Author.objects.annotate(num_books=Count('book'), highly_rated_books=highly_rated)
|
||||
@ -381,7 +419,9 @@ Given:
|
||||
* Publisher B has two books with ratings 1 and 4.
|
||||
* Publisher C has one book with rating 1.
|
||||
|
||||
Here's an example with the ``Count`` aggregate::
|
||||
Here's an example with the ``Count`` aggregate:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> a, b = Publisher.objects.annotate(num_books=Count('book', distinct=True)).filter(book__rating__gt=3.0)
|
||||
>>> a, a.num_books
|
||||
@ -406,7 +446,9 @@ The second query counts the number of books that have a rating exceeding 3.0
|
||||
for each publisher. The filter precedes the annotation, so the filter
|
||||
constrains the objects considered when calculating the annotation.
|
||||
|
||||
Here's another example with the ``Avg`` aggregate::
|
||||
Here's another example with the ``Avg`` aggregate:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> a, b = Publisher.objects.annotate(avg_rating=Avg('book__rating')).filter(book__rating__gt=3.0)
|
||||
>>> a, a.avg_rating
|
||||
@ -437,7 +479,9 @@ define an ``order_by()`` clause, the aggregates you provide can reference
|
||||
any alias defined as part of an ``annotate()`` clause in the query.
|
||||
|
||||
For example, to order a ``QuerySet`` of books by the number of authors
|
||||
that have contributed to the book, you could use the following query::
|
||||
that have contributed to the book, you could use the following query:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Book.objects.annotate(num_authors=Count('authors')).order_by('num_authors')
|
||||
|
||||
@ -462,7 +506,9 @@ rating of books written by each author:
|
||||
This will return one result for each author in the database, annotated with
|
||||
their average book rating.
|
||||
|
||||
However, the result will be slightly different if you use a ``values()`` clause::
|
||||
However, the result will be slightly different if you use a ``values()`` clause:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Author.objects.values('name').annotate(average_rating=Avg('book__rating'))
|
||||
|
||||
@ -486,7 +532,9 @@ the ``values()`` clause only constrains the fields that are generated on
|
||||
output.
|
||||
|
||||
For example, if we reverse the order of the ``values()`` and ``annotate()``
|
||||
clause from our previous example::
|
||||
clause from our previous example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Author.objects.annotate(average_rating=Avg('book__rating')).values('name', 'average_rating')
|
||||
|
||||
@ -563,7 +611,9 @@ any alias defined as part of an ``annotate()`` clause in the query.
|
||||
|
||||
For example, if you wanted to calculate the average number of authors per
|
||||
book you first annotate the set of books with the author count, then
|
||||
aggregate that author count, referencing the annotation field::
|
||||
aggregate that author count, referencing the annotation field:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.db.models import Avg, Count
|
||||
>>> Book.objects.annotate(num_authors=Count('authors')).aggregate(Avg('num_authors'))
|
||||
|
@ -2,8 +2,6 @@
|
||||
Many-to-many relationships
|
||||
==========================
|
||||
|
||||
.. highlight:: pycon
|
||||
|
||||
To define a many-to-many relationship, use
|
||||
:class:`~django.db.models.ManyToManyField`.
|
||||
|
||||
@ -36,7 +34,9 @@ objects, and a ``Publication`` has multiple ``Article`` objects:
|
||||
What follows are examples of operations that can be performed using the Python
|
||||
API facilities.
|
||||
|
||||
Create a few ``Publications``::
|
||||
Create a few ``Publications``:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> p1 = Publication(title='The Python Journal')
|
||||
>>> p1.save()
|
||||
@ -45,11 +45,15 @@ Create a few ``Publications``::
|
||||
>>> p3 = Publication(title='Science Weekly')
|
||||
>>> p3.save()
|
||||
|
||||
Create an ``Article``::
|
||||
Create an ``Article``:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> a1 = Article(headline='Django lets you build web apps easily')
|
||||
|
||||
You can't associate it with a ``Publication`` until it's been saved::
|
||||
You can't associate it with a ``Publication`` until it's been saved:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> a1.publications.add(p1)
|
||||
Traceback (most recent call last):
|
||||
@ -57,26 +61,35 @@ You can't associate it with a ``Publication`` until it's been saved::
|
||||
ValueError: "<Article: Django lets you build web apps easily>" needs to have a value for field "id" before this many-to-many relationship can be used.
|
||||
|
||||
Save it!
|
||||
::
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> a1.save()
|
||||
|
||||
Associate the ``Article`` with a ``Publication``::
|
||||
Associate the ``Article`` with a ``Publication``:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> a1.publications.add(p1)
|
||||
|
||||
Create another ``Article``, and set it to appear in the ``Publications``::
|
||||
Create another ``Article``, and set it to appear in the ``Publications``:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> a2 = Article(headline='NASA uses Python')
|
||||
>>> a2.save()
|
||||
>>> a2.publications.add(p1, p2)
|
||||
>>> a2.publications.add(p3)
|
||||
|
||||
Adding a second time is OK, it will not duplicate the relation::
|
||||
Adding a second time is OK, it will not duplicate the relation:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> a2.publications.add(p3)
|
||||
|
||||
Adding an object of the wrong type raises :exc:`TypeError`::
|
||||
Adding an object of the wrong type raises :exc:`TypeError`:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> a2.publications.add(a1)
|
||||
Traceback (most recent call last):
|
||||
@ -84,18 +97,24 @@ Adding an object of the wrong type raises :exc:`TypeError`::
|
||||
TypeError: 'Publication' instance expected
|
||||
|
||||
Create and add a ``Publication`` to an ``Article`` in one step using
|
||||
:meth:`~django.db.models.fields.related.RelatedManager.create`::
|
||||
:meth:`~django.db.models.fields.related.RelatedManager.create`:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> new_publication = a2.publications.create(title='Highlights for Children')
|
||||
|
||||
``Article`` objects have access to their related ``Publication`` objects::
|
||||
``Article`` objects have access to their related ``Publication`` objects:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> a1.publications.all()
|
||||
<QuerySet [<Publication: The Python Journal>]>
|
||||
>>> a2.publications.all()
|
||||
<QuerySet [<Publication: Highlights for Children>, <Publication: Science News>, <Publication: Science Weekly>, <Publication: The Python Journal>]>
|
||||
|
||||
``Publication`` objects have access to their related ``Article`` objects::
|
||||
``Publication`` objects have access to their related ``Article`` objects:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> p2.article_set.all()
|
||||
<QuerySet [<Article: NASA uses Python>]>
|
||||
@ -105,7 +124,9 @@ Create and add a ``Publication`` to an ``Article`` in one step using
|
||||
<QuerySet [<Article: NASA uses Python>]>
|
||||
|
||||
Many-to-many relationships can be queried using :ref:`lookups across
|
||||
relationships <lookups-that-span-relationships>`::
|
||||
relationships <lookups-that-span-relationships>`:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Article.objects.filter(publications__id=1)
|
||||
<QuerySet [<Article: Django lets you build web apps easily>, <Article: NASA uses Python>]>
|
||||
@ -123,7 +144,9 @@ relationships <lookups-that-span-relationships>`::
|
||||
<QuerySet [<Article: NASA uses Python>]>
|
||||
|
||||
The :meth:`~django.db.models.query.QuerySet.count` function respects
|
||||
:meth:`~django.db.models.query.QuerySet.distinct` as well::
|
||||
:meth:`~django.db.models.query.QuerySet.distinct` as well:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Article.objects.filter(publications__title__startswith="Science").count()
|
||||
2
|
||||
@ -137,7 +160,9 @@ The :meth:`~django.db.models.query.QuerySet.count` function respects
|
||||
<QuerySet [<Article: Django lets you build web apps easily>, <Article: NASA uses Python>]>
|
||||
|
||||
Reverse m2m queries are supported (i.e., starting at the table that doesn't have
|
||||
a :class:`~django.db.models.ManyToManyField`)::
|
||||
a :class:`~django.db.models.ManyToManyField`):
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Publication.objects.filter(id=1)
|
||||
<QuerySet [<Publication: The Python Journal>]>
|
||||
@ -162,12 +187,16 @@ a :class:`~django.db.models.ManyToManyField`)::
|
||||
<QuerySet [<Publication: Highlights for Children>, <Publication: Science News>, <Publication: Science Weekly>, <Publication: The Python Journal>]>
|
||||
|
||||
Excluding a related item works as you would expect, too (although the SQL
|
||||
involved is a little complex)::
|
||||
involved is a little complex):
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Article.objects.exclude(publications=p2)
|
||||
<QuerySet [<Article: Django lets you build web apps easily>]>
|
||||
|
||||
If we delete a ``Publication``, its ``Articles`` won't be able to access it::
|
||||
If we delete a ``Publication``, its ``Articles`` won't be able to access it:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> p1.delete()
|
||||
>>> Publication.objects.all()
|
||||
@ -176,7 +205,9 @@ If we delete a ``Publication``, its ``Articles`` won't be able to access it::
|
||||
>>> a1.publications.all()
|
||||
<QuerySet []>
|
||||
|
||||
If we delete an ``Article``, its ``Publications`` won't be able to access it::
|
||||
If we delete an ``Article``, its ``Publications`` won't be able to access it:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> a2.delete()
|
||||
>>> Article.objects.all()
|
||||
@ -184,7 +215,9 @@ If we delete an ``Article``, its ``Publications`` won't be able to access it::
|
||||
>>> p2.article_set.all()
|
||||
<QuerySet []>
|
||||
|
||||
Adding via the 'other' end of an m2m::
|
||||
Adding via the 'other' end of an m2m:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> a4 = Article(headline='NASA finds intelligent life on Earth')
|
||||
>>> a4.save()
|
||||
@ -194,7 +227,9 @@ Adding via the 'other' end of an m2m::
|
||||
>>> a4.publications.all()
|
||||
<QuerySet [<Publication: Science News>]>
|
||||
|
||||
Adding via the other end using keywords::
|
||||
Adding via the other end using keywords:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> new_article = p2.article_set.create(headline='Oxygen-free diet works wonders')
|
||||
>>> p2.article_set.all()
|
||||
@ -203,7 +238,9 @@ Adding via the other end using keywords::
|
||||
>>> a5.publications.all()
|
||||
<QuerySet [<Publication: Science News>]>
|
||||
|
||||
Removing ``Publication`` from an ``Article``::
|
||||
Removing ``Publication`` from an ``Article``:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> a4.publications.remove(p2)
|
||||
>>> p2.article_set.all()
|
||||
@ -211,7 +248,9 @@ Removing ``Publication`` from an ``Article``::
|
||||
>>> a4.publications.all()
|
||||
<QuerySet []>
|
||||
|
||||
And from the other end::
|
||||
And from the other end:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> p2.article_set.remove(a5)
|
||||
>>> p2.article_set.all()
|
||||
@ -219,7 +258,9 @@ And from the other end::
|
||||
>>> a5.publications.all()
|
||||
<QuerySet []>
|
||||
|
||||
Relation sets can be set::
|
||||
Relation sets can be set:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> a4.publications.all()
|
||||
<QuerySet [<Publication: Science News>]>
|
||||
@ -227,13 +268,17 @@ Relation sets can be set::
|
||||
>>> a4.publications.all()
|
||||
<QuerySet [<Publication: Science Weekly>]>
|
||||
|
||||
Relation sets can be cleared::
|
||||
Relation sets can be cleared:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> p2.article_set.clear()
|
||||
>>> p2.article_set.all()
|
||||
<QuerySet []>
|
||||
|
||||
And you can clear from the other end::
|
||||
And you can clear from the other end:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> p2.article_set.add(a4, a5)
|
||||
>>> p2.article_set.all()
|
||||
@ -246,7 +291,9 @@ And you can clear from the other end::
|
||||
>>> p2.article_set.all()
|
||||
<QuerySet [<Article: Oxygen-free diet works wonders>]>
|
||||
|
||||
Recreate the ``Article`` and ``Publication`` we have deleted::
|
||||
Recreate the ``Article`` and ``Publication`` we have deleted:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> p1 = Publication(title='The Python Journal')
|
||||
>>> p1.save()
|
||||
@ -255,7 +302,9 @@ Recreate the ``Article`` and ``Publication`` we have deleted::
|
||||
>>> a2.publications.add(p1, p2, p3)
|
||||
|
||||
Bulk delete some ``Publications`` - references to deleted publications should
|
||||
go::
|
||||
go:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Publication.objects.filter(title__startswith='Science').delete()
|
||||
>>> Publication.objects.all()
|
||||
@ -265,7 +314,9 @@ go::
|
||||
>>> a2.publications.all()
|
||||
<QuerySet [<Publication: The Python Journal>]>
|
||||
|
||||
Bulk delete some articles - references to deleted objects should go::
|
||||
Bulk delete some articles - references to deleted objects should go:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> q = Article.objects.filter(headline__startswith='Django')
|
||||
>>> print(q)
|
||||
@ -274,7 +325,9 @@ Bulk delete some articles - references to deleted objects should go::
|
||||
|
||||
After the :meth:`~django.db.models.query.QuerySet.delete`, the
|
||||
:class:`~django.db.models.query.QuerySet` cache needs to be cleared, and the
|
||||
referenced objects should be gone::
|
||||
referenced objects should be gone:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> print(q)
|
||||
<QuerySet []>
|
||||
|
@ -31,9 +31,9 @@ objects, but an ``Article`` can only have one ``Reporter`` object::
|
||||
What follows are examples of operations that can be performed using the Python
|
||||
API facilities.
|
||||
|
||||
.. highlight:: pycon
|
||||
Create a few Reporters:
|
||||
|
||||
Create a few Reporters::
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> r = Reporter(first_name='John', last_name='Smith', email='john@example.com')
|
||||
>>> r.save()
|
||||
@ -41,7 +41,9 @@ Create a few Reporters::
|
||||
>>> r2 = Reporter(first_name='Paul', last_name='Jones', email='paul@example.com')
|
||||
>>> r2.save()
|
||||
|
||||
Create an Article::
|
||||
Create an Article:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from datetime import date
|
||||
>>> a = Article(id=None, headline="This is a test", pub_date=date(2005, 7, 27), reporter=r)
|
||||
@ -55,7 +57,9 @@ Create an Article::
|
||||
|
||||
Note that you must save an object before it can be assigned to a foreign key
|
||||
relationship. For example, creating an ``Article`` with unsaved ``Reporter``
|
||||
raises ``ValueError``::
|
||||
raises ``ValueError``:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> r3 = Reporter(first_name='John', last_name='Smith', email='john@example.com')
|
||||
>>> Article.objects.create(headline="This is a test", pub_date=date(2005, 7, 27), reporter=r3)
|
||||
@ -63,11 +67,15 @@ raises ``ValueError``::
|
||||
...
|
||||
ValueError: save() prohibited to prevent data loss due to unsaved related object 'reporter'.
|
||||
|
||||
Article objects have access to their related Reporter objects::
|
||||
Article objects have access to their related Reporter objects:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> r = a.reporter
|
||||
|
||||
Create an Article via the Reporter object::
|
||||
Create an Article via the Reporter object:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> new_article = r.article_set.create(headline="John's second story", pub_date=date(2005, 7, 29))
|
||||
>>> new_article
|
||||
@ -77,7 +85,9 @@ Create an Article via the Reporter object::
|
||||
>>> new_article.reporter.id
|
||||
1
|
||||
|
||||
Create a new article::
|
||||
Create a new article:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> new_article2 = Article.objects.create(headline="Paul's story", pub_date=date(2006, 1, 17), reporter=r)
|
||||
>>> new_article2.reporter
|
||||
@ -87,7 +97,9 @@ Create a new article::
|
||||
>>> r.article_set.all()
|
||||
<QuerySet [<Article: John's second story>, <Article: Paul's story>, <Article: This is a test>]>
|
||||
|
||||
Add the same article to a different article set - check that it moves::
|
||||
Add the same article to a different article set - check that it moves:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> r2.article_set.add(new_article2)
|
||||
>>> new_article2.reporter.id
|
||||
@ -95,7 +107,9 @@ Add the same article to a different article set - check that it moves::
|
||||
>>> new_article2.reporter
|
||||
<Reporter: Paul Jones>
|
||||
|
||||
Adding an object of the wrong type raises TypeError::
|
||||
Adding an object of the wrong type raises TypeError:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> r.article_set.add(r2)
|
||||
Traceback (most recent call last):
|
||||
@ -118,7 +132,9 @@ Note that in the last example the article has moved from John to Paul.
|
||||
Related managers support field lookups as well.
|
||||
The API automatically follows relationships as far as you need.
|
||||
Use double underscores to separate relationships.
|
||||
This works as many levels deep as you want. There's no limit. For example::
|
||||
This works as many levels deep as you want. There's no limit. For example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> r.article_set.filter(headline__startswith='This')
|
||||
<QuerySet [<Article: This is a test>]>
|
||||
@ -127,19 +143,25 @@ This works as many levels deep as you want. There's no limit. For example::
|
||||
>>> Article.objects.filter(reporter__first_name='John')
|
||||
<QuerySet [<Article: John's second story>, <Article: This is a test>]>
|
||||
|
||||
Exact match is implied here::
|
||||
Exact match is implied here:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Article.objects.filter(reporter__first_name='John')
|
||||
<QuerySet [<Article: John's second story>, <Article: This is a test>]>
|
||||
|
||||
Query twice over the related field. This translates to an AND condition in the
|
||||
WHERE clause::
|
||||
WHERE clause:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Article.objects.filter(reporter__first_name='John', reporter__last_name='Smith')
|
||||
<QuerySet [<Article: John's second story>, <Article: This is a test>]>
|
||||
|
||||
For the related lookup you can supply a primary key value or pass the related
|
||||
object explicitly::
|
||||
object explicitly:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Article.objects.filter(reporter__pk=1)
|
||||
<QuerySet [<Article: John's second story>, <Article: This is a test>]>
|
||||
@ -153,12 +175,16 @@ object explicitly::
|
||||
>>> Article.objects.filter(reporter__in=[r,r2]).distinct()
|
||||
<QuerySet [<Article: John's second story>, <Article: Paul's story>, <Article: This is a test>]>
|
||||
|
||||
You can also use a queryset instead of a literal list of instances::
|
||||
You can also use a queryset instead of a literal list of instances:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Article.objects.filter(reporter__in=Reporter.objects.filter(first_name='John')).distinct()
|
||||
<QuerySet [<Article: John's second story>, <Article: This is a test>]>
|
||||
|
||||
Querying in the opposite direction::
|
||||
Querying in the opposite direction:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Reporter.objects.filter(article__pk=1)
|
||||
<QuerySet [<Reporter: John Smith>]>
|
||||
@ -172,14 +198,18 @@ Querying in the opposite direction::
|
||||
>>> Reporter.objects.filter(article__headline__startswith='This').distinct()
|
||||
<QuerySet [<Reporter: John Smith>]>
|
||||
|
||||
Counting in the opposite direction works in conjunction with ``distinct()``::
|
||||
Counting in the opposite direction works in conjunction with ``distinct()``:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Reporter.objects.filter(article__headline__startswith='This').count()
|
||||
3
|
||||
>>> Reporter.objects.filter(article__headline__startswith='This').distinct().count()
|
||||
1
|
||||
|
||||
Queries can go round in circles::
|
||||
Queries can go round in circles:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Reporter.objects.filter(article__reporter__first_name__startswith='John')
|
||||
<QuerySet [<Reporter: John Smith>, <Reporter: John Smith>, <Reporter: John Smith>, <Reporter: John Smith>]>
|
||||
@ -190,7 +220,9 @@ Queries can go round in circles::
|
||||
|
||||
If you delete a reporter, their articles will be deleted (assuming that the
|
||||
ForeignKey was defined with :attr:`django.db.models.ForeignKey.on_delete` set to
|
||||
``CASCADE``, which is the default)::
|
||||
``CASCADE``, which is the default):
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Article.objects.all()
|
||||
<QuerySet [<Article: John's second story>, <Article: Paul's story>, <Article: This is a test>]>
|
||||
@ -202,7 +234,9 @@ ForeignKey was defined with :attr:`django.db.models.ForeignKey.on_delete` set to
|
||||
>>> Reporter.objects.order_by('first_name')
|
||||
<QuerySet [<Reporter: John Smith>]>
|
||||
|
||||
You can delete using a JOIN in the query::
|
||||
You can delete using a JOIN in the query:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Reporter.objects.filter(article__headline__startswith='This').delete()
|
||||
>>> Reporter.objects.all()
|
||||
|
@ -38,31 +38,39 @@ In this example, a ``Place`` optionally can be a ``Restaurant``::
|
||||
What follows are examples of operations that can be performed using the Python
|
||||
API facilities.
|
||||
|
||||
.. highlight:: pycon
|
||||
Create a couple of Places:
|
||||
|
||||
Create a couple of Places::
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> p1 = Place(name='Demon Dogs', address='944 W. Fullerton')
|
||||
>>> p1.save()
|
||||
>>> p2 = Place(name='Ace Hardware', address='1013 N. Ashland')
|
||||
>>> p2.save()
|
||||
|
||||
Create a Restaurant. Pass the "parent" object as this object's primary key::
|
||||
Create a Restaurant. Pass the "parent" object as this object's primary key:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> r = Restaurant(place=p1, serves_hot_dogs=True, serves_pizza=False)
|
||||
>>> r.save()
|
||||
|
||||
A Restaurant can access its place::
|
||||
A Restaurant can access its place:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> r.place
|
||||
<Place: Demon Dogs the place>
|
||||
|
||||
A Place can access its restaurant, if available::
|
||||
A Place can access its restaurant, if available:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> p1.restaurant
|
||||
<Restaurant: Demon Dogs the restaurant>
|
||||
|
||||
p2 doesn't have an associated restaurant::
|
||||
p2 doesn't have an associated restaurant:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.core.exceptions import ObjectDoesNotExist
|
||||
>>> try:
|
||||
@ -71,13 +79,17 @@ p2 doesn't have an associated restaurant::
|
||||
>>> print("There is no restaurant here.")
|
||||
There is no restaurant here.
|
||||
|
||||
You can also use ``hasattr`` to avoid the need for exception catching::
|
||||
You can also use ``hasattr`` to avoid the need for exception catching:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> hasattr(p2, 'restaurant')
|
||||
False
|
||||
|
||||
Set the place using assignment notation. Because place is the primary key on
|
||||
Restaurant, the save will create a new restaurant::
|
||||
Restaurant, the save will create a new restaurant:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> r.place = p2
|
||||
>>> r.save()
|
||||
@ -86,7 +98,9 @@ Restaurant, the save will create a new restaurant::
|
||||
>>> r.place
|
||||
<Place: Ace Hardware the place>
|
||||
|
||||
Set the place back again, using assignment in the reverse direction::
|
||||
Set the place back again, using assignment in the reverse direction:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> p1.restaurant = r
|
||||
>>> p1.restaurant
|
||||
@ -94,7 +108,9 @@ Set the place back again, using assignment in the reverse direction::
|
||||
|
||||
Note that you must save an object before it can be assigned to a one-to-one
|
||||
relationship. For example, creating a ``Restaurant`` with unsaved ``Place``
|
||||
raises ``ValueError``::
|
||||
raises ``ValueError``:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> p3 = Place(name='Demon Dogs', address='944 W. Fullerton')
|
||||
>>> Restaurant.objects.create(place=p3, serves_hot_dogs=True, serves_pizza=False)
|
||||
@ -104,18 +120,24 @@ raises ``ValueError``::
|
||||
|
||||
Restaurant.objects.all() returns the Restaurants, not the Places. Note that
|
||||
there are two restaurants - Ace Hardware the Restaurant was created in the call
|
||||
to r.place = p2::
|
||||
to r.place = p2:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Restaurant.objects.all()
|
||||
<QuerySet [<Restaurant: Demon Dogs the restaurant>, <Restaurant: Ace Hardware the restaurant>]>
|
||||
|
||||
Place.objects.all() returns all Places, regardless of whether they have
|
||||
Restaurants::
|
||||
Restaurants:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Place.objects.order_by('name')
|
||||
<QuerySet [<Place: Ace Hardware the place>, <Place: Demon Dogs the place>]>
|
||||
|
||||
You can query the models using :ref:`lookups across relationships <lookups-that-span-relationships>`::
|
||||
You can query the models using :ref:`lookups across relationships <lookups-that-span-relationships>`:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Restaurant.objects.get(place=p1)
|
||||
<Restaurant: Demon Dogs the restaurant>
|
||||
@ -126,7 +148,9 @@ You can query the models using :ref:`lookups across relationships <lookups-that-
|
||||
>>> Restaurant.objects.exclude(place__address__contains="Ashland")
|
||||
<QuerySet [<Restaurant: Demon Dogs the restaurant>]>
|
||||
|
||||
This also works in reverse::
|
||||
This also works in reverse:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Place.objects.get(pk=1)
|
||||
<Place: Demon Dogs the place>
|
||||
@ -140,20 +164,26 @@ This also works in reverse::
|
||||
If you delete a place, its restaurant will be deleted (assuming that the
|
||||
``OneToOneField`` was defined with
|
||||
:attr:`~django.db.models.ForeignKey.on_delete` set to ``CASCADE``, which is the
|
||||
default)::
|
||||
default):
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> p2.delete()
|
||||
(2, {'one_to_one.Restaurant': 1, 'one_to_one.Place': 1})
|
||||
>>> Restaurant.objects.all()
|
||||
<QuerySet [<Restaurant: Demon Dogs the restaurant>]>
|
||||
|
||||
Add a Waiter to the Restaurant::
|
||||
Add a Waiter to the Restaurant:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> w = r.waiter_set.create(name='Joe')
|
||||
>>> w
|
||||
<Waiter: Joe the waiter at Demon Dogs the restaurant>
|
||||
|
||||
Query the waiters::
|
||||
Query the waiters:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Waiter.objects.filter(restaurant__place=p1)
|
||||
<QuerySet [<Waiter: Joe the waiter at Demon Dogs the restaurant>]>
|
||||
|
@ -43,7 +43,9 @@ Django will load any and all fixtures it finds in these locations that match
|
||||
the provided fixture names.
|
||||
|
||||
If the named fixture has a file extension, only fixtures of that type
|
||||
will be loaded. For example::
|
||||
will be loaded. For example:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
django-admin loaddata mydata.json
|
||||
|
||||
@ -52,7 +54,9 @@ must correspond to the registered name of a
|
||||
:ref:`serializer <serialization-formats>` (e.g., ``json`` or ``xml``).
|
||||
|
||||
If you omit the extensions, Django will search all available fixture types
|
||||
for a matching fixture. For example::
|
||||
for a matching fixture. For example:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
django-admin loaddata mydata
|
||||
|
||||
@ -61,7 +65,9 @@ directory contained ``mydata.json``, that fixture would be loaded
|
||||
as a JSON fixture.
|
||||
|
||||
The fixtures that are named can include directory components. These
|
||||
directories will be included in the search path. For example::
|
||||
directories will be included in the search path. For example:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
django-admin loaddata foo/bar/mydata.json
|
||||
|
||||
@ -124,7 +130,9 @@ Compressed fixtures
|
||||
===================
|
||||
|
||||
Fixtures may be compressed in ``zip``, ``gz``, ``bz2``, ``lzma``, or ``xz``
|
||||
format. For example::
|
||||
format. For example:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
django-admin loaddata mydata.json
|
||||
|
||||
|
@ -425,7 +425,9 @@ Implementation concerns
|
||||
|
||||
Whatever features you add to your custom ``Manager``, it must be
|
||||
possible to make a shallow copy of a ``Manager`` instance; i.e., the
|
||||
following code must work::
|
||||
following code must work:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> import copy
|
||||
>>> manager = MyManager()
|
||||
|
@ -189,7 +189,7 @@ ones:
|
||||
name = models.CharField(max_length=60)
|
||||
shirt_size = models.CharField(max_length=1, choices=SHIRT_SIZES)
|
||||
|
||||
::
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> p = Person(name="Fred Flintstone", shirt_size="L")
|
||||
>>> p.save()
|
||||
@ -503,7 +503,9 @@ There are a few restrictions on the intermediate model:
|
||||
Now that you have set up your :class:`~django.db.models.ManyToManyField` to use
|
||||
your intermediary model (``Membership``, in this case), you're ready to start
|
||||
creating some many-to-many relationships. You do this by creating instances of
|
||||
the intermediate model::
|
||||
the intermediate model:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> ringo = Person.objects.create(name="Ringo Starr")
|
||||
>>> paul = Person.objects.create(name="Paul McCartney")
|
||||
@ -526,7 +528,9 @@ You can also use :meth:`~django.db.models.fields.related.RelatedManager.add`,
|
||||
:meth:`~django.db.models.fields.related.RelatedManager.create`, or
|
||||
:meth:`~django.db.models.fields.related.RelatedManager.set` to create
|
||||
relationships, as long as you specify ``through_defaults`` for any required
|
||||
fields::
|
||||
fields:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> beatles.members.add(john, through_defaults={'date_joined': date(1960, 8, 1)})
|
||||
>>> beatles.members.create(name="George Harrison", through_defaults={'date_joined': date(1960, 8, 1)})
|
||||
@ -537,7 +541,9 @@ You may prefer to create instances of the intermediate model directly.
|
||||
If the custom through table defined by the intermediate model does not enforce
|
||||
uniqueness on the ``(model1, model2)`` pair, allowing multiple values, the
|
||||
:meth:`~django.db.models.fields.related.RelatedManager.remove` call will
|
||||
remove all intermediate model instances::
|
||||
remove all intermediate model instances:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Membership.objects.create(person=ringo, group=beatles,
|
||||
... date_joined=date(1968, 9, 4),
|
||||
@ -550,7 +556,9 @@ remove all intermediate model instances::
|
||||
<QuerySet [<Person: Paul McCartney>]>
|
||||
|
||||
The :meth:`~django.db.models.fields.related.RelatedManager.clear`
|
||||
method can be used to remove all many-to-many relationships for an instance::
|
||||
method can be used to remove all many-to-many relationships for an instance:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> # Beatles have broken up
|
||||
>>> beatles.members.clear()
|
||||
@ -560,13 +568,17 @@ method can be used to remove all many-to-many relationships for an instance::
|
||||
|
||||
Once you have established the many-to-many relationships, you can issue
|
||||
queries. Just as with normal many-to-many relationships, you can query using
|
||||
the attributes of the many-to-many-related model::
|
||||
the attributes of the many-to-many-related model:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
# Find all the groups with a member whose name starts with 'Paul'
|
||||
>>> Group.objects.filter(members__name__startswith='Paul')
|
||||
<QuerySet [<Group: The Beatles>]>
|
||||
|
||||
As you are using an intermediate model, you can also query on its attributes::
|
||||
As you are using an intermediate model, you can also query on its attributes:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
# Find all the members of the Beatles that joined after 1 Jan 1961
|
||||
>>> Person.objects.filter(
|
||||
@ -575,7 +587,9 @@ As you are using an intermediate model, you can also query on its attributes::
|
||||
<QuerySet [<Person: Ringo Starr]>
|
||||
|
||||
If you need to access a membership's information you may do so by directly
|
||||
querying the ``Membership`` model::
|
||||
querying the ``Membership`` model:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> ringos_membership = Membership.objects.get(group=beatles, person=ringo)
|
||||
>>> ringos_membership.date_joined
|
||||
@ -585,7 +599,9 @@ querying the ``Membership`` model::
|
||||
|
||||
Another way to access the same information is by querying the
|
||||
:ref:`many-to-many reverse relationship<m2m-reverse-relationships>` from a
|
||||
``Person`` object::
|
||||
``Person`` object:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> ringos_membership = ringo.membership_set.get(group=beatles)
|
||||
>>> ringos_membership.date_joined
|
||||
@ -1120,14 +1136,18 @@ For example::
|
||||
|
||||
All of the fields of ``Place`` will also be available in ``Restaurant``,
|
||||
although the data will reside in a different database table. So these are both
|
||||
possible::
|
||||
possible:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Place.objects.filter(name="Bob's Cafe")
|
||||
>>> Restaurant.objects.filter(name="Bob's Cafe")
|
||||
|
||||
If you have a ``Place`` that is also a ``Restaurant``, you can get from the
|
||||
``Place`` object to the ``Restaurant`` object by using the lowercase version of
|
||||
the model name::
|
||||
the model name:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> p = Place.objects.get(id=12)
|
||||
# If p is a Restaurant object, this will give the child class:
|
||||
@ -1264,7 +1284,9 @@ For example, suppose you want to add a method to the ``Person`` model. You can d
|
||||
|
||||
The ``MyPerson`` class operates on the same database table as its parent
|
||||
``Person`` class. In particular, any new instances of ``Person`` will also be
|
||||
accessible through ``MyPerson``, and vice-versa::
|
||||
accessible through ``MyPerson``, and vice-versa:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> p = Person.objects.create(first_name="foobar")
|
||||
>>> MyPerson.objects.get(first_name="foobar")
|
||||
|
@ -85,7 +85,9 @@ The :djadmin:`migrate` management command operates on one database at a
|
||||
time. By default, it operates on the ``default`` database, but by
|
||||
providing the :option:`--database <migrate --database>` option, you can tell it
|
||||
to synchronize a different database. So, to synchronize all models onto
|
||||
all databases in the first example above, you would need to call::
|
||||
all databases in the first example above, you would need to call:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
$ ./manage.py migrate
|
||||
$ ./manage.py migrate --database=users
|
||||
@ -97,7 +99,9 @@ constraining the availability of particular models.
|
||||
|
||||
If, as in the second example above, you've left the ``default`` database empty,
|
||||
you must provide a database name each time you run :djadmin:`migrate`. Omitting
|
||||
the database name would raise an error. For the second example::
|
||||
the database name would raise an error. For the second example:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
$ ./manage.py migrate --database=users
|
||||
$ ./manage.py migrate --database=customers
|
||||
@ -405,7 +409,9 @@ catch-all nature of the PrimaryReplicaRouter implementation would mean
|
||||
that all models would be available on all databases.
|
||||
|
||||
With this setup installed, and all databases migrated as per
|
||||
:ref:`synchronizing_multiple_databases`, lets run some Django code::
|
||||
:ref:`synchronizing_multiple_databases`, lets run some Django code:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> # This retrieval will be performed on the 'auth_db' database
|
||||
>>> fred = User.objects.get(username='fred')
|
||||
@ -453,7 +459,9 @@ You can select the database for a ``QuerySet`` at any point in the
|
||||
``QuerySet`` that uses the specified database.
|
||||
|
||||
``using()`` takes a single argument: the alias of the database on
|
||||
which you want to run the query. For example::
|
||||
which you want to run the query. For example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> # This will run on the 'default' database.
|
||||
>>> Author.objects.all()
|
||||
@ -471,7 +479,9 @@ Use the ``using`` keyword to ``Model.save()`` to specify to which
|
||||
database the data should be saved.
|
||||
|
||||
For example, to save an object to the ``legacy_users`` database, you'd
|
||||
use this::
|
||||
use this:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> my_object.save(using='legacy_users')
|
||||
|
||||
@ -486,7 +496,9 @@ use ``save(using=...)`` as a way to migrate the instance to a new
|
||||
database. However, if you don't take appropriate steps, this could
|
||||
have some unexpected consequences.
|
||||
|
||||
Consider the following example::
|
||||
Consider the following example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> p = Person(name='Fred')
|
||||
>>> p.save(using='first') # (statement 1)
|
||||
@ -510,7 +522,9 @@ will be overridden when ``p`` is saved.
|
||||
You can avoid this in two ways. First, you can clear the primary key
|
||||
of the instance. If an object has no primary key, Django will treat it
|
||||
as a new object, avoiding any loss of data on the ``second``
|
||||
database::
|
||||
database:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> p = Person(name='Fred')
|
||||
>>> p.save(using='first')
|
||||
@ -518,7 +532,9 @@ database::
|
||||
>>> p.save(using='second') # Write a completely new object.
|
||||
|
||||
The second option is to use the ``force_insert`` option to ``save()``
|
||||
to ensure that Django does an SQL ``INSERT``::
|
||||
to ensure that Django does an SQL ``INSERT``:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> p = Person(name='Fred')
|
||||
>>> p.save(using='first')
|
||||
@ -534,7 +550,9 @@ Selecting a database to delete from
|
||||
|
||||
By default, a call to delete an existing object will be executed on
|
||||
the same database that was used to retrieve the object in the first
|
||||
place::
|
||||
place:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> u = User.objects.using('legacy_users').get(username='fred')
|
||||
>>> u.delete() # will delete from the `legacy_users` database
|
||||
@ -544,7 +562,9 @@ To specify the database from which a model will be deleted, pass a
|
||||
argument works just like the ``using`` keyword argument to ``save()``.
|
||||
|
||||
For example, if you're migrating a user from the ``legacy_users``
|
||||
database to the ``new_users`` database, you might use these commands::
|
||||
database to the ``new_users`` database, you might use these commands:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> user_obj.save(using='new_users')
|
||||
>>> user_obj.delete(using='legacy_users')
|
||||
|
@ -82,13 +82,17 @@ Understand cached attributes
|
||||
As well as caching of the whole ``QuerySet``, there is caching of the result of
|
||||
attributes on ORM objects. In general, attributes that are not callable will be
|
||||
cached. For example, assuming the :ref:`example blog models
|
||||
<queryset-model-example>`::
|
||||
<queryset-model-example>`:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> entry = Entry.objects.get(id=1)
|
||||
>>> entry.blog # Blog object is retrieved at this point
|
||||
>>> entry.blog # cached version, no DB access
|
||||
|
||||
But in general, callable attributes cause DB lookups every time::
|
||||
But in general, callable attributes cause DB lookups every time:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> entry = Entry.objects.get(id=1)
|
||||
>>> entry.authors.all() # query performed
|
||||
@ -164,18 +168,24 @@ First, the query will be quicker because of the underlying database index.
|
||||
Also, the query could run much slower if multiple objects match the lookup;
|
||||
having a unique constraint on the column guarantees this will never happen.
|
||||
|
||||
So using the :ref:`example blog models <queryset-model-example>`::
|
||||
So using the :ref:`example blog models <queryset-model-example>`:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> entry = Entry.objects.get(id=10)
|
||||
|
||||
will be quicker than:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> entry = Entry.objects.get(headline="News Item Title")
|
||||
|
||||
because ``id`` is indexed by the database and is guaranteed to be unique.
|
||||
|
||||
Doing the following is potentially quite slow:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> entry = Entry.objects.get(headline__startswith="News")
|
||||
|
||||
First of all, ``headline`` is not indexed, which will make the underlying
|
||||
|
@ -59,7 +59,9 @@ class represents a particular record in the database table.
|
||||
To create an object, instantiate it using keyword arguments to the model class,
|
||||
then call :meth:`~django.db.models.Model.save` to save it to the database.
|
||||
|
||||
Assuming models live in a file ``mysite/blog/models.py``, here's an example::
|
||||
Assuming models live in a file ``mysite/blog/models.py``, here's an example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from blog.models import Blog
|
||||
>>> b = Blog(name='Beatles Blog', tagline='All the latest Beatles news.')
|
||||
@ -86,7 +88,9 @@ To save changes to an object that's already in the database, use
|
||||
:meth:`~django.db.models.Model.save`.
|
||||
|
||||
Given a ``Blog`` instance ``b5`` that has already been saved to the database,
|
||||
this example changes its name and updates its record in the database::
|
||||
this example changes its name and updates its record in the database:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> b5.name = 'New name'
|
||||
>>> b5.save()
|
||||
@ -101,7 +105,9 @@ Updating a :class:`~django.db.models.ForeignKey` field works exactly the same
|
||||
way as saving a normal field -- assign an object of the right type to the field
|
||||
in question. This example updates the ``blog`` attribute of an ``Entry``
|
||||
instance ``entry``, assuming appropriate instances of ``Entry`` and ``Blog``
|
||||
are already saved to the database (so we can retrieve them below)::
|
||||
are already saved to the database (so we can retrieve them below):
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from blog.models import Blog, Entry
|
||||
>>> entry = Entry.objects.get(pk=1)
|
||||
@ -113,7 +119,9 @@ Updating a :class:`~django.db.models.ManyToManyField` works a little
|
||||
differently -- use the
|
||||
:meth:`~django.db.models.fields.related.RelatedManager.add` method on the field
|
||||
to add a record to the relation. This example adds the ``Author`` instance
|
||||
``joe`` to the ``entry`` object::
|
||||
``joe`` to the ``entry`` object:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from blog.models import Author
|
||||
>>> joe = Author.objects.create(name="Joe")
|
||||
@ -121,7 +129,9 @@ to add a record to the relation. This example adds the ``Author`` instance
|
||||
|
||||
To add multiple records to a :class:`~django.db.models.ManyToManyField` in one
|
||||
go, include multiple arguments in the call to
|
||||
:meth:`~django.db.models.fields.related.RelatedManager.add`, like this::
|
||||
:meth:`~django.db.models.fields.related.RelatedManager.add`, like this:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> john = Author.objects.create(name="John")
|
||||
>>> paul = Author.objects.create(name="Paul")
|
||||
@ -150,7 +160,9 @@ You get a :class:`~django.db.models.query.QuerySet` by using your model's
|
||||
:class:`~django.db.models.Manager`. Each model has at least one
|
||||
:class:`~django.db.models.Manager`, and it's called
|
||||
:attr:`~django.db.models.Model.objects` by default. Access it directly via the
|
||||
model class, like so::
|
||||
model class, like so:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Blog.objects
|
||||
<django.db.models.manager.Manager object at ...>
|
||||
@ -176,7 +188,9 @@ Retrieving all objects
|
||||
|
||||
The simplest way to retrieve objects from a table is to get all of them. To do
|
||||
this, use the :meth:`~django.db.models.query.QuerySet.all` method on a
|
||||
:class:`~django.db.models.Manager`::
|
||||
:class:`~django.db.models.Manager`:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> all_entries = Entry.objects.all()
|
||||
|
||||
@ -223,7 +237,9 @@ Chaining filters
|
||||
|
||||
The result of refining a :class:`~django.db.models.query.QuerySet` is itself a
|
||||
:class:`~django.db.models.query.QuerySet`, so it's possible to chain
|
||||
refinements together. For example::
|
||||
refinements together. For example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Entry.objects.filter(
|
||||
... headline__startswith='What'
|
||||
@ -250,7 +266,9 @@ the previous :class:`~django.db.models.query.QuerySet`. Each refinement creates
|
||||
a separate and distinct :class:`~django.db.models.query.QuerySet` that can be
|
||||
stored, used and reused.
|
||||
|
||||
Example::
|
||||
Example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> q1 = Entry.objects.filter(headline__startswith="What")
|
||||
>>> q2 = q1.exclude(pub_date__gte=datetime.date.today())
|
||||
@ -274,7 +292,9 @@ refinement process.
|
||||
:class:`~django.db.models.query.QuerySet` doesn't involve any database
|
||||
activity. You can stack filters together all day long, and Django won't
|
||||
actually run the query until the :class:`~django.db.models.query.QuerySet` is
|
||||
*evaluated*. Take a look at this example::
|
||||
*evaluated*. Take a look at this example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> q = Entry.objects.filter(headline__startswith="What")
|
||||
>>> q = q.filter(pub_date__lte=datetime.date.today())
|
||||
@ -301,7 +321,9 @@ the query - in this case, it will be a
|
||||
|
||||
If you know there is only one object that matches your query, you can use the
|
||||
:meth:`~django.db.models.query.QuerySet.get` method on a
|
||||
:class:`~django.db.models.Manager` which returns the object directly::
|
||||
:class:`~django.db.models.Manager` which returns the object directly:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> one_entry = Entry.objects.get(pk=1)
|
||||
|
||||
@ -345,11 +367,15 @@ Use a subset of Python's array-slicing syntax to limit your
|
||||
:class:`~django.db.models.query.QuerySet` to a certain number of results. This
|
||||
is the equivalent of SQL's ``LIMIT`` and ``OFFSET`` clauses.
|
||||
|
||||
For example, this returns the first 5 objects (``LIMIT 5``)::
|
||||
For example, this returns the first 5 objects (``LIMIT 5``):
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Entry.objects.all()[:5]
|
||||
|
||||
This returns the sixth through tenth objects (``OFFSET 5 LIMIT 5``)::
|
||||
This returns the sixth through tenth objects (``OFFSET 5 LIMIT 5``):
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Entry.objects.all()[5:10]
|
||||
|
||||
@ -359,7 +385,9 @@ Generally, slicing a :class:`~django.db.models.query.QuerySet` returns a new
|
||||
:class:`~django.db.models.query.QuerySet` -- it doesn't evaluate the query. An
|
||||
exception is if you use the "step" parameter of Python slice syntax. For
|
||||
example, this would actually execute the query in order to return a list of
|
||||
every *second* object of the first 10::
|
||||
every *second* object of the first 10:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Entry.objects.all()[:10:2]
|
||||
|
||||
@ -369,11 +397,15 @@ ambiguous nature of how that might work.
|
||||
To retrieve a *single* object rather than a list
|
||||
(e.g. ``SELECT foo FROM bar LIMIT 1``), use an index instead of a slice. For
|
||||
example, this returns the first ``Entry`` in the database, after ordering
|
||||
entries alphabetically by headline::
|
||||
entries alphabetically by headline:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Entry.objects.order_by('headline')[0]
|
||||
|
||||
This is roughly equivalent to::
|
||||
This is roughly equivalent to:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Entry.objects.order_by('headline')[0:1].get()
|
||||
|
||||
@ -393,7 +425,9 @@ methods :meth:`~django.db.models.query.QuerySet.filter`,
|
||||
:meth:`~django.db.models.query.QuerySet.get`.
|
||||
|
||||
Basic lookups keyword arguments take the form ``field__lookuptype=value``.
|
||||
(That's a double-underscore). For example::
|
||||
(That's a double-underscore). For example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Entry.objects.filter(pub_date__lte='2006-01-01')
|
||||
|
||||
@ -426,7 +460,9 @@ a taste of what's available, here's some of the more common lookups you'll
|
||||
probably use:
|
||||
|
||||
:lookup:`exact`
|
||||
An "exact" match. For example::
|
||||
An "exact" match. For example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Entry.objects.get(headline__exact="Cat bites dog")
|
||||
|
||||
@ -440,7 +476,9 @@ probably use:
|
||||
doesn't contain a double underscore -- the lookup type is assumed to be
|
||||
``exact``.
|
||||
|
||||
For example, the following two statements are equivalent::
|
||||
For example, the following two statements are equivalent:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Blog.objects.get(id__exact=14) # Explicit form
|
||||
>>> Blog.objects.get(id=14) # __exact is implied
|
||||
@ -448,7 +486,9 @@ probably use:
|
||||
This is for convenience, because ``exact`` lookups are the common case.
|
||||
|
||||
:lookup:`iexact`
|
||||
A case-insensitive match. So, the query::
|
||||
A case-insensitive match. So, the query:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Blog.objects.get(name__iexact="beatles blog")
|
||||
|
||||
@ -491,7 +531,9 @@ across models, separated by double underscores, until you get to the field you
|
||||
want.
|
||||
|
||||
This example retrieves all ``Entry`` objects with a ``Blog`` whose ``name``
|
||||
is ``'Beatles Blog'``::
|
||||
is ``'Beatles Blog'``:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Entry.objects.filter(blog__name='Beatles Blog')
|
||||
|
||||
@ -502,7 +544,9 @@ It works backwards, too. While it :attr:`can be customized
|
||||
relationship in a lookup using the lowercase name of the model.
|
||||
|
||||
This example retrieves all ``Blog`` objects which have at least one ``Entry``
|
||||
whose ``headline`` contains ``'Lennon'``::
|
||||
whose ``headline`` contains ``'Lennon'``:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Blog.objects.filter(entry__headline__contains='Lennon')
|
||||
|
||||
@ -649,7 +693,9 @@ of two different fields on the same model instance.
|
||||
|
||||
For example, to find a list of all blog entries that have had more comments
|
||||
than pingbacks, we construct an ``F()`` object to reference the pingback count,
|
||||
and use that ``F()`` object in the query::
|
||||
and use that ``F()`` object in the query:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.db.models import F
|
||||
>>> Entry.objects.filter(number_of_comments__gt=F('number_of_pingbacks'))
|
||||
@ -657,13 +703,17 @@ and use that ``F()`` object in the query::
|
||||
Django supports the use of addition, subtraction, multiplication,
|
||||
division, modulo, and power arithmetic with ``F()`` objects, both with constants
|
||||
and with other ``F()`` objects. To find all the blog entries with more than
|
||||
*twice* as many comments as pingbacks, we modify the query::
|
||||
*twice* as many comments as pingbacks, we modify the query:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Entry.objects.filter(number_of_comments__gt=F('number_of_pingbacks') * 2)
|
||||
|
||||
To find all the entries where the rating of the entry is less than the
|
||||
sum of the pingback count and comment count, we would issue the
|
||||
query::
|
||||
query:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Entry.objects.filter(rating__lt=F('number_of_comments') + F('number_of_pingbacks'))
|
||||
|
||||
@ -671,19 +721,25 @@ You can also use the double underscore notation to span relationships in
|
||||
an ``F()`` object. An ``F()`` object with a double underscore will introduce
|
||||
any joins needed to access the related object. For example, to retrieve all
|
||||
the entries where the author's name is the same as the blog name, we could
|
||||
issue the query::
|
||||
issue the query:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Entry.objects.filter(authors__name=F('blog__name'))
|
||||
|
||||
For date and date/time fields, you can add or subtract a
|
||||
:class:`~datetime.timedelta` object. The following would return all entries
|
||||
that were modified more than 3 days after they were published::
|
||||
that were modified more than 3 days after they were published:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from datetime import timedelta
|
||||
>>> Entry.objects.filter(mod_date__gt=F('pub_date') + timedelta(days=3))
|
||||
|
||||
The ``F()`` objects support bitwise operations by ``.bitand()``, ``.bitor()``,
|
||||
``.bitxor()``, ``.bitrightshift()``, and ``.bitleftshift()``. For example::
|
||||
``.bitxor()``, ``.bitrightshift()``, and ``.bitleftshift()``. For example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> F('somefield').bitand(16)
|
||||
|
||||
@ -699,18 +755,24 @@ Expressions can reference transforms
|
||||
Django supports using transforms in expressions.
|
||||
|
||||
For example, to find all ``Entry`` objects published in the same year as they
|
||||
were last modified::
|
||||
were last modified:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.db.models import F
|
||||
>>> Entry.objects.filter(pub_date__year=F('mod_date__year'))
|
||||
|
||||
To find the earliest year an entry was published, we can issue the query::
|
||||
To find the earliest year an entry was published, we can issue the query:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.db.models import Min
|
||||
>>> Entry.objects.aggregate(first_published_year=Min('pub_date__year'))
|
||||
|
||||
This example finds the value of the highest rated entry and the total number
|
||||
of comments on all entries for each year::
|
||||
of comments on all entries for each year:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.db.models import OuterRef, Subquery, Sum
|
||||
>>> Entry.objects.values('pub_date__year').annotate(
|
||||
@ -729,14 +791,18 @@ For convenience, Django provides a ``pk`` lookup shortcut, which stands for
|
||||
"primary key".
|
||||
|
||||
In the example ``Blog`` model, the primary key is the ``id`` field, so these
|
||||
three statements are equivalent::
|
||||
three statements are equivalent:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Blog.objects.get(id__exact=14) # Explicit form
|
||||
>>> Blog.objects.get(id=14) # __exact is implied
|
||||
>>> Blog.objects.get(pk=14) # pk implies id__exact
|
||||
|
||||
The use of ``pk`` isn't limited to ``__exact`` queries -- any query term
|
||||
can be combined with ``pk`` to perform a query on the primary key of a model::
|
||||
can be combined with ``pk`` to perform a query on the primary key of a model:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
# Get blogs entries with id 1, 4 and 7
|
||||
>>> Blog.objects.filter(pk__in=[1,4,7])
|
||||
@ -745,7 +811,9 @@ can be combined with ``pk`` to perform a query on the primary key of a model::
|
||||
>>> Blog.objects.filter(pk__gt=14)
|
||||
|
||||
``pk`` lookups also work across joins. For example, these three statements are
|
||||
equivalent::
|
||||
equivalent:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Entry.objects.filter(blog__id__exact=3) # Explicit form
|
||||
>>> Entry.objects.filter(blog__id=3) # __exact is implied
|
||||
@ -763,7 +831,9 @@ underscore signifies a single-character wildcard.)
|
||||
|
||||
This means things should work intuitively, so the abstraction doesn't leak.
|
||||
For example, to retrieve all the entries that contain a percent sign, use the
|
||||
percent sign as any other character::
|
||||
percent sign as any other character:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Entry.objects.filter(headline__contains='%')
|
||||
|
||||
@ -798,7 +868,9 @@ results.
|
||||
Keep this caching behavior in mind, because it may bite you if you don't use
|
||||
your :class:`~django.db.models.query.QuerySet`\s correctly. For example, the
|
||||
following will create two :class:`~django.db.models.query.QuerySet`\s, evaluate
|
||||
them, and throw them away::
|
||||
them, and throw them away:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> print([e.headline for e in Entry.objects.all()])
|
||||
>>> print([e.pub_date for e in Entry.objects.all()])
|
||||
@ -809,7 +881,9 @@ the same database records, because an ``Entry`` may have been added or deleted
|
||||
in the split second between the two requests.
|
||||
|
||||
To avoid this problem, save the :class:`~django.db.models.query.QuerySet` and
|
||||
reuse it::
|
||||
reuse it:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> queryset = Entry.objects.all()
|
||||
>>> print([p.headline for p in queryset]) # Evaluate the query set.
|
||||
@ -825,14 +899,18 @@ returned by the subsequent query are not cached. Specifically, this means that
|
||||
index will not populate the cache.
|
||||
|
||||
For example, repeatedly getting a certain index in a queryset object will query
|
||||
the database each time::
|
||||
the database each time:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> queryset = Entry.objects.all()
|
||||
>>> print(queryset[5]) # Queries the database
|
||||
>>> print(queryset[5]) # Queries the database again
|
||||
|
||||
However, if the entire queryset has already been evaluated, the cache will be
|
||||
checked instead::
|
||||
checked instead:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> queryset = Entry.objects.all()
|
||||
>>> [entry for entry in queryset] # Queries the database
|
||||
@ -840,7 +918,9 @@ checked instead::
|
||||
>>> print(queryset[5]) # Uses cache
|
||||
|
||||
Here are some examples of other actions that will result in the entire queryset
|
||||
being evaluated and therefore populate the cache::
|
||||
being evaluated and therefore populate the cache:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> [entry for entry in queryset]
|
||||
>>> bool(queryset)
|
||||
@ -975,7 +1055,9 @@ is inside a :py:class:`list` or :py:class:`dict`, it will always be interpreted
|
||||
as JSON ``null``.
|
||||
|
||||
When querying, ``None`` value will always be interpreted as JSON ``null``. To
|
||||
query for SQL ``NULL``, use :lookup:`isnull`::
|
||||
query for SQL ``NULL``, use :lookup:`isnull`:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Dog.objects.create(name='Max', data=None) # SQL NULL.
|
||||
<Dog: Max>
|
||||
@ -1015,7 +1097,9 @@ Unless you are sure you wish to work with SQL ``NULL`` values, consider setting
|
||||
Key, index, and path transforms
|
||||
-------------------------------
|
||||
|
||||
To query based on a given dictionary key, use that key as the lookup name::
|
||||
To query based on a given dictionary key, use that key as the lookup name:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Dog.objects.create(name='Rufus', data={
|
||||
... 'breed': 'labrador',
|
||||
@ -1032,13 +1116,17 @@ To query based on a given dictionary key, use that key as the lookup name::
|
||||
>>> Dog.objects.filter(data__breed='collie')
|
||||
<QuerySet [<Dog: Meg>]>
|
||||
|
||||
Multiple keys can be chained together to form a path lookup::
|
||||
Multiple keys can be chained together to form a path lookup:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Dog.objects.filter(data__owner__name='Bob')
|
||||
<QuerySet [<Dog: Rufus>]>
|
||||
|
||||
If the key is an integer, it will be interpreted as an index transform in an
|
||||
array::
|
||||
array:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Dog.objects.filter(data__owner__other_pets__0__name='Fishy')
|
||||
<QuerySet [<Dog: Rufus>]>
|
||||
@ -1046,7 +1134,9 @@ array::
|
||||
If the key you wish to query by clashes with the name of another lookup, use
|
||||
the :lookup:`contains <jsonfield.contains>` lookup instead.
|
||||
|
||||
To query for missing keys, use the ``isnull`` lookup::
|
||||
To query for missing keys, use the ``isnull`` lookup:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Dog.objects.create(name='Shep', data={'breed': 'collie'})
|
||||
<Dog: Shep>
|
||||
@ -1075,7 +1165,9 @@ To query for missing keys, use the ``isnull`` lookup::
|
||||
:class:`~django.db.models.JSONField`. You can use the double underscore
|
||||
notation in ``lookup`` to chain dictionary key and index transforms.
|
||||
|
||||
For example::
|
||||
For example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.db.models.fields.json import KT
|
||||
>>> Dog.objects.create(name="Shep", data={
|
||||
@ -1142,7 +1234,9 @@ Containment and key lookups
|
||||
|
||||
The :lookup:`contains` lookup is overridden on ``JSONField``. The returned
|
||||
objects are those where the given ``dict`` of key-value pairs are all
|
||||
contained in the top-level of the field. For example::
|
||||
contained in the top-level of the field. For example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Dog.objects.create(name='Rufus', data={'breed': 'labrador', 'owner': 'Bob'})
|
||||
<Dog: Rufus>
|
||||
@ -1166,7 +1260,9 @@ contained in the top-level of the field. For example::
|
||||
|
||||
This is the inverse of the :lookup:`contains <jsonfield.contains>` lookup - the
|
||||
objects returned will be those where the key-value pairs on the object are a
|
||||
subset of those in the value passed. For example::
|
||||
subset of those in the value passed. For example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Dog.objects.create(name='Rufus', data={'breed': 'labrador', 'owner': 'Bob'})
|
||||
<Dog: Rufus>
|
||||
@ -1189,7 +1285,9 @@ subset of those in the value passed. For example::
|
||||
~~~~~~~~~~~
|
||||
|
||||
Returns objects where the given key is in the top-level of the data. For
|
||||
example::
|
||||
example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Dog.objects.create(name='Rufus', data={'breed': 'labrador'})
|
||||
<Dog: Rufus>
|
||||
@ -1204,7 +1302,9 @@ example::
|
||||
~~~~~~~~~~~~
|
||||
|
||||
Returns objects where all of the given keys are in the top-level of the data.
|
||||
For example::
|
||||
For example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Dog.objects.create(name='Rufus', data={'breed': 'labrador'})
|
||||
<Dog: Rufus>
|
||||
@ -1219,7 +1319,9 @@ For example::
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
Returns objects where any of the given keys are in the top-level of the data.
|
||||
For example::
|
||||
For example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Dog.objects.create(name='Rufus', data={'breed': 'labrador'})
|
||||
<Dog: Rufus>
|
||||
@ -1318,14 +1420,18 @@ To compare two model instances, use the standard Python comparison operator,
|
||||
the double equals sign: ``==``. Behind the scenes, that compares the primary
|
||||
key values of two models.
|
||||
|
||||
Using the ``Entry`` example above, the following two statements are equivalent::
|
||||
Using the ``Entry`` example above, the following two statements are equivalent:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> some_entry == other_entry
|
||||
>>> some_entry.id == other_entry.id
|
||||
|
||||
If a model's primary key isn't called ``id``, no problem. Comparisons will
|
||||
always use the primary key, whatever it's called. For example, if a model's
|
||||
primary key field is called ``name``, these two statements are equivalent::
|
||||
primary key field is called ``name``, these two statements are equivalent:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> some_obj == other_obj
|
||||
>>> some_obj.name == other_obj.name
|
||||
@ -1338,7 +1444,9 @@ Deleting objects
|
||||
The delete method, conveniently, is named
|
||||
:meth:`~django.db.models.Model.delete`. This method immediately deletes the
|
||||
object and returns the number of objects deleted and a dictionary with
|
||||
the number of deletions per object type. Example::
|
||||
the number of deletions per object type. Example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> e.delete()
|
||||
(1, {'blog.Entry': 1})
|
||||
@ -1349,7 +1457,9 @@ You can also delete objects in bulk. Every
|
||||
members of that :class:`~django.db.models.query.QuerySet`.
|
||||
|
||||
For example, this deletes all ``Entry`` objects with a ``pub_date`` year of
|
||||
2005::
|
||||
2005:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Entry.objects.filter(pub_date__year=2005).delete()
|
||||
(5, {'webapp.Entry': 5})
|
||||
@ -1458,7 +1568,9 @@ a :class:`~django.db.models.query.QuerySet`. You can do this with the
|
||||
You can only set non-relation fields and :class:`~django.db.models.ForeignKey`
|
||||
fields using this method. To update a non-relation field, provide the new value
|
||||
as a constant. To update :class:`~django.db.models.ForeignKey` fields, set the
|
||||
new value to be the new model instance you want to point to. For example::
|
||||
new value to be the new model instance you want to point to. For example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> b = Blog.objects.get(pk=1)
|
||||
|
||||
@ -1471,7 +1583,9 @@ some rows already have the new value). The only restriction on the
|
||||
:class:`~django.db.models.query.QuerySet` being updated is that it can only
|
||||
access one database table: the model's main table. You can filter based on
|
||||
related fields, but you can only update columns in the model's main
|
||||
table. Example::
|
||||
table. Example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> b = Blog.objects.get(pk=1)
|
||||
|
||||
@ -1495,14 +1609,18 @@ them and call :meth:`~django.db.models.Model.save`::
|
||||
Calls to update can also use :class:`F expressions <django.db.models.F>` to
|
||||
update one field based on the value of another field in the model. This is
|
||||
especially useful for incrementing counters based upon their current value. For
|
||||
example, to increment the pingback count for every entry in the blog::
|
||||
example, to increment the pingback count for every entry in the blog:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Entry.objects.update(number_of_pingbacks=F('number_of_pingbacks') + 1)
|
||||
|
||||
However, unlike ``F()`` objects in filter and exclude clauses, you can't
|
||||
introduce joins when you use ``F()`` objects in an update -- you can only
|
||||
reference fields local to the model being updated. If you attempt to introduce
|
||||
a join with an ``F()`` object, a ``FieldError`` will be raised::
|
||||
a join with an ``F()`` object, a ``FieldError`` will be raised:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
# This will raise a FieldError
|
||||
>>> Entry.objects.update(headline=F('blog__name'))
|
||||
@ -1543,14 +1661,18 @@ Forward
|
||||
If a model has a :class:`~django.db.models.ForeignKey`, instances of that model
|
||||
will have access to the related (foreign) object via an attribute of the model.
|
||||
|
||||
Example::
|
||||
Example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> e = Entry.objects.get(id=2)
|
||||
>>> e.blog # Returns the related Blog object.
|
||||
|
||||
You can get and set via a foreign-key attribute. As you may expect, changes to
|
||||
the foreign key aren't saved to the database until you call
|
||||
:meth:`~django.db.models.Model.save`. Example::
|
||||
:meth:`~django.db.models.Model.save`. Example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> e = Entry.objects.get(id=2)
|
||||
>>> e.blog = some_blog
|
||||
@ -1558,7 +1680,9 @@ the foreign key aren't saved to the database until you call
|
||||
|
||||
If a :class:`~django.db.models.ForeignKey` field has ``null=True`` set (i.e.,
|
||||
it allows ``NULL`` values), you can assign ``None`` to remove the relation.
|
||||
Example::
|
||||
Example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> e = Entry.objects.get(id=2)
|
||||
>>> e.blog = None
|
||||
@ -1566,7 +1690,9 @@ Example::
|
||||
|
||||
Forward access to one-to-many relationships is cached the first time the
|
||||
related object is accessed. Subsequent accesses to the foreign key on the same
|
||||
object instance are cached. Example::
|
||||
object instance are cached. Example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> e = Entry.objects.get(id=2)
|
||||
>>> print(e.blog) # Hits the database to retrieve the associated Blog.
|
||||
@ -1574,7 +1700,9 @@ object instance are cached. Example::
|
||||
|
||||
Note that the :meth:`~django.db.models.query.QuerySet.select_related`
|
||||
:class:`~django.db.models.query.QuerySet` method recursively prepopulates the
|
||||
cache of all one-to-many relationships ahead of time. Example::
|
||||
cache of all one-to-many relationships ahead of time. Example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> e = Entry.objects.select_related().get(id=2)
|
||||
>>> print(e.blog) # Doesn't hit the database; uses cached version.
|
||||
@ -1593,7 +1721,9 @@ source model name, lowercased. This :class:`~django.db.models.Manager` returns
|
||||
``QuerySets``, which can be filtered and manipulated as described in the
|
||||
"Retrieving objects" section above.
|
||||
|
||||
Example::
|
||||
Example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> b = Blog.objects.get(id=1)
|
||||
>>> b.entry_set.all() # Returns all Entry objects related to Blog.
|
||||
@ -1606,7 +1736,9 @@ You can override the ``FOO_set`` name by setting the
|
||||
:attr:`~django.db.models.ForeignKey.related_name` parameter in the
|
||||
:class:`~django.db.models.ForeignKey` definition. For example, if the ``Entry``
|
||||
model was altered to ``blog = ForeignKey(Blog, on_delete=models.CASCADE,
|
||||
related_name='entries')``, the above example code would look like this::
|
||||
related_name='entries')``, the above example code would look like this:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> b = Blog.objects.get(id=1)
|
||||
>>> b.entries.all() # Returns all Entry objects related to Blog.
|
||||
|
@ -17,7 +17,9 @@ Standard textual queries
|
||||
------------------------
|
||||
|
||||
Text-based fields have a selection of matching operations. For example, you may
|
||||
wish to allow lookup up an author like so::
|
||||
wish to allow lookup up an author like so:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Author.objects.filter(name__contains='Terry')
|
||||
[<Author: Terry Gilliam>, <Author: Terry Jones>]
|
||||
@ -47,7 +49,9 @@ demonstrate the kind of functionality databases may have.
|
||||
|
||||
In the above example, we determined that a case insensitive lookup would be
|
||||
more useful. When dealing with non-English names, a further improvement is to
|
||||
use :lookup:`unaccented comparison <unaccent>`::
|
||||
use :lookup:`unaccented comparison <unaccent>`:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Author.objects.filter(name__unaccent__icontains='Helen')
|
||||
[<Author: Helen Mirren>, <Author: Helena Bonham Carter>, <Author: Hélène Joy>]
|
||||
@ -58,7 +62,9 @@ will pick up ``Helena`` or ``Hélène``, but not the reverse. Another option
|
||||
would be to use a :lookup:`trigram_similar` comparison, which compares
|
||||
sequences of letters.
|
||||
|
||||
For example::
|
||||
For example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Author.objects.filter(name__unaccent__lower__trigram_similar='Hélène')
|
||||
[<Author: Helen Mirren>, <Author: Hélène Joy>]
|
||||
@ -110,12 +116,16 @@ as categorization.
|
||||
|
||||
The :mod:`django.contrib.postgres` module provides some helpers to make these
|
||||
queries. For example, a query might select all the blog entries which mention
|
||||
"cheese"::
|
||||
"cheese":
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Entry.objects.filter(body_text__search='cheese')
|
||||
[<Entry: Cheese on Toast recipes>, <Entry: Pizza recipes>]
|
||||
|
||||
You can also filter on a combination of fields and on related models::
|
||||
You can also filter on a combination of fields and on related models:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Entry.objects.annotate(
|
||||
... search=SearchVector('blog__tagline', 'body_text'),
|
||||
|
@ -56,7 +56,9 @@ This is best illustrated with an example. Suppose you have the following model::
|
||||
last_name = models.CharField(...)
|
||||
birth_date = models.DateField(...)
|
||||
|
||||
You could then execute custom SQL like so::
|
||||
You could then execute custom SQL like so:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> for p in Person.objects.raw('SELECT * FROM myapp_person'):
|
||||
... print(p)
|
||||
@ -104,7 +106,9 @@ Mapping query fields to model fields
|
||||
``raw()`` automatically maps fields in the query to fields on the model.
|
||||
|
||||
The order of fields in your query doesn't matter. In other words, both
|
||||
of the following queries work identically::
|
||||
of the following queries work identically:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Person.objects.raw('SELECT id, first_name, last_name, birth_date FROM myapp_person')
|
||||
...
|
||||
@ -113,7 +117,9 @@ of the following queries work identically::
|
||||
|
||||
Matching is done by name. This means that you can use SQL's ``AS`` clauses to
|
||||
map fields in the query to model fields. So if you had some other table that
|
||||
had ``Person`` data in it, you could easily map it into ``Person`` instances::
|
||||
had ``Person`` data in it, you could easily map it into ``Person`` instances:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Person.objects.raw('''SELECT first AS first_name,
|
||||
... last AS last_name,
|
||||
@ -126,7 +132,9 @@ As long as the names match, the model instances will be created correctly.
|
||||
Alternatively, you can map fields in the query to model fields using the
|
||||
``translations`` argument to ``raw()``. This is a dictionary mapping names of
|
||||
fields in the query to names of fields on the model. For example, the above
|
||||
query could also be written::
|
||||
query could also be written:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> name_map = {'first': 'first_name', 'last': 'last_name', 'bd': 'birth_date', 'pk': 'id'}
|
||||
>>> Person.objects.raw('SELECT * FROM some_other_table', translations=name_map)
|
||||
@ -135,26 +143,34 @@ Index lookups
|
||||
-------------
|
||||
|
||||
``raw()`` supports indexing, so if you need only the first result you can
|
||||
write::
|
||||
write:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> first_person = Person.objects.raw('SELECT * FROM myapp_person')[0]
|
||||
|
||||
However, the indexing and slicing are not performed at the database level. If
|
||||
you have a large number of ``Person`` objects in your database, it is more
|
||||
efficient to limit the query at the SQL level::
|
||||
efficient to limit the query at the SQL level:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> first_person = Person.objects.raw('SELECT * FROM myapp_person LIMIT 1')[0]
|
||||
|
||||
Deferring model fields
|
||||
----------------------
|
||||
|
||||
Fields may also be left out::
|
||||
Fields may also be left out:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> people = Person.objects.raw('SELECT id, first_name FROM myapp_person')
|
||||
|
||||
The ``Person`` objects returned by this query will be deferred model instances
|
||||
(see :meth:`~django.db.models.query.QuerySet.defer()`). This means that the
|
||||
fields that are omitted from the query will be loaded on demand. For example::
|
||||
fields that are omitted from the query will be loaded on demand. For example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> for p in Person.objects.raw('SELECT id, first_name FROM myapp_person'):
|
||||
... print(p.first_name, # This will be retrieved by the original query
|
||||
@ -179,7 +195,9 @@ Adding annotations
|
||||
|
||||
You can also execute queries containing fields that aren't defined on the
|
||||
model. For example, we could use `PostgreSQL's age() function`__ to get a list
|
||||
of people with their ages calculated by the database::
|
||||
of people with their ages calculated by the database:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> people = Person.objects.raw('SELECT *, age(birth_date) AS age FROM myapp_person')
|
||||
>>> for p in people:
|
||||
@ -197,7 +215,9 @@ Passing parameters into ``raw()``
|
||||
---------------------------------
|
||||
|
||||
If you need to perform parameterized queries, you can use the ``params``
|
||||
argument to ``raw()``::
|
||||
argument to ``raw()``:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> lname = 'Doe'
|
||||
>>> Person.objects.raw('SELECT * FROM myapp_person WHERE last_name = %s', [lname])
|
||||
@ -218,13 +238,17 @@ replaced with parameters from the ``params`` argument.
|
||||
**Do not use string formatting on raw queries or quote placeholders in your
|
||||
SQL strings!**
|
||||
|
||||
It's tempting to write the above query as::
|
||||
It's tempting to write the above query as:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> query = 'SELECT * FROM myapp_person WHERE last_name = %s' % lname
|
||||
>>> Person.objects.raw(query)
|
||||
|
||||
You might also think you should write your query like this (with quotes
|
||||
around ``%s``)::
|
||||
around ``%s``):
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> query = "SELECT * FROM myapp_person WHERE last_name = '%s'"
|
||||
|
||||
@ -313,7 +337,9 @@ immutable and accessible by field names or indices, which might be useful::
|
||||
nt_result = namedtuple('Result', [col[0] for col in desc])
|
||||
return [nt_result(*row) for row in cursor.fetchall()]
|
||||
|
||||
Here is an example of the difference between the three::
|
||||
Here is an example of the difference between the three:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> cursor.execute("SELECT id, parent_id FROM test LIMIT 2")
|
||||
>>> cursor.fetchall()
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user