Fixed #30573 -- Rephrased documentation to avoid words that minimise the involved difficulty.
This patch does not remove all occurrences of the words in question. Rather, I went through all of the occurrences of the words listed below, and judged if they a) suggested the reader had some kind of knowledge/experience, and b) if they added anything of value (including tone of voice, etc). I left most of the words alone. I looked at the following words: - simply/simple - easy/easier/easiest - obvious - just - merely - straightforward - ridiculous Thanks to Carlton Gibson for guidance on how to approach this issue, and to Tim Bell for providing the idea. But the enormous lion's share of thanks go to Adam Johnson for his patient and helpful review.
This commit is contained in:
parent
addabc492b
commit
4a954cfd11
|
@ -78,9 +78,9 @@ modules to the page via the model's class Admin :ref:`js parameter
|
||||||
pointing to JavaScript modules that will be included within the admin form via
|
pointing to JavaScript modules that will be included within the admin form via
|
||||||
a ``<script>`` tag.
|
a ``<script>`` tag.
|
||||||
|
|
||||||
If you want more flexibility than simply tweaking the auto-generated forms,
|
If you want more flexibility than is feasible by tweaking the auto-generated
|
||||||
feel free to write custom views for the admin. The admin is powered by Django
|
forms, feel free to write custom views for the admin. The admin is powered by
|
||||||
itself, and you can write custom views that hook into the authentication
|
Django itself, and you can write custom views that hook into the authentication
|
||||||
system, check permissions and do whatever else they need to do.
|
system, check permissions and do whatever else they need to do.
|
||||||
|
|
||||||
If you want to customize the look-and-feel of the admin interface, read the
|
If you want to customize the look-and-feel of the admin interface, read the
|
||||||
|
|
|
@ -84,7 +84,7 @@ of a larger problem. While we can spend time writing, testing and applying
|
||||||
lots of little patches, sometimes the right solution is to rebuild. If a
|
lots of little patches, sometimes the right solution is to rebuild. If a
|
||||||
rebuild or refactor of a particular component has been proposed or is
|
rebuild or refactor of a particular component has been proposed or is
|
||||||
underway, you may find that bugs affecting that component will not get as much
|
underway, you may find that bugs affecting that component will not get as much
|
||||||
attention. Again, this is just a matter of prioritizing scarce resources. By
|
attention. Again, this is a matter of prioritizing scarce resources. By
|
||||||
concentrating on the rebuild, we can close all the little bugs at once, and
|
concentrating on the rebuild, we can close all the little bugs at once, and
|
||||||
hopefully prevent other little bugs from appearing in the future.
|
hopefully prevent other little bugs from appearing in the future.
|
||||||
|
|
||||||
|
@ -93,7 +93,7 @@ bug regularly, it doesn't necessarily follow that every single Django user
|
||||||
will hit the same bug. Different users use Django in different ways, stressing
|
will hit the same bug. Different users use Django in different ways, stressing
|
||||||
different parts of the code under different conditions. When we evaluate the
|
different parts of the code under different conditions. When we evaluate the
|
||||||
relative priorities, we are generally trying to consider the needs of the
|
relative priorities, we are generally trying to consider the needs of the
|
||||||
entire community, not just the severity for one particular user. This doesn't
|
entire community, instead of prioritizing the impact on one particular user.
|
||||||
mean that we think your problem is unimportant -- just that in the limited
|
This doesn't mean that we think your problem is unimportant -- just that in the
|
||||||
time we have available, we will always err on the side of making 10 people
|
limited time we have available, we will always err on the side of making 10
|
||||||
happy rather than making 1 person happy.
|
people happy rather than making a single person happy.
|
||||||
|
|
|
@ -8,7 +8,7 @@ How can I see the raw SQL queries Django is running?
|
||||||
====================================================
|
====================================================
|
||||||
|
|
||||||
Make sure your Django :setting:`DEBUG` setting is set to ``True``.
|
Make sure your Django :setting:`DEBUG` setting is set to ``True``.
|
||||||
Then, just do this::
|
Then do this::
|
||||||
|
|
||||||
>>> from django.db import connection
|
>>> from django.db import connection
|
||||||
>>> connection.queries
|
>>> connection.queries
|
||||||
|
@ -32,7 +32,7 @@ same interface on each member of the ``connections`` dictionary::
|
||||||
>>> connections['my_db_alias'].queries
|
>>> connections['my_db_alias'].queries
|
||||||
|
|
||||||
If you need to clear the query list manually at any point in your functions,
|
If you need to clear the query list manually at any point in your functions,
|
||||||
just call ``reset_queries()``, like this::
|
call ``reset_queries()``, like this::
|
||||||
|
|
||||||
from django.db import reset_queries
|
from django.db import reset_queries
|
||||||
reset_queries()
|
reset_queries()
|
||||||
|
@ -61,8 +61,8 @@ But this isn't an issue in practice, because there's nothing stopping you from
|
||||||
adding other constraints (using the ``unique_together`` model option or
|
adding other constraints (using the ``unique_together`` model option or
|
||||||
creating the constraint directly in your database), and enforcing the
|
creating the constraint directly in your database), and enforcing the
|
||||||
uniqueness at that level. Single-column primary keys are needed for things such
|
uniqueness at that level. Single-column primary keys are needed for things such
|
||||||
as the admin interface to work; e.g., you need a simple way of being able to
|
as the admin interface to work; e.g., you need a single value to specify
|
||||||
specify an object to edit or delete.
|
an object to edit or delete.
|
||||||
|
|
||||||
Does Django support NoSQL databases?
|
Does Django support NoSQL databases?
|
||||||
====================================
|
====================================
|
||||||
|
|
|
@ -61,9 +61,9 @@ Using a :class:`~django.db.models.FileField` or an
|
||||||
How do I make a variable available to all my templates?
|
How do I make a variable available to all my templates?
|
||||||
=======================================================
|
=======================================================
|
||||||
|
|
||||||
Sometimes your templates just all need the same thing. A common example would
|
Sometimes your templates all need the same thing. A common example would be
|
||||||
be dynamically-generated menus. At first glance, it seems logical to simply
|
dynamically generated menus. At first glance, it seems logical to add a common
|
||||||
add a common dictionary to the template context.
|
dictionary to the template context.
|
||||||
|
|
||||||
The correct solution is to use a ``RequestContext``. Details on how to do this
|
The best way to do this in Django is to use a ``RequestContext``. Details on
|
||||||
are here: :ref:`subclassing-context-requestcontext`.
|
how to do this are here: :ref:`subclassing-context-requestcontext`.
|
||||||
|
|
|
@ -111,8 +111,8 @@ Using ``REMOTE_USER`` on login pages only
|
||||||
|
|
||||||
The ``RemoteUserMiddleware`` authentication middleware assumes that the HTTP
|
The ``RemoteUserMiddleware`` authentication middleware assumes that the HTTP
|
||||||
request header ``REMOTE_USER`` is present with all authenticated requests. That
|
request header ``REMOTE_USER`` is present with all authenticated requests. That
|
||||||
might be expected and practical when Basic HTTP Auth with ``htpasswd`` or other
|
might be expected and practical when Basic HTTP Auth with ``htpasswd`` or
|
||||||
simple mechanisms are used, but with Negotiate (GSSAPI/Kerberos) or other
|
similar mechanisms are used, but with Negotiate (GSSAPI/Kerberos) or other
|
||||||
resource intensive authentication methods, the authentication in the front-end
|
resource intensive authentication methods, the authentication in the front-end
|
||||||
HTTP server is usually only set up for one or a few login URLs, and after
|
HTTP server is usually only set up for one or a few login URLs, and after
|
||||||
successful authentication, the application is supposed to maintain the
|
successful authentication, the application is supposed to maintain the
|
||||||
|
|
|
@ -9,10 +9,10 @@ filtering (for example, ``exact`` and ``icontains``). This documentation
|
||||||
explains how to write custom lookups and how to alter the working of existing
|
explains how to write custom lookups and how to alter the working of existing
|
||||||
lookups. For the API references of lookups, see the :doc:`/ref/models/lookups`.
|
lookups. For the API references of lookups, see the :doc:`/ref/models/lookups`.
|
||||||
|
|
||||||
A simple lookup example
|
A lookup example
|
||||||
=======================
|
================
|
||||||
|
|
||||||
Let's start with a simple custom lookup. We will write a custom lookup ``ne``
|
Let's start with a small custom lookup. We will write a custom lookup ``ne``
|
||||||
which works opposite to ``exact``. ``Author.objects.filter(name__ne='Jack')``
|
which works opposite to ``exact``. ``Author.objects.filter(name__ne='Jack')``
|
||||||
will translate to the SQL:
|
will translate to the SQL:
|
||||||
|
|
||||||
|
@ -24,8 +24,7 @@ This SQL is backend independent, so we don't need to worry about different
|
||||||
databases.
|
databases.
|
||||||
|
|
||||||
There are two steps to making this work. Firstly we need to implement the
|
There are two steps to making this work. Firstly we need to implement the
|
||||||
lookup, then we need to tell Django about it. The implementation is quite
|
lookup, then we need to tell Django about it::
|
||||||
straightforward::
|
|
||||||
|
|
||||||
from django.db.models import Lookup
|
from django.db.models import Lookup
|
||||||
|
|
||||||
|
@ -38,10 +37,10 @@ straightforward::
|
||||||
params = lhs_params + rhs_params
|
params = lhs_params + rhs_params
|
||||||
return '%s <> %s' % (lhs, rhs), params
|
return '%s <> %s' % (lhs, rhs), params
|
||||||
|
|
||||||
To register the ``NotEqual`` lookup we will just need to call
|
To register the ``NotEqual`` lookup we will need to call ``register_lookup`` on
|
||||||
``register_lookup`` on the field class we want the lookup to be available. In
|
the field class we want the lookup to be available for. In this case, the lookup
|
||||||
this case, the lookup makes sense on all ``Field`` subclasses, so we register
|
makes sense on all ``Field`` subclasses, so we register it with ``Field``
|
||||||
it with ``Field`` directly::
|
directly::
|
||||||
|
|
||||||
from django.db.models.fields import Field
|
from django.db.models.fields import Field
|
||||||
Field.register_lookup(NotEqual)
|
Field.register_lookup(NotEqual)
|
||||||
|
@ -94,8 +93,8 @@ Finally we combine the parts into an SQL expression with ``<>``, and supply all
|
||||||
the parameters for the query. We then return a tuple containing the generated
|
the parameters for the query. We then return a tuple containing the generated
|
||||||
SQL string and the parameters.
|
SQL string and the parameters.
|
||||||
|
|
||||||
A simple transformer example
|
A transformer example
|
||||||
============================
|
=====================
|
||||||
|
|
||||||
The custom lookup above is great, but in some cases you may want to be able to
|
The custom lookup above is great, but in some cases you may want to be able to
|
||||||
chain lookups together. For example, let's suppose we are building an
|
chain lookups together. For example, let's suppose we are building an
|
||||||
|
@ -241,10 +240,10 @@ want the transformation to be applied to both the left-hand side and the
|
||||||
right-hand side. For instance, if you want to filter a queryset based on the
|
right-hand side. For instance, if you want to filter a queryset based on the
|
||||||
equality of the left and right-hand side insensitively to some SQL function.
|
equality of the left and right-hand side insensitively to some SQL function.
|
||||||
|
|
||||||
Let's examine the simple example of case-insensitive transformation here. This
|
Let's examine case-insensitive transformations here. This transformation isn't
|
||||||
transformation isn't very useful in practice as Django already comes with a bunch
|
very useful in practice as Django already comes with a bunch of built-in
|
||||||
of built-in case-insensitive lookups, but it will be a nice demonstration of
|
case-insensitive lookups, but it will be a nice demonstration of bilateral
|
||||||
bilateral transformations in a database-agnostic way.
|
transformations in a database-agnostic way.
|
||||||
|
|
||||||
We define an ``UpperCase`` transformer which uses the SQL function ``UPPER()`` to
|
We define an ``UpperCase`` transformer which uses the SQL function ``UPPER()`` to
|
||||||
transform the values before comparison. We define
|
transform the values before comparison. We define
|
||||||
|
|
|
@ -10,9 +10,9 @@ distributing. In this document, we will be building a custom ``closepoll``
|
||||||
command for the ``polls`` application from the
|
command for the ``polls`` application from the
|
||||||
:doc:`tutorial</intro/tutorial01>`.
|
:doc:`tutorial</intro/tutorial01>`.
|
||||||
|
|
||||||
To do this, just add a ``management/commands`` directory to the application.
|
To do this, add a ``management/commands`` directory to the application. Django
|
||||||
Django will register a ``manage.py`` command for each Python module in that
|
will register a ``manage.py`` command for each Python module in that directory
|
||||||
directory whose name doesn't begin with an underscore. For example::
|
whose name doesn't begin with an underscore. For example::
|
||||||
|
|
||||||
polls/
|
polls/
|
||||||
__init__.py
|
__init__.py
|
||||||
|
|
|
@ -50,7 +50,7 @@ something like this::
|
||||||
|
|
||||||
.. _Bridge: https://en.wikipedia.org/wiki/Contract_bridge
|
.. _Bridge: https://en.wikipedia.org/wiki/Contract_bridge
|
||||||
|
|
||||||
This is just an ordinary Python class, with nothing Django-specific about it.
|
This is an ordinary Python class, with nothing Django-specific about it.
|
||||||
We'd like to be able to do things like this in our models (we assume the
|
We'd like to be able to do things like this in our models (we assume the
|
||||||
``hand`` attribute on the model is an instance of ``Hand``)::
|
``hand`` attribute on the model is an instance of ``Hand``)::
|
||||||
|
|
||||||
|
@ -81,11 +81,12 @@ Background theory
|
||||||
Database storage
|
Database storage
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
The simplest way to think of a model field is that it provides a way to take a
|
Let's start with model fields. If you break it down, a model field provides a
|
||||||
normal Python object -- string, boolean, ``datetime``, or something more
|
way to take a normal Python object -- string, boolean, ``datetime``, or
|
||||||
complex like ``Hand`` -- and convert it to and from a format that is useful
|
something more complex like ``Hand`` -- and convert it to and from a format
|
||||||
when dealing with the database (and serialization, but, as we'll see later,
|
that is useful when dealing with the database. (Such a format is also useful
|
||||||
that falls out fairly naturally once you have the database side under control).
|
for serialization, but as we'll see later, that is easier once you have the
|
||||||
|
database side under control).
|
||||||
|
|
||||||
Fields in a model must somehow be converted to fit into an existing database
|
Fields in a model must somehow be converted to fit into an existing database
|
||||||
column type. Different databases provide different sets of valid column types,
|
column type. Different databases provide different sets of valid column types,
|
||||||
|
@ -94,8 +95,7 @@ with. Anything you want to store in the database must fit into one of
|
||||||
those types.
|
those types.
|
||||||
|
|
||||||
Normally, you're either writing a Django field to match a particular database
|
Normally, you're either writing a Django field to match a particular database
|
||||||
column type, or there's a fairly straightforward way to convert your data to,
|
column type, or you will need a way to convert your data to, say, a string.
|
||||||
say, a string.
|
|
||||||
|
|
||||||
For our ``Hand`` example, we could convert the card data to a string of 104
|
For our ``Hand`` example, we could convert the card data to a string of 104
|
||||||
characters by concatenating all the cards together in a pre-determined order --
|
characters by concatenating all the cards together in a pre-determined order --
|
||||||
|
@ -180,16 +180,16 @@ card values plus their suits; 104 characters in total.
|
||||||
with. For example, you can pass both
|
with. For example, you can pass both
|
||||||
:attr:`~django.db.models.Field.editable` and
|
:attr:`~django.db.models.Field.editable` and
|
||||||
:attr:`~django.db.models.DateField.auto_now` to a
|
:attr:`~django.db.models.DateField.auto_now` to a
|
||||||
:class:`django.db.models.DateField` and it will simply ignore the
|
:class:`django.db.models.DateField` and it will ignore the
|
||||||
:attr:`~django.db.models.Field.editable` parameter
|
:attr:`~django.db.models.Field.editable` parameter
|
||||||
(:attr:`~django.db.models.DateField.auto_now` being set implies
|
(:attr:`~django.db.models.DateField.auto_now` being set implies
|
||||||
``editable=False``). No error is raised in this case.
|
``editable=False``). No error is raised in this case.
|
||||||
|
|
||||||
This behavior simplifies the field classes, because they don't need to
|
This behavior simplifies the field classes, because they don't need to
|
||||||
check for options that aren't necessary. They just pass all the options to
|
check for options that aren't necessary. They pass all the options to
|
||||||
the parent class and then don't use them later on. It's up to you whether
|
the parent class and then don't use them later on. It's up to you whether
|
||||||
you want your fields to be more strict about the options they select, or to
|
you want your fields to be more strict about the options they select, or to
|
||||||
use the simpler, more permissive behavior of the current fields.
|
use the more permissive behavior of the current fields.
|
||||||
|
|
||||||
The ``Field.__init__()`` method takes the following parameters:
|
The ``Field.__init__()`` method takes the following parameters:
|
||||||
|
|
||||||
|
@ -241,11 +241,11 @@ then there's no need to write a new ``deconstruct()`` method. If, however,
|
||||||
you're changing the arguments passed in ``__init__()`` (like we are in
|
you're changing the arguments passed in ``__init__()`` (like we are in
|
||||||
``HandField``), you'll need to supplement the values being passed.
|
``HandField``), you'll need to supplement the values being passed.
|
||||||
|
|
||||||
The contract of ``deconstruct()`` is simple; it returns a tuple of four items:
|
``deconstruct()`` returns a tuple of four items: the field's attribute name,
|
||||||
the field's attribute name, the full import path of the field class, the
|
the full import path of the field class, the positional arguments (as a list),
|
||||||
positional arguments (as a list), and the keyword arguments (as a dict). Note
|
and the keyword arguments (as a dict). Note this is different from the
|
||||||
this is different from the ``deconstruct()`` method :ref:`for custom classes
|
``deconstruct()`` method :ref:`for custom classes <custom-deconstruct-method>`
|
||||||
<custom-deconstruct-method>` which returns a tuple of three things.
|
which returns a tuple of three things.
|
||||||
|
|
||||||
As a custom field author, you don't need to care about the first two values;
|
As a custom field author, you don't need to care about the first two values;
|
||||||
the base ``Field`` class has all the code to work out the field's attribute
|
the base ``Field`` class has all the code to work out the field's attribute
|
||||||
|
@ -307,8 +307,8 @@ mind that people will be reconstructing your field from the serialized version
|
||||||
for quite a while (possibly years), depending how long your migrations live for.
|
for quite a while (possibly years), depending how long your migrations live for.
|
||||||
|
|
||||||
You can see the results of deconstruction by looking in migrations that include
|
You can see the results of deconstruction by looking in migrations that include
|
||||||
the field, and you can test deconstruction in unit tests by just deconstructing
|
the field, and you can test deconstruction in unit tests by deconstructing and
|
||||||
and reconstructing the field::
|
reconstructing the field::
|
||||||
|
|
||||||
name, path, args, kwargs = my_field_instance.deconstruct()
|
name, path, args, kwargs = my_field_instance.deconstruct()
|
||||||
new_instance = MyField(*args, **kwargs)
|
new_instance = MyField(*args, **kwargs)
|
||||||
|
@ -349,10 +349,10 @@ As always, you should document your field type, so users will know what it is.
|
||||||
In addition to providing a docstring for it, which is useful for developers,
|
In addition to providing a docstring for it, which is useful for developers,
|
||||||
you can also allow users of the admin app to see a short description of the
|
you can also allow users of the admin app to see a short description of the
|
||||||
field type via the :doc:`django.contrib.admindocs
|
field type via the :doc:`django.contrib.admindocs
|
||||||
</ref/contrib/admin/admindocs>` application. To do this simply provide
|
</ref/contrib/admin/admindocs>` application. To do this provide descriptive
|
||||||
descriptive text in a :attr:`~Field.description` class attribute of your custom
|
text in a :attr:`~Field.description` class attribute of your custom field. In
|
||||||
field. In the above example, the description displayed by the ``admindocs``
|
the above example, the description displayed by the ``admindocs`` application
|
||||||
application for a ``HandField`` will be 'A hand of cards (bridge style)'.
|
for a ``HandField`` will be 'A hand of cards (bridge style)'.
|
||||||
|
|
||||||
In the :mod:`django.contrib.admindocs` display, the field description is
|
In the :mod:`django.contrib.admindocs` display, the field description is
|
||||||
interpolated with ``field.__dict__`` which allows the description to
|
interpolated with ``field.__dict__`` which allows the description to
|
||||||
|
@ -393,8 +393,8 @@ Once you have ``MytypeField``, you can use it in any model, just like any other
|
||||||
If you aim to build a database-agnostic application, you should account for
|
If you aim to build a database-agnostic application, you should account for
|
||||||
differences in database column types. For example, the date/time column type
|
differences in database column types. For example, the date/time column type
|
||||||
in PostgreSQL is called ``timestamp``, while the same column in MySQL is called
|
in PostgreSQL is called ``timestamp``, while the same column in MySQL is called
|
||||||
``datetime``. The simplest way to handle this in a :meth:`~Field.db_type`
|
``datetime``. You can handle this in a :meth:`~Field.db_type` method by
|
||||||
method is to check the ``connection.settings_dict['ENGINE']`` attribute.
|
checking the ``connection.settings_dict['ENGINE']`` attribute.
|
||||||
|
|
||||||
For example::
|
For example::
|
||||||
|
|
||||||
|
@ -431,7 +431,7 @@ sense to have a ``CharMaxlength25Field``, shown here::
|
||||||
my_field = CharMaxlength25Field()
|
my_field = CharMaxlength25Field()
|
||||||
|
|
||||||
The better way of doing this would be to make the parameter specifiable at run
|
The better way of doing this would be to make the parameter specifiable at run
|
||||||
time -- i.e., when the class is instantiated. To do that, just implement
|
time -- i.e., when the class is instantiated. To do that, implement
|
||||||
``Field.__init__()``, like so::
|
``Field.__init__()``, like so::
|
||||||
|
|
||||||
# This is a much more flexible example.
|
# This is a much more flexible example.
|
||||||
|
@ -730,7 +730,7 @@ accessed, and what methods are available. It lives at
|
||||||
:doc:`file documentation </ref/files/file>`.
|
:doc:`file documentation </ref/files/file>`.
|
||||||
|
|
||||||
Once a subclass of ``File`` is created, the new ``FileField`` subclass must be
|
Once a subclass of ``File`` is created, the new ``FileField`` subclass must be
|
||||||
told to use it. To do so, simply assign the new ``File`` subclass to the special
|
told to use it. To do so, assign the new ``File`` subclass to the special
|
||||||
``attr_class`` attribute of the ``FileField`` subclass.
|
``attr_class`` attribute of the ``FileField`` subclass.
|
||||||
|
|
||||||
A few suggestions
|
A few suggestions
|
||||||
|
|
|
@ -89,7 +89,7 @@ an application.
|
||||||
Writing custom template filters
|
Writing custom template filters
|
||||||
===============================
|
===============================
|
||||||
|
|
||||||
Custom filters are just Python functions that take one or two arguments:
|
Custom filters are Python functions that take one or two arguments:
|
||||||
|
|
||||||
* The value of the variable (input) -- not necessarily a string.
|
* The value of the variable (input) -- not necessarily a string.
|
||||||
* The value of the argument -- this can have a default value, or be left
|
* The value of the argument -- this can have a default value, or be left
|
||||||
|
@ -117,8 +117,8 @@ And here's an example of how that filter would be used:
|
||||||
|
|
||||||
{{ somevariable|cut:"0" }}
|
{{ somevariable|cut:"0" }}
|
||||||
|
|
||||||
Most filters don't take arguments. In this case, just leave the argument out of
|
Most filters don't take arguments. In this case, leave the argument out of your
|
||||||
your function. Example::
|
function::
|
||||||
|
|
||||||
def lower(value): # Only one argument.
|
def lower(value): # Only one argument.
|
||||||
"""Converts a string into all lowercase"""
|
"""Converts a string into all lowercase"""
|
||||||
|
@ -312,11 +312,11 @@ Template filter code falls into one of two situations:
|
||||||
that our function will know whether automatic escaping is in effect when the
|
that our function will know whether automatic escaping is in effect when the
|
||||||
filter is called. We use ``autoescape`` to decide whether the input data
|
filter is called. We use ``autoescape`` to decide whether the input data
|
||||||
needs to be passed through ``django.utils.html.conditional_escape`` or not.
|
needs to be passed through ``django.utils.html.conditional_escape`` or not.
|
||||||
(In the latter case, we just use the identity function as the "escape"
|
(In the latter case, we use the identity function as the "escape" function.)
|
||||||
function.) The ``conditional_escape()`` function is like ``escape()`` except
|
The ``conditional_escape()`` function is like ``escape()`` except it only
|
||||||
it only escapes input that is **not** a ``SafeData`` instance. If a
|
escapes input that is **not** a ``SafeData`` instance. If a ``SafeData``
|
||||||
``SafeData`` instance is passed to ``conditional_escape()``, the data is
|
instance is passed to ``conditional_escape()``, the data is returned
|
||||||
returned unchanged.
|
unchanged.
|
||||||
|
|
||||||
Finally, in the above example, we remember to mark the result as safe
|
Finally, in the above example, we remember to mark the result as safe
|
||||||
so that our HTML is inserted directly into the template without further
|
so that our HTML is inserted directly into the template without further
|
||||||
|
@ -428,7 +428,7 @@ A few things to note about the ``simple_tag`` helper function:
|
||||||
* Checking for the required number of arguments, etc., has already been
|
* Checking for the required number of arguments, etc., has already been
|
||||||
done by the time our function is called, so we don't need to do that.
|
done by the time our function is called, so we don't need to do that.
|
||||||
* The quotes around the argument (if any) have already been stripped away,
|
* The quotes around the argument (if any) have already been stripped away,
|
||||||
so we just receive a plain string.
|
so we receive a plain string.
|
||||||
* If the argument was a template variable, our function is passed the
|
* If the argument was a template variable, our function is passed the
|
||||||
current value of the variable, not the variable itself.
|
current value of the variable, not the variable itself.
|
||||||
|
|
||||||
|
@ -539,7 +539,7 @@ for the template fragment. Example::
|
||||||
|
|
||||||
Next, create the template used to render the tag's output. This template is a
|
Next, create the template used to render the tag's output. This template is a
|
||||||
fixed feature of the tag: the tag writer specifies it, not the template
|
fixed feature of the tag: the tag writer specifies it, not the template
|
||||||
designer. Following our example, the template is very simple:
|
designer. Following our example, the template is very short:
|
||||||
|
|
||||||
.. code-block:: html+django
|
.. code-block:: html+django
|
||||||
|
|
||||||
|
@ -645,10 +645,10 @@ the rendering works.
|
||||||
|
|
||||||
When Django compiles a template, it splits the raw template text into
|
When Django compiles a template, it splits the raw template text into
|
||||||
''nodes''. Each node is an instance of ``django.template.Node`` and has
|
''nodes''. Each node is an instance of ``django.template.Node`` and has
|
||||||
a ``render()`` method. A compiled template is, simply, a list of ``Node``
|
a ``render()`` method. A compiled template is a list of ``Node`` objects. When
|
||||||
objects. When you call ``render()`` on a compiled template object, the template
|
you call ``render()`` on a compiled template object, the template calls
|
||||||
calls ``render()`` on each ``Node`` in its node list, with the given context.
|
``render()`` on each ``Node`` in its node list, with the given context. The
|
||||||
The results are all concatenated together to form the output of the template.
|
results are all concatenated together to form the output of the template.
|
||||||
|
|
||||||
Thus, to define a custom template tag, you specify how the raw template tag is
|
Thus, to define a custom template tag, you specify how the raw template tag is
|
||||||
converted into a ``Node`` (the compilation function), and what the node's
|
converted into a ``Node`` (the compilation function), and what the node's
|
||||||
|
@ -661,7 +661,7 @@ For each template tag the template parser encounters, it calls a Python
|
||||||
function with the tag contents and the parser object itself. This function is
|
function with the tag contents and the parser object itself. This function is
|
||||||
responsible for returning a ``Node`` instance based on the contents of the tag.
|
responsible for returning a ``Node`` instance based on the contents of the tag.
|
||||||
|
|
||||||
For example, let's write a full implementation of our simple template tag,
|
For example, let's write a full implementation of our template tag,
|
||||||
``{% current_time %}``, that displays the current date/time, formatted according
|
``{% current_time %}``, that displays the current date/time, formatted according
|
||||||
to a parameter given in the tag, in :func:`~time.strftime` syntax. It's a good
|
to a parameter given in the tag, in :func:`~time.strftime` syntax. It's a good
|
||||||
idea to decide the tag syntax before anything else. In our case, let's say the
|
idea to decide the tag syntax before anything else. In our case, let's say the
|
||||||
|
@ -715,7 +715,7 @@ Notes:
|
||||||
arguments.
|
arguments.
|
||||||
|
|
||||||
* The function returns a ``CurrentTimeNode`` with everything the node needs
|
* The function returns a ``CurrentTimeNode`` with everything the node needs
|
||||||
to know about this tag. In this case, it just passes the argument --
|
to know about this tag. In this case, it passes the argument --
|
||||||
``"%Y-%m-%d %I:%M %p"``. The leading and trailing quotes from the
|
``"%Y-%m-%d %I:%M %p"``. The leading and trailing quotes from the
|
||||||
template tag are removed in ``format_string[1:-1]``.
|
template tag are removed in ``format_string[1:-1]``.
|
||||||
|
|
||||||
|
@ -853,7 +853,7 @@ the same time:
|
||||||
|
|
||||||
The CycleNode is iterating, but it's iterating globally. As far as Thread 1
|
The CycleNode is iterating, but it's iterating globally. As far as Thread 1
|
||||||
and Thread 2 are concerned, it's always returning the same value. This is
|
and Thread 2 are concerned, it's always returning the same value. This is
|
||||||
obviously not what we want!
|
not what we want!
|
||||||
|
|
||||||
To address this problem, Django provides a ``render_context`` that's associated
|
To address this problem, Django provides a ``render_context`` that's associated
|
||||||
with the ``context`` of the template that is currently being rendered. The
|
with the ``context`` of the template that is currently being rendered. The
|
||||||
|
@ -965,9 +965,8 @@ You also have to change the renderer to retrieve the actual contents of the
|
||||||
``date_updated`` property of the ``blog_entry`` object. This can be
|
``date_updated`` property of the ``blog_entry`` object. This can be
|
||||||
accomplished by using the ``Variable()`` class in ``django.template``.
|
accomplished by using the ``Variable()`` class in ``django.template``.
|
||||||
|
|
||||||
To use the ``Variable`` class, simply instantiate it with the name of the
|
To use the ``Variable`` class, instantiate it with the name of the variable to
|
||||||
variable to be resolved, and then call ``variable.resolve(context)``. So,
|
be resolved, and then call ``variable.resolve(context)``. So, for example::
|
||||||
for example::
|
|
||||||
|
|
||||||
class FormatTimeNode(template.Node):
|
class FormatTimeNode(template.Node):
|
||||||
def __init__(self, date_to_be_formatted, format_string):
|
def __init__(self, date_to_be_formatted, format_string):
|
||||||
|
@ -987,11 +986,11 @@ cannot resolve the string passed to it in the current context of the page.
|
||||||
Setting a variable in the context
|
Setting a variable in the context
|
||||||
---------------------------------
|
---------------------------------
|
||||||
|
|
||||||
The above examples simply output a value. Generally, it's more flexible if your
|
The above examples output a value. Generally, it's more flexible if your
|
||||||
template tags set template variables instead of outputting values. That way,
|
template tags set template variables instead of outputting values. That way,
|
||||||
template authors can reuse the values that your template tags create.
|
template authors can reuse the values that your template tags create.
|
||||||
|
|
||||||
To set a variable in the context, just use dictionary assignment on the context
|
To set a variable in the context, use dictionary assignment on the context
|
||||||
object in the ``render()`` method. Here's an updated version of
|
object in the ``render()`` method. Here's an updated version of
|
||||||
``CurrentTimeNode`` that sets a template variable ``current_time`` instead of
|
``CurrentTimeNode`` that sets a template variable ``current_time`` instead of
|
||||||
outputting it::
|
outputting it::
|
||||||
|
@ -1116,7 +1115,7 @@ After ``parser.parse()`` is called, the parser hasn't yet "consumed" the
|
||||||
``{% endcomment %}`` tag, so the code needs to explicitly call
|
``{% endcomment %}`` tag, so the code needs to explicitly call
|
||||||
``parser.delete_first_token()``.
|
``parser.delete_first_token()``.
|
||||||
|
|
||||||
``CommentNode.render()`` simply returns an empty string. Anything between
|
``CommentNode.render()`` returns an empty string. Anything between
|
||||||
``{% comment %}`` and ``{% endcomment %}`` is ignored.
|
``{% comment %}`` and ``{% endcomment %}`` is ignored.
|
||||||
|
|
||||||
Parsing until another block tag, and saving contents
|
Parsing until another block tag, and saving contents
|
||||||
|
|
|
@ -5,14 +5,14 @@ How to use Django with Gunicorn
|
||||||
.. highlight:: bash
|
.. highlight:: bash
|
||||||
|
|
||||||
Gunicorn_ ('Green Unicorn') is a pure-Python WSGI server for UNIX. It has no
|
Gunicorn_ ('Green Unicorn') is a pure-Python WSGI server for UNIX. It has no
|
||||||
dependencies and is easy to install and use.
|
dependencies and can be installed using ``pip``.
|
||||||
|
|
||||||
.. _Gunicorn: https://gunicorn.org/
|
.. _Gunicorn: https://gunicorn.org/
|
||||||
|
|
||||||
Installing Gunicorn
|
Installing Gunicorn
|
||||||
===================
|
===================
|
||||||
|
|
||||||
Installing gunicorn is as easy as ``python -m pip install gunicorn``. For more
|
Install gunicorn by running ``python -m pip install gunicorn``. For more
|
||||||
details, see the `gunicorn documentation`_.
|
details, see the `gunicorn documentation`_.
|
||||||
|
|
||||||
.. _gunicorn documentation: https://docs.gunicorn.org/en/latest/install.html
|
.. _gunicorn documentation: https://docs.gunicorn.org/en/latest/install.html
|
||||||
|
@ -21,10 +21,9 @@ Running Django in Gunicorn as a generic WSGI application
|
||||||
========================================================
|
========================================================
|
||||||
|
|
||||||
When Gunicorn is installed, a ``gunicorn`` command is available which starts
|
When Gunicorn is installed, a ``gunicorn`` command is available which starts
|
||||||
the Gunicorn server process. At its simplest, gunicorn just needs to be called
|
the Gunicorn server process. The simplest invocation of gunicorn is to pass the
|
||||||
with the location of a module containing a WSGI application object named
|
location of a module containing a WSGI application object named
|
||||||
`application`. So for a typical Django project, invoking gunicorn would look
|
``application``, which for a typical Django project would look like::
|
||||||
like::
|
|
||||||
|
|
||||||
gunicorn myproject.wsgi
|
gunicorn myproject.wsgi
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ servers and applications.
|
||||||
|
|
||||||
.. _WSGI: https://wsgi.readthedocs.io/en/latest/
|
.. _WSGI: https://wsgi.readthedocs.io/en/latest/
|
||||||
|
|
||||||
Django's :djadmin:`startproject` management command sets up a simple default
|
Django's :djadmin:`startproject` management command sets up a minimal default
|
||||||
WSGI configuration for you, which you can tweak as needed for your project,
|
WSGI configuration for you, which you can tweak as needed for your project,
|
||||||
and direct any WSGI-compliant application server to use.
|
and direct any WSGI-compliant application server to use.
|
||||||
|
|
||||||
|
@ -70,8 +70,8 @@ If this variable isn't set, the default :file:`wsgi.py` sets it to
|
||||||
Applying WSGI middleware
|
Applying WSGI middleware
|
||||||
========================
|
========================
|
||||||
|
|
||||||
To apply `WSGI middleware`_ you can simply wrap the application object. For
|
To apply `WSGI middleware`_ you can wrap the application object. For instance
|
||||||
instance you could add these lines at the bottom of :file:`wsgi.py`::
|
you could add these lines at the bottom of :file:`wsgi.py`::
|
||||||
|
|
||||||
from helloworld.wsgi import HelloWorldApplication
|
from helloworld.wsgi import HelloWorldApplication
|
||||||
application = HelloWorldApplication(application)
|
application = HelloWorldApplication(application)
|
||||||
|
|
|
@ -57,8 +57,8 @@ virtualenv guide`_ for more details.
|
||||||
The ``WSGIPythonPath`` line ensures that your project package is available for
|
The ``WSGIPythonPath`` line ensures that your project package is available for
|
||||||
import on the Python path; in other words, that ``import mysite`` works.
|
import on the Python path; in other words, that ``import mysite`` works.
|
||||||
|
|
||||||
The ``<Directory>`` piece just ensures that Apache can access your
|
The ``<Directory>`` piece ensures that Apache can access your :file:`wsgi.py`
|
||||||
:file:`wsgi.py` file.
|
file.
|
||||||
|
|
||||||
Next we'll need to ensure this :file:`wsgi.py` with a WSGI application object
|
Next we'll need to ensure this :file:`wsgi.py` with a WSGI application object
|
||||||
exists. As of Django version 1.4, :djadmin:`startproject` will have created one
|
exists. As of Django version 1.4, :djadmin:`startproject` will have created one
|
||||||
|
|
|
@ -8,9 +8,9 @@ also prevent malicious users from seeing details of your application that can be
|
||||||
revealed by the error pages.
|
revealed by the error pages.
|
||||||
|
|
||||||
However, running with :setting:`DEBUG` set to ``False`` means you'll never see
|
However, running with :setting:`DEBUG` set to ``False`` means you'll never see
|
||||||
errors generated by your site -- everyone will just see your public error pages.
|
errors generated by your site -- everyone will instead see your public error
|
||||||
You need to keep track of errors that occur in deployed sites, so Django can be
|
pages. You need to keep track of errors that occur in deployed sites, so Django
|
||||||
configured to create reports with details about those errors.
|
can be configured to create reports with details about those errors.
|
||||||
|
|
||||||
Email reports
|
Email reports
|
||||||
=============
|
=============
|
||||||
|
@ -63,7 +63,7 @@ not found" errors). Django sends emails about 404 errors when:
|
||||||
If those conditions are met, Django will email the users listed in the
|
If those conditions are met, Django will email the users listed in the
|
||||||
:setting:`MANAGERS` setting whenever your code raises a 404 and the request has
|
:setting:`MANAGERS` setting whenever your code raises a 404 and the request has
|
||||||
a referer. It doesn't bother to email for 404s that don't have a referer --
|
a referer. It doesn't bother to email for 404s that don't have a referer --
|
||||||
those are usually just people typing in broken URLs or broken Web bots. It also
|
those are usually people typing in broken URLs or broken Web bots. It also
|
||||||
ignores 404s when the referer is equal to the requested URL, since this
|
ignores 404s when the referer is equal to the requested URL, since this
|
||||||
behavior is from broken Web bots too.
|
behavior is from broken Web bots too.
|
||||||
|
|
||||||
|
|
|
@ -32,8 +32,8 @@ Or, you can write fixtures by hand; fixtures can be written as JSON, XML or YAML
|
||||||
|
|
||||||
.. _PyYAML: https://pyyaml.org/
|
.. _PyYAML: https://pyyaml.org/
|
||||||
|
|
||||||
As an example, though, here's what a fixture for a simple ``Person`` model might
|
As an example, though, here's what a fixture for a ``Person`` model might look
|
||||||
look like in JSON:
|
like in JSON:
|
||||||
|
|
||||||
.. code-block:: js
|
.. code-block:: js
|
||||||
|
|
||||||
|
@ -73,7 +73,7 @@ And here's that same fixture as YAML:
|
||||||
|
|
||||||
You'll store this data in a ``fixtures`` directory inside your app.
|
You'll store this data in a ``fixtures`` directory inside your app.
|
||||||
|
|
||||||
Loading data is easy: just call :djadmin:`manage.py loaddata <loaddata>`
|
You can load data by calling :djadmin:`manage.py loaddata <loaddata>`
|
||||||
``<fixturename>``, where ``<fixturename>`` is the name of the fixture file
|
``<fixturename>``, where ``<fixturename>`` is the name of the fixture file
|
||||||
you've created. Each time you run :djadmin:`loaddata`, the data will be read
|
you've created. Each time you run :djadmin:`loaddata`, the data will be read
|
||||||
from the fixture and re-loaded into the database. Note this means that if you
|
from the fixture and re-loaded into the database. Note this means that if you
|
||||||
|
|
|
@ -62,7 +62,7 @@ each table's creation, modification, and deletion::
|
||||||
|
|
||||||
If you do want to allow Django to manage the table's lifecycle, you'll need to
|
If you do want to allow Django to manage the table's lifecycle, you'll need to
|
||||||
change the :attr:`~django.db.models.Options.managed` option above to ``True``
|
change the :attr:`~django.db.models.Options.managed` option above to ``True``
|
||||||
(or simply remove it because ``True`` is its default value).
|
(or remove it because ``True`` is its default value).
|
||||||
|
|
||||||
Install the core Django tables
|
Install the core Django tables
|
||||||
==============================
|
==============================
|
||||||
|
|
|
@ -41,17 +41,16 @@ mention:
|
||||||
contains the name of the CSV file. This filename is arbitrary; call it
|
contains the name of the CSV file. This filename is arbitrary; call it
|
||||||
whatever you want. It'll be used by browsers in the "Save as..." dialog, etc.
|
whatever you want. It'll be used by browsers in the "Save as..." dialog, etc.
|
||||||
|
|
||||||
* Hooking into the CSV-generation API is easy: Just pass ``response`` as the
|
* You can hook into the CSV-generation API by passing ``response`` as the first
|
||||||
first argument to ``csv.writer``. The ``csv.writer`` function expects a
|
argument to ``csv.writer``. The ``csv.writer`` function expects a file-like
|
||||||
file-like object, and :class:`~django.http.HttpResponse` objects fit the
|
object, and :class:`~django.http.HttpResponse` objects fit the bill.
|
||||||
bill.
|
|
||||||
|
|
||||||
* For each row in your CSV file, call ``writer.writerow``, passing it an
|
* For each row in your CSV file, call ``writer.writerow``, passing it an
|
||||||
:term:`iterable`.
|
:term:`iterable`.
|
||||||
|
|
||||||
* The CSV module takes care of quoting for you, so you don't have to worry
|
* The CSV module takes care of quoting for you, so you don't have to worry
|
||||||
about escaping strings with quotes or commas in them. Just pass
|
about escaping strings with quotes or commas in them. Pass ``writerow()``
|
||||||
``writerow()`` your raw strings, and it'll do the right thing.
|
your raw strings, and it'll do the right thing.
|
||||||
|
|
||||||
.. _streaming-csv-files:
|
.. _streaming-csv-files:
|
||||||
|
|
||||||
|
@ -137,9 +136,9 @@ Then, create the template ``my_template_name.txt``, with this template code:
|
||||||
{% for row in data %}"{{ row.0|addslashes }}", "{{ row.1|addslashes }}", "{{ row.2|addslashes }}", "{{ row.3|addslashes }}", "{{ row.4|addslashes }}"
|
{% for row in data %}"{{ row.0|addslashes }}", "{{ row.1|addslashes }}", "{{ row.2|addslashes }}", "{{ row.3|addslashes }}", "{{ row.4|addslashes }}"
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
This template is quite basic. It just iterates over the given data and displays
|
This short template iterates over the given data and displays a line of CSV for
|
||||||
a line of CSV for each row. It uses the :tfilter:`addslashes` template filter to
|
each row. It uses the :tfilter:`addslashes` template filter to ensure there
|
||||||
ensure there aren't any problems with quotes.
|
aren't any problems with quotes.
|
||||||
|
|
||||||
Other text-based formats
|
Other text-based formats
|
||||||
========================
|
========================
|
||||||
|
|
|
@ -88,7 +88,7 @@ mention:
|
||||||
* You can provide an arbitrary ``filename`` parameter. It'll be used by browsers
|
* You can provide an arbitrary ``filename`` parameter. It'll be used by browsers
|
||||||
in the "Save as..." dialog.
|
in the "Save as..." dialog.
|
||||||
|
|
||||||
* Hooking into the ReportLab API is easy: The same buffer passed as the first
|
* You can hook into the ReportLab API: The same buffer passed as the first
|
||||||
argument to ``canvas.Canvas`` can be fed to the
|
argument to ``canvas.Canvas`` can be fed to the
|
||||||
:class:`~django.http.FileResponse` class.
|
:class:`~django.http.FileResponse` class.
|
||||||
|
|
||||||
|
|
|
@ -12,13 +12,14 @@ Deploying static files
|
||||||
Serving static files in production
|
Serving static files in production
|
||||||
==================================
|
==================================
|
||||||
|
|
||||||
The basic outline of putting static files into production is simple: run the
|
The basic outline of putting static files into production consists of two
|
||||||
:djadmin:`collectstatic` command when static files change, then arrange for
|
steps: run the :djadmin:`collectstatic` command when static files change, then
|
||||||
the collected static files directory (:setting:`STATIC_ROOT`) to be moved to
|
arrange for the collected static files directory (:setting:`STATIC_ROOT`) to be
|
||||||
the static file server and served. Depending on :setting:`STATICFILES_STORAGE`,
|
moved to the static file server and served. Depending on
|
||||||
files may need to be moved to a new location manually or the :func:`post_process
|
:setting:`STATICFILES_STORAGE`, files may need to be moved to a new location
|
||||||
<django.contrib.staticfiles.storage.StaticFilesStorage.post_process>` method
|
manually or the :func:`post_process
|
||||||
of the ``Storage`` class might take care of that.
|
<django.contrib.staticfiles.storage.StaticFilesStorage.post_process>` method of
|
||||||
|
the ``Storage`` class might take care of that.
|
||||||
|
|
||||||
Of course, as with all deployment tasks, the devil's in the details. Every
|
Of course, as with all deployment tasks, the devil's in the details. Every
|
||||||
production setup will be a bit different, so you'll need to adapt the basic
|
production setup will be a bit different, so you'll need to adapt the basic
|
||||||
|
@ -80,11 +81,11 @@ When using these services, the basic workflow would look a bit like the above,
|
||||||
except that instead of using ``rsync`` to transfer your static files to the
|
except that instead of using ``rsync`` to transfer your static files to the
|
||||||
server you'd need to transfer the static files to the storage provider or CDN.
|
server you'd need to transfer the static files to the storage provider or CDN.
|
||||||
|
|
||||||
There's any number of ways you might do this, but if the provider has an API a
|
There's any number of ways you might do this, but if the provider has an API,
|
||||||
:doc:`custom file storage backend </howto/custom-file-storage>` will make the
|
you can use a :doc:`custom file storage backend </howto/custom-file-storage>`
|
||||||
process incredibly simple. If you've written or are using a 3rd party custom
|
to integrate the CDN with your Django project. If you've written or are using a
|
||||||
storage backend, you can tell :djadmin:`collectstatic` to use it by setting
|
3rd party custom storage backend, you can tell :djadmin:`collectstatic` to use
|
||||||
:setting:`STATICFILES_STORAGE` to the storage engine.
|
it by setting :setting:`STATICFILES_STORAGE` to the storage engine.
|
||||||
|
|
||||||
For example, if you've written an S3 storage backend in
|
For example, if you've written an S3 storage backend in
|
||||||
``myproject.storage.S3Storage`` you could use it with::
|
``myproject.storage.S3Storage`` you could use it with::
|
||||||
|
@ -93,8 +94,8 @@ For example, if you've written an S3 storage backend in
|
||||||
|
|
||||||
Once that's done, all you have to do is run :djadmin:`collectstatic` and your
|
Once that's done, all you have to do is run :djadmin:`collectstatic` and your
|
||||||
static files would be pushed through your storage package up to S3. If you
|
static files would be pushed through your storage package up to S3. If you
|
||||||
later needed to switch to a different storage provider, it could be as simple
|
later needed to switch to a different storage provider, you may only have to
|
||||||
as changing your :setting:`STATICFILES_STORAGE` setting.
|
change your :setting:`STATICFILES_STORAGE` setting.
|
||||||
|
|
||||||
For details on how you'd write one of these backends, see
|
For details on how you'd write one of these backends, see
|
||||||
:doc:`/howto/custom-file-storage`. There are 3rd party apps available that
|
:doc:`/howto/custom-file-storage`. There are 3rd party apps available that
|
||||||
|
|
|
@ -67,7 +67,7 @@ details on how ``staticfiles`` finds your files.
|
||||||
first static file it finds whose name matches, and if you had a static file
|
first static file it finds whose name matches, and if you had a static file
|
||||||
with the same name in a *different* application, Django would be unable to
|
with the same name in a *different* application, Django would be unable to
|
||||||
distinguish between them. We need to be able to point Django at the right
|
distinguish between them. We need to be able to point Django at the right
|
||||||
one, and the easiest way to ensure this is by *namespacing* them. That is,
|
one, and the best way to ensure this is by *namespacing* them. That is,
|
||||||
by putting those static files inside *another* directory named for the
|
by putting those static files inside *another* directory named for the
|
||||||
application itself.
|
application itself.
|
||||||
|
|
||||||
|
|
|
@ -57,7 +57,7 @@ Install ``virtualenv`` and ``virtualenvwrapper``
|
||||||
`virtualenv`_ and `virtualenvwrapper`_ provide a dedicated environment for
|
`virtualenv`_ and `virtualenvwrapper`_ provide a dedicated environment for
|
||||||
each Django project you create. While not mandatory, this is considered a best
|
each Django project you create. While not mandatory, this is considered a best
|
||||||
practice and will save you time in the future when you're ready to deploy your
|
practice and will save you time in the future when you're ready to deploy your
|
||||||
project. Simply type::
|
project. To do this, run::
|
||||||
|
|
||||||
...\> py -m pip install virtualenvwrapper-win
|
...\> py -m pip install virtualenvwrapper-win
|
||||||
|
|
||||||
|
|
|
@ -46,13 +46,13 @@ particular:
|
||||||
include a clear, concise description of the problem, and a set of
|
include a clear, concise description of the problem, and a set of
|
||||||
instructions for replicating it. Add as much debug information as you can:
|
instructions for replicating it. Add as much debug information as you can:
|
||||||
code snippets, test cases, exception backtraces, screenshots, etc. A nice
|
code snippets, test cases, exception backtraces, screenshots, etc. A nice
|
||||||
small test case is the best way to report a bug, as it gives us an easy
|
small test case is the best way to report a bug, as it gives us a
|
||||||
way to confirm the bug quickly.
|
helpful way to confirm the bug quickly.
|
||||||
|
|
||||||
* **Don't** post to |django-developers| just to announce that you have
|
* **Don't** post to |django-developers| only to announce that you have filed a
|
||||||
filed a bug report. All the tickets are mailed to another list,
|
bug report. All the tickets are mailed to another list, |django-updates|,
|
||||||
|django-updates|, which is tracked by developers and interested
|
which is tracked by developers and interested community members; we see them
|
||||||
community members; we see them as they are filed.
|
as they are filed.
|
||||||
|
|
||||||
To understand the lifecycle of your ticket once you have created it, refer to
|
To understand the lifecycle of your ticket once you have created it, refer to
|
||||||
:doc:`triaging-tickets`.
|
:doc:`triaging-tickets`.
|
||||||
|
@ -116,8 +116,8 @@ ticket description.
|
||||||
|
|
||||||
As with most open-source projects, code talks. If you are willing to write the
|
As with most open-source projects, code talks. If you are willing to write the
|
||||||
code for the feature yourself or, even better, if you've already written it,
|
code for the feature yourself or, even better, if you've already written it,
|
||||||
it's much more likely to be accepted. Just fork Django on GitHub, create a
|
it's much more likely to be accepted. Fork Django on GitHub, create a feature
|
||||||
feature branch, and show us your work!
|
branch, and show us your work!
|
||||||
|
|
||||||
See also: :ref:`documenting-new-features`.
|
See also: :ref:`documenting-new-features`.
|
||||||
|
|
||||||
|
|
|
@ -11,8 +11,8 @@ contribute code to Django, look at :doc:`writing-code/working-with-git` instead.
|
||||||
Handling pull requests
|
Handling pull requests
|
||||||
======================
|
======================
|
||||||
|
|
||||||
Since Django is now hosted at GitHub, most patches are provided in the form of
|
Since Django is hosted on GitHub, patches are provided in the form of pull
|
||||||
pull requests.
|
requests.
|
||||||
|
|
||||||
When committing a pull request, make sure each individual commit matches the
|
When committing a pull request, make sure each individual commit matches the
|
||||||
commit guidelines described below. Contributors are expected to provide the
|
commit guidelines described below. Contributors are expected to provide the
|
||||||
|
@ -26,14 +26,14 @@ builders that doesn't run automatically, such as Oracle or Selenium. See the
|
||||||
|
|
||||||
.. _Jenkins wiki page: https://code.djangoproject.com/wiki/Jenkins
|
.. _Jenkins wiki page: https://code.djangoproject.com/wiki/Jenkins
|
||||||
|
|
||||||
An easy way to checkout a pull request locally is to add an alias to your
|
If you find yourself checking out pull requests locally more often, this git
|
||||||
``~/.gitconfig`` (``upstream`` is assumed to be ``django/django``)::
|
alias will be helpful::
|
||||||
|
|
||||||
[alias]
|
[alias]
|
||||||
pr = !sh -c \"git fetch upstream pull/${1}/head:pr/${1} && git checkout pr/${1}\"
|
pr = !sh -c \"git fetch upstream pull/${1}/head:pr/${1} && git checkout pr/${1}\"
|
||||||
|
|
||||||
Now you can simply run ``git pr ####`` to checkout the corresponding pull
|
Add it to your ``~/.gitconfig``, and set ``upstream`` to be ``django/django``.
|
||||||
request.
|
Then you can run ``git pr ####`` to checkout the corresponding pull request.
|
||||||
|
|
||||||
At this point, you can work on the code. Use ``git rebase -i`` and ``git
|
At this point, you can work on the code. Use ``git rebase -i`` and ``git
|
||||||
commit --amend`` to make sure the commits have the expected level of quality.
|
commit --amend`` to make sure the commits have the expected level of quality.
|
||||||
|
@ -243,8 +243,8 @@ When a mistaken commit is discovered, please follow these guidelines:
|
||||||
* The release branch maintainer may back out commits to the release
|
* The release branch maintainer may back out commits to the release
|
||||||
branch without permission if the commit breaks the release branch.
|
branch without permission if the commit breaks the release branch.
|
||||||
|
|
||||||
* If you mistakenly push a topic branch to ``django/django``, just delete it.
|
* If you mistakenly push a topic branch to ``django/django``, delete it.
|
||||||
For instance, if you did: ``git push upstream feature_antigravity``,
|
For instance, if you did: ``git push upstream feature_antigravity``,
|
||||||
just do a reverse push: ``git push upstream :feature_antigravity``.
|
do a reverse push: ``git push upstream :feature_antigravity``.
|
||||||
|
|
||||||
.. _ticket tracker: https://code.djangoproject.com/
|
.. _ticket tracker: https://code.djangoproject.com/
|
||||||
|
|
|
@ -36,7 +36,7 @@ development:
|
||||||
on the `#django-dev IRC channel`_.
|
on the `#django-dev IRC channel`_.
|
||||||
|
|
||||||
* :doc:`Submit patches <writing-code/submitting-patches>` for new and/or
|
* :doc:`Submit patches <writing-code/submitting-patches>` for new and/or
|
||||||
fixed behavior. If you're looking for an easy way to start contributing
|
fixed behavior. If you're looking for a way to get started contributing
|
||||||
to Django read the :doc:`/intro/contributing` tutorial and have a look at the
|
to Django read the :doc:`/intro/contributing` tutorial and have a look at the
|
||||||
`easy pickings`_ tickets. The :ref:`patch-review-checklist` will also be
|
`easy pickings`_ tickets. The :ref:`patch-review-checklist` will also be
|
||||||
helpful.
|
helpful.
|
||||||
|
|
|
@ -13,7 +13,7 @@ to get started? This is the section for you.
|
||||||
First steps
|
First steps
|
||||||
===========
|
===========
|
||||||
|
|
||||||
Start with these easy tasks to discover Django's development process.
|
Start with these steps to discover Django's development process.
|
||||||
|
|
||||||
* **Sign the Contributor License Agreement**
|
* **Sign the Contributor License Agreement**
|
||||||
|
|
||||||
|
@ -45,7 +45,7 @@ Start with these easy tasks to discover Django's development process.
|
||||||
|
|
||||||
Oftentimes the codebase will change between a patch being submitted and the
|
Oftentimes the codebase will change between a patch being submitted and the
|
||||||
time it gets reviewed. Make sure it still applies cleanly and functions as
|
time it gets reviewed. Make sure it still applies cleanly and functions as
|
||||||
expected. Simply updating a patch is both useful and important! See more on
|
expected. Updating a patch is both useful and important! See more on
|
||||||
:doc:`writing-code/submitting-patches`.
|
:doc:`writing-code/submitting-patches`.
|
||||||
|
|
||||||
* **Write some documentation**
|
* **Write some documentation**
|
||||||
|
|
|
@ -17,12 +17,11 @@ community as a whole to self-manage, keep the problems to a minimum, and
|
||||||
educate those coming into the community so that they can become valuable
|
educate those coming into the community so that they can become valuable
|
||||||
contributing members.
|
contributing members.
|
||||||
|
|
||||||
Similarly, while we aim for Trac to be a perfect representation of the state
|
Similarly, while we aim for Trac to be a perfect representation of the state of
|
||||||
of Django's progress, we acknowledge that this simply will not happen. By
|
Django's progress, we acknowledge that this will not happen. By distributing
|
||||||
distributing the load of Trac maintenance to the community, we accept that
|
the load of Trac maintenance to the community, we accept that there will be
|
||||||
there will be mistakes. Trac is "mostly accurate", and we give allowances for
|
mistakes. Trac is "mostly accurate", and we give allowances for the fact that
|
||||||
the fact that sometimes it will be wrong. That's okay. We're perfectionists
|
sometimes it will be wrong. That's okay. We're perfectionists with deadlines.
|
||||||
with deadlines.
|
|
||||||
|
|
||||||
We rely on the community to keep participating, keep tickets as accurate as
|
We rely on the community to keep participating, keep tickets as accurate as
|
||||||
possible, and raise issues for discussion on our mailing lists when there is
|
possible, and raise issues for discussion on our mailing lists when there is
|
||||||
|
@ -269,8 +268,8 @@ When a ticket has completed its useful lifecycle, it's time for it to be
|
||||||
closed. Closing a ticket is a big responsibility, though. You have to be sure
|
closed. Closing a ticket is a big responsibility, though. You have to be sure
|
||||||
that the issue is really resolved, and you need to keep in mind that the
|
that the issue is really resolved, and you need to keep in mind that the
|
||||||
reporter of the ticket may not be happy to have their ticket closed (unless
|
reporter of the ticket may not be happy to have their ticket closed (unless
|
||||||
it's fixed, of course). If you're not certain about closing a ticket, just
|
it's fixed, of course). If you're not certain about closing a ticket, leave a
|
||||||
leave a comment with your thoughts instead.
|
comment with your thoughts instead.
|
||||||
|
|
||||||
If you do close a ticket, you should always make sure of the following:
|
If you do close a ticket, you should always make sure of the following:
|
||||||
|
|
||||||
|
|
|
@ -85,10 +85,9 @@ Which tickets should be claimed?
|
||||||
Of course, going through the steps of claiming tickets is overkill in some
|
Of course, going through the steps of claiming tickets is overkill in some
|
||||||
cases.
|
cases.
|
||||||
|
|
||||||
In the case of small changes, such as typos in the documentation or
|
In the case of small changes, such as typos in the documentation or small bugs
|
||||||
small bugs that will only take a few minutes to fix, you don't need to jump
|
that will only take a few minutes to fix, you don't need to jump through the
|
||||||
through the hoops of claiming tickets. Just submit your patch and be done with
|
hoops of claiming tickets. Submit your patch directly and you're done!
|
||||||
it.
|
|
||||||
|
|
||||||
Of course, it is *always* acceptable, regardless whether someone has claimed it
|
Of course, it is *always* acceptable, regardless whether someone has claimed it
|
||||||
or not, to submit patches to a ticket if you happen to have a patch ready.
|
or not, to submit patches to a ticket if you happen to have a patch ready.
|
||||||
|
@ -145,14 +144,14 @@ Regardless of the way you submit your work, follow these steps.
|
||||||
Non-trivial patches
|
Non-trivial patches
|
||||||
===================
|
===================
|
||||||
|
|
||||||
A "non-trivial" patch is one that is more than a simple bug fix. It's a patch
|
A "non-trivial" patch is one that is more than a small bug fix. It's a patch
|
||||||
that introduces Django functionality and makes some sort of design decision.
|
that introduces Django functionality and makes some sort of design decision.
|
||||||
|
|
||||||
If you provide a non-trivial patch, include evidence that alternatives have
|
If you provide a non-trivial patch, include evidence that alternatives have
|
||||||
been discussed on |django-developers|.
|
been discussed on |django-developers|.
|
||||||
|
|
||||||
If you're not sure whether your patch should be considered non-trivial, just
|
If you're not sure whether your patch should be considered non-trivial, ask on
|
||||||
ask.
|
the ticket for opinions.
|
||||||
|
|
||||||
.. _deprecating-a-feature:
|
.. _deprecating-a-feature:
|
||||||
|
|
||||||
|
|
|
@ -45,10 +45,10 @@ test dependencies. If you don't have an optional dependency installed, the
|
||||||
tests that require it will be skipped.
|
tests that require it will be skipped.
|
||||||
|
|
||||||
Running the tests requires a Django settings module that defines the databases
|
Running the tests requires a Django settings module that defines the databases
|
||||||
to use. To make it easy to get started, Django provides and uses a sample
|
to use. To help you get started, Django provides and uses a sample settings
|
||||||
settings module that uses the SQLite database. See
|
module that uses the SQLite database. See :ref:`running-unit-tests-settings` to
|
||||||
:ref:`running-unit-tests-settings` to learn how to use a different settings
|
learn how to use a different settings module to run the tests with a different
|
||||||
module to run the tests with a different database.
|
database.
|
||||||
|
|
||||||
Having problems? See :ref:`troubleshooting-unit-tests` for some common issues.
|
Having problems? See :ref:`troubleshooting-unit-tests` for some common issues.
|
||||||
|
|
||||||
|
@ -199,7 +199,7 @@ internationalization, type:
|
||||||
How do you find out the names of individual tests? Look in ``tests/`` — each
|
How do you find out the names of individual tests? Look in ``tests/`` — each
|
||||||
directory name there is the name of a test.
|
directory name there is the name of a test.
|
||||||
|
|
||||||
If you just want to run a particular class of tests, you can specify a list of
|
If you want to run only a particular class of tests, you can specify a list of
|
||||||
paths to individual test classes. For example, to run the ``TranslationTests``
|
paths to individual test classes. For example, to run the ``TranslationTests``
|
||||||
of the ``i18n`` module, type:
|
of the ``i18n`` module, type:
|
||||||
|
|
||||||
|
|
|
@ -98,7 +98,7 @@ necessary::
|
||||||
Publishing work
|
Publishing work
|
||||||
---------------
|
---------------
|
||||||
|
|
||||||
You can publish your work on GitHub just by doing::
|
You can publish your work on GitHub by running::
|
||||||
|
|
||||||
git push origin ticket_xxxxx
|
git push origin ticket_xxxxx
|
||||||
|
|
||||||
|
@ -186,9 +186,9 @@ the changes::
|
||||||
git push -f origin ticket_xxxxx
|
git push -f origin ticket_xxxxx
|
||||||
|
|
||||||
Note that this will rewrite history of ticket_xxxxx - if you check the commit
|
Note that this will rewrite history of ticket_xxxxx - if you check the commit
|
||||||
hashes before and after the operation at GitHub you will notice that the
|
hashes before and after the operation at GitHub you will notice that the commit
|
||||||
commit hashes do not match anymore. This is acceptable, as the branch is merely
|
hashes do not match anymore. This is acceptable, as the branch is a topic
|
||||||
a topic branch, and nobody should be basing their work on it.
|
branch, and nobody should be basing their work on it.
|
||||||
|
|
||||||
After upstream has changed
|
After upstream has changed
|
||||||
--------------------------
|
--------------------------
|
||||||
|
|
|
@ -201,15 +201,15 @@ documentation:
|
||||||
This is because Sphinx will generate proper links for the latter, which
|
This is because Sphinx will generate proper links for the latter, which
|
||||||
greatly helps readers.
|
greatly helps readers.
|
||||||
|
|
||||||
You can prefix the target with a ``~`` (that's a tilde) to get just the
|
You can prefix the target with a ``~`` (that's a tilde) to get only the
|
||||||
"last bit" of that path. So ``:mod:`~django.contrib.auth``` will just
|
"last bit" of that path. So ``:mod:`~django.contrib.auth``` will
|
||||||
display a link with the title "auth".
|
display a link with the title "auth".
|
||||||
|
|
||||||
* Use :mod:`~sphinx.ext.intersphinx` to reference Python's and Sphinx'
|
* Use :mod:`~sphinx.ext.intersphinx` to reference Python's and Sphinx'
|
||||||
documentation.
|
documentation.
|
||||||
|
|
||||||
* Add ``.. code-block:: <lang>`` to literal blocks so that they get
|
* Add ``.. code-block:: <lang>`` to literal blocks so that they get
|
||||||
highlighted. Prefer relying on automatic highlighting simply using ``::``
|
highlighted. Prefer relying on automatic highlighting using ``::``
|
||||||
(two colons). This has the benefit that if the code contains some invalid
|
(two colons). This has the benefit that if the code contains some invalid
|
||||||
syntax, it won't be highlighted. Adding ``.. code-block:: python``, for
|
syntax, it won't be highlighted. Adding ``.. code-block:: python``, for
|
||||||
example, will force highlighting despite invalid syntax.
|
example, will force highlighting despite invalid syntax.
|
||||||
|
@ -383,8 +383,8 @@ If a function, attribute, etc. is added, it's also okay to use a
|
||||||
|
|
||||||
An author's middle name.
|
An author's middle name.
|
||||||
|
|
||||||
We can simply remove the ``.. versionadded:: A.B`` annotation without any
|
We can remove the ``.. versionadded:: A.B`` annotation without any indentation
|
||||||
indentation changes when the time comes.
|
changes when the time comes.
|
||||||
|
|
||||||
Minimizing images
|
Minimizing images
|
||||||
=================
|
=================
|
||||||
|
|
|
@ -70,10 +70,10 @@ documentation, test suite, packaging scripts and other miscellaneous bits.
|
||||||
Django's code will be present in your clone as a directory named
|
Django's code will be present in your clone as a directory named
|
||||||
``django``.
|
``django``.
|
||||||
|
|
||||||
To try out the in-development code with your own applications, simply place
|
To try out the in-development code with your own applications, place the
|
||||||
the directory containing your clone on your Python import path. Then
|
directory containing your clone on your Python import path. Then ``import``
|
||||||
``import`` statements which look for Django will find the ``django`` module
|
statements which look for Django will find the ``django`` module within your
|
||||||
within your clone.
|
clone.
|
||||||
|
|
||||||
If you're going to be working on Django's code (say, to fix a bug or
|
If you're going to be working on Django's code (say, to fix a bug or
|
||||||
develop a new feature), you can probably stop reading here and move
|
develop a new feature), you can probably stop reading here and move
|
||||||
|
|
|
@ -172,7 +172,7 @@ OK, this is the fun part, where we actually push out a release!
|
||||||
|
|
||||||
#. If this is a security release, merge the appropriate patches from
|
#. If this is a security release, merge the appropriate patches from
|
||||||
``django-security``. Rebase these patches as necessary to make each one a
|
``django-security``. Rebase these patches as necessary to make each one a
|
||||||
simple commit on the release branch rather than a merge commit. To ensure
|
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::
|
||||||
|
|
||||||
$ git checkout stable/1.5.x
|
$ git checkout stable/1.5.x
|
||||||
|
|
|
@ -163,8 +163,8 @@ notification of security issues is not and will not be made public.
|
||||||
We also aim to keep this list as small as effectively possible, in
|
We also aim to keep this list as small as effectively possible, in
|
||||||
order to better manage the flow of confidential information prior to
|
order to better manage the flow of confidential information prior to
|
||||||
disclosure. As such, our notification list is *not* simply a list of
|
disclosure. As such, our notification list is *not* simply a list of
|
||||||
users of Django, and merely being a user of Django is not sufficient
|
users of Django, and being a user of Django is not sufficient reason
|
||||||
reason to be placed on the notification list.
|
to be placed on the notification list.
|
||||||
|
|
||||||
In broad terms, recipients of security notifications fall into three
|
In broad terms, recipients of security notifications fall into three
|
||||||
groups:
|
groups:
|
||||||
|
|
|
@ -10,8 +10,9 @@ in Django that you'd like to see fixed, or maybe there's a small feature you
|
||||||
want added.
|
want added.
|
||||||
|
|
||||||
Contributing back to Django itself is the best way to see your own concerns
|
Contributing back to Django itself is the best way to see your own concerns
|
||||||
addressed. This may seem daunting at first, but it's really pretty simple.
|
addressed. This may seem daunting at first, but it's a well-traveled path with
|
||||||
We'll walk you through the entire process, so you can learn by example.
|
documentation, tooling, and a community to support you. We'll walk you through
|
||||||
|
the entire process, so you can learn by example.
|
||||||
|
|
||||||
Who's this tutorial for?
|
Who's this tutorial for?
|
||||||
------------------------
|
------------------------
|
||||||
|
@ -387,7 +388,7 @@ Running Django's test suite for the second time
|
||||||
===============================================
|
===============================================
|
||||||
|
|
||||||
Once you've verified that your patch and your test are working correctly, it's
|
Once you've verified that your patch and your test are working correctly, it's
|
||||||
a good idea to run the entire Django test suite just to verify that your change
|
a good idea to run the entire Django test suite to verify that your change
|
||||||
hasn't introduced any bugs into other areas of Django. While successfully
|
hasn't introduced any bugs into other areas of Django. While successfully
|
||||||
passing the entire test suite doesn't guarantee your code is bug free, it does
|
passing the entire test suite doesn't guarantee your code is bug free, it does
|
||||||
help identify many bugs and regressions that might otherwise go unnoticed.
|
help identify many bugs and regressions that might otherwise go unnoticed.
|
||||||
|
@ -592,7 +593,7 @@ If you just want to get started already (and nobody would blame you!), try
|
||||||
taking a look at the list of `easy tickets that need patches`__ and the
|
taking a look at the list of `easy tickets that need patches`__ and the
|
||||||
`easy tickets that have patches which need improvement`__. If you're familiar
|
`easy tickets that have patches which need improvement`__. If you're familiar
|
||||||
with writing tests, you can also look at the list of
|
with writing tests, you can also look at the list of
|
||||||
`easy tickets that need tests`__. Just remember to follow the guidelines about
|
`easy tickets that need tests`__. Remember to follow the guidelines about
|
||||||
claiming tickets that were mentioned in the link to Django's documentation on
|
claiming tickets that were mentioned in the link to Django's documentation on
|
||||||
:doc:`claiming tickets and submitting patches
|
:doc:`claiming tickets and submitting patches
|
||||||
</internals/contributing/writing-code/submitting-patches>`.
|
</internals/contributing/writing-code/submitting-patches>`.
|
||||||
|
|
|
@ -4,8 +4,8 @@ Quick install guide
|
||||||
|
|
||||||
Before you can use Django, you'll need to get it installed. We have a
|
Before you can use Django, you'll need to get it installed. We have a
|
||||||
:doc:`complete installation guide </topics/install>` that covers all the
|
:doc:`complete installation guide </topics/install>` that covers all the
|
||||||
possibilities; this guide will guide you to a simple, minimal installation
|
possibilities; this guide will guide you to a minimal installation that'll work
|
||||||
that'll work while you walk through the introduction.
|
while you walk through the introduction.
|
||||||
|
|
||||||
Install Python
|
Install Python
|
||||||
==============
|
==============
|
||||||
|
@ -37,7 +37,7 @@ the :ref:`database installation information <database-installation>`.
|
||||||
Install Django
|
Install Django
|
||||||
==============
|
==============
|
||||||
|
|
||||||
You've got three easy options to install Django:
|
You've got three options to install Django:
|
||||||
|
|
||||||
* :ref:`Install an official release <installing-official-release>`. This
|
* :ref:`Install an official release <installing-official-release>`. This
|
||||||
is the best approach for most users.
|
is the best approach for most users.
|
||||||
|
|
|
@ -144,8 +144,8 @@ A dynamic admin interface: it's not just scaffolding -- it's the whole house
|
||||||
|
|
||||||
Once your models are defined, Django can automatically create a professional,
|
Once your models are defined, Django can automatically create a professional,
|
||||||
production ready :doc:`administrative interface </ref/contrib/admin/index>` --
|
production ready :doc:`administrative interface </ref/contrib/admin/index>` --
|
||||||
a website that lets authenticated users add, change and delete objects. It's
|
a website that lets authenticated users add, change and delete objects. The
|
||||||
as easy as registering your model in the admin site:
|
only step required is to register your model in the admin site:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
:caption: mysite/news/models.py
|
:caption: mysite/news/models.py
|
||||||
|
@ -169,7 +169,7 @@ as easy as registering your model in the admin site:
|
||||||
|
|
||||||
The philosophy here is that your site is edited by a staff, or a client, or
|
The philosophy here is that your site is edited by a staff, or a client, or
|
||||||
maybe just you -- and you don't want to have to deal with creating backend
|
maybe just you -- and you don't want to have to deal with creating backend
|
||||||
interfaces just to manage content.
|
interfaces only to manage content.
|
||||||
|
|
||||||
One typical workflow in creating Django apps is to create models and get the
|
One typical workflow in creating Django apps is to create models and get the
|
||||||
admin sites up and running as fast as possible, so your staff (or clients) can
|
admin sites up and running as fast as possible, so your staff (or clients) can
|
||||||
|
@ -183,9 +183,9 @@ application. Django encourages beautiful URL design and doesn't put any cruft
|
||||||
in URLs, like ``.php`` or ``.asp``.
|
in URLs, like ``.php`` or ``.asp``.
|
||||||
|
|
||||||
To design URLs for an app, you create a Python module called a :doc:`URLconf
|
To design URLs for an app, you create a Python module called a :doc:`URLconf
|
||||||
</topics/http/urls>`. A table of contents for your app, it contains a simple
|
</topics/http/urls>`. A table of contents for your app, it contains a mapping
|
||||||
mapping between URL patterns and Python callback functions. URLconfs also serve
|
between URL patterns and Python callback functions. URLconfs also serve to
|
||||||
to decouple URLs from Python code.
|
decouple URLs from Python code.
|
||||||
|
|
||||||
Here's what a URLconf might look like for the ``Reporter``/``Article``
|
Here's what a URLconf might look like for the ``Reporter``/``Article``
|
||||||
example above:
|
example above:
|
||||||
|
@ -315,12 +315,12 @@ Here's what the "base.html" template, including the use of :doc:`static files
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
Simplistically, it defines the look-and-feel of the site (with the site's logo),
|
Simplistically, it defines the look-and-feel of the site (with the site's logo),
|
||||||
and provides "holes" for child templates to fill. This makes a site redesign as
|
and provides "holes" for child templates to fill. This means that a site redesign
|
||||||
easy as changing a single file -- the base template.
|
can be done by changing a single file -- the base template.
|
||||||
|
|
||||||
It also lets you create multiple versions of a site, with different base
|
It also lets you create multiple versions of a site, with different base
|
||||||
templates, while reusing child templates. Django's creators have used this
|
templates, while reusing child templates. Django's creators have used this
|
||||||
technique to create strikingly different mobile versions of sites -- simply by
|
technique to create strikingly different mobile versions of sites by only
|
||||||
creating a new base template.
|
creating a new base template.
|
||||||
|
|
||||||
Note that you don't have to use Django's template system if you prefer another
|
Note that you don't have to use Django's template system if you prefer another
|
||||||
|
@ -340,15 +340,14 @@ features:
|
||||||
* A :doc:`caching framework </topics/cache>` that integrates with memcached
|
* A :doc:`caching framework </topics/cache>` that integrates with memcached
|
||||||
or other backends.
|
or other backends.
|
||||||
|
|
||||||
* A :doc:`syndication framework </ref/contrib/syndication>` that makes
|
* A :doc:`syndication framework </ref/contrib/syndication>` that lets you
|
||||||
creating RSS and Atom feeds as easy as writing a small Python class.
|
create RSS and Atom feeds by writing a small Python class.
|
||||||
|
|
||||||
* More attractive automatically-generated admin features -- this overview
|
* More attractive automatically-generated admin features -- this overview
|
||||||
barely scratched the surface.
|
barely scratched the surface.
|
||||||
|
|
||||||
The next obvious steps are for you to `download Django`_, read :doc:`the
|
The next steps are for you to `download Django`_, read :doc:`the tutorial
|
||||||
tutorial </intro/tutorial01>` and join `the community`_. Thanks for your
|
</intro/tutorial01>` and join `the community`_. Thanks for your interest!
|
||||||
interest!
|
|
||||||
|
|
||||||
.. _download Django: https://www.djangoproject.com/download/
|
.. _download Django: https://www.djangoproject.com/download/
|
||||||
.. _the community: https://www.djangoproject.com/community/
|
.. _the community: https://www.djangoproject.com/community/
|
||||||
|
|
|
@ -20,7 +20,7 @@ Reusability is the way of life in Python. `The Python Package Index (PyPI)
|
||||||
<https://pypi.org/>`_ has a vast range of packages you can use in your own
|
<https://pypi.org/>`_ has a vast range of packages you can use in your own
|
||||||
Python programs. Check out `Django Packages <https://djangopackages.org>`_ for
|
Python programs. Check out `Django Packages <https://djangopackages.org>`_ for
|
||||||
existing reusable apps you could incorporate in your project. Django itself is
|
existing reusable apps you could incorporate in your project. Django itself is
|
||||||
also just a Python package. This means that you can take existing Python
|
also a normal Python package. This means that you can take existing Python
|
||||||
packages or Django apps and compose them into your own web project. You only
|
packages or Django apps and compose them into your own web project. You only
|
||||||
need to write the parts that make your project unique.
|
need to write the parts that make your project unique.
|
||||||
|
|
||||||
|
@ -41,8 +41,8 @@ projects and ready to publish for others to install and use.
|
||||||
bar``. For a directory (like ``polls``) to form a package, it must contain
|
bar``. For a directory (like ``polls``) to form a package, it must contain
|
||||||
a special file ``__init__.py``, even if this file is empty.
|
a special file ``__init__.py``, even if this file is empty.
|
||||||
|
|
||||||
A Django *application* is just a Python package that is specifically
|
A Django *application* is a Python package that is specifically intended
|
||||||
intended for use in a Django project. An application may use common Django
|
for use in a Django project. An application may use common Django
|
||||||
conventions, such as having ``models``, ``tests``, ``urls``, and ``views``
|
conventions, such as having ``models``, ``tests``, ``urls``, and ``views``
|
||||||
submodules.
|
submodules.
|
||||||
|
|
||||||
|
@ -148,8 +148,8 @@ this. For a small app like polls, this process isn't too difficult.
|
||||||
Polls
|
Polls
|
||||||
=====
|
=====
|
||||||
|
|
||||||
Polls is a simple Django app to conduct Web-based polls. For each
|
Polls is a Django app to conduct Web-based polls. For each question,
|
||||||
question, visitors can choose between a fixed number of answers.
|
visitors can choose between a fixed number of answers.
|
||||||
|
|
||||||
Detailed documentation is in the "docs" directory.
|
Detailed documentation is in the "docs" directory.
|
||||||
|
|
||||||
|
@ -206,7 +206,7 @@ this. For a small app like polls, this process isn't too difficult.
|
||||||
packages=find_packages(),
|
packages=find_packages(),
|
||||||
include_package_data=True,
|
include_package_data=True,
|
||||||
license='BSD License', # example license
|
license='BSD License', # example license
|
||||||
description='A simple Django app to conduct Web-based polls.',
|
description='A Django app to conduct Web-based polls.',
|
||||||
long_description=README,
|
long_description=README,
|
||||||
url='https://www.example.com/',
|
url='https://www.example.com/',
|
||||||
author='Your Name',
|
author='Your Name',
|
||||||
|
|
|
@ -90,9 +90,8 @@ Let's look at what :djadmin:`startproject` created::
|
||||||
|
|
||||||
These files are:
|
These files are:
|
||||||
|
|
||||||
* The outer :file:`mysite/` root directory is just a container for your
|
* The outer :file:`mysite/` root directory is a container for your project. Its
|
||||||
project. Its name doesn't matter to Django; you can rename it to anything
|
name doesn't matter to Django; you can rename it to anything you like.
|
||||||
you like.
|
|
||||||
|
|
||||||
* :file:`manage.py`: A command-line utility that lets you interact with this
|
* :file:`manage.py`: A command-line utility that lets you interact with this
|
||||||
Django project in various ways. You can read all the details about
|
Django project in various ways. You can read all the details about
|
||||||
|
@ -207,7 +206,7 @@ rather than creating directories.
|
||||||
|
|
||||||
What's the difference between a project and an app? An app is a Web
|
What's the difference between a project and an app? An app is a Web
|
||||||
application that does something -- e.g., a Weblog system, a database of
|
application that does something -- e.g., a Weblog system, a database of
|
||||||
public records or a simple poll app. A project is a collection of
|
public records or a small poll app. A project is a collection of
|
||||||
configuration and apps for a particular website. A project can contain
|
configuration and apps for a particular website. A project can contain
|
||||||
multiple apps. An app can be in multiple projects.
|
multiple apps. An app can be in multiple projects.
|
||||||
|
|
||||||
|
|
|
@ -123,16 +123,16 @@ additional metadata.
|
||||||
place and automatically derive things from it.
|
place and automatically derive things from it.
|
||||||
|
|
||||||
This includes the migrations - unlike in Ruby On Rails, for example, migrations
|
This includes the migrations - unlike in Ruby On Rails, for example, migrations
|
||||||
are entirely derived from your models file, and are essentially just a
|
are entirely derived from your models file, and are essentially a
|
||||||
history that Django can roll through to update your database schema to
|
history that Django can roll through to update your database schema to
|
||||||
match your current models.
|
match your current models.
|
||||||
|
|
||||||
In our simple poll app, we'll create two models: ``Question`` and ``Choice``.
|
In our poll app, we'll create two models: ``Question`` and ``Choice``. A
|
||||||
A ``Question`` has a question and a publication date. A ``Choice`` has two
|
``Question`` has a question and a publication date. A ``Choice`` has two
|
||||||
fields: the text of the choice and a vote tally. Each ``Choice`` is associated
|
fields: the text of the choice and a vote tally. Each ``Choice`` is associated
|
||||||
with a ``Question``.
|
with a ``Question``.
|
||||||
|
|
||||||
These concepts are represented by simple Python classes. Edit the
|
These concepts are represented by Python classes. Edit the
|
||||||
:file:`polls/models.py` file so it looks like this:
|
:file:`polls/models.py` file so it looks like this:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
@ -151,9 +151,9 @@ These concepts are represented by simple Python classes. Edit the
|
||||||
choice_text = models.CharField(max_length=200)
|
choice_text = models.CharField(max_length=200)
|
||||||
votes = models.IntegerField(default=0)
|
votes = models.IntegerField(default=0)
|
||||||
|
|
||||||
The code is straightforward. Each model is represented by a class that
|
Here, each model is represented by a class that subclasses
|
||||||
subclasses :class:`django.db.models.Model`. Each model has a number of class
|
:class:`django.db.models.Model`. Each model has a number of class variables,
|
||||||
variables, each of which represents a database field in the model.
|
each of which represents a database field in the model.
|
||||||
|
|
||||||
Each field is represented by an instance of a :class:`~django.db.models.Field`
|
Each field is represented by an instance of a :class:`~django.db.models.Field`
|
||||||
class -- e.g., :class:`~django.db.models.CharField` for character fields and
|
class -- e.g., :class:`~django.db.models.CharField` for character fields and
|
||||||
|
@ -245,11 +245,11 @@ some changes to your models (in this case, you've made new ones) and that
|
||||||
you'd like the changes to be stored as a *migration*.
|
you'd like the changes to be stored as a *migration*.
|
||||||
|
|
||||||
Migrations are how Django stores changes to your models (and thus your
|
Migrations are how Django stores changes to your models (and thus your
|
||||||
database schema) - they're just files on disk. You can read the migration
|
database schema) - they're files on disk. You can read the migration for your
|
||||||
for your new model if you like; it's the file
|
new model if you like; it's the file ``polls/migrations/0001_initial.py``.
|
||||||
``polls/migrations/0001_initial.py``. Don't worry, you're not expected to read
|
Don't worry, you're not expected to read them every time Django makes one, but
|
||||||
them every time Django makes one, but they're designed to be human-editable
|
they're designed to be human-editable in case you want to manually tweak how
|
||||||
in case you want to manually tweak how Django changes things.
|
Django changes things.
|
||||||
|
|
||||||
There's a command that will run the migrations for you and manage your database
|
There's a command that will run the migrations for you and manage your database
|
||||||
schema automatically - that's called :djadmin:`migrate`, and we'll come to it in a
|
schema automatically - that's called :djadmin:`migrate`, and we'll come to it in a
|
||||||
|
@ -311,7 +311,7 @@ Note the following:
|
||||||
(Yes, you can override this, as well.)
|
(Yes, you can override this, as well.)
|
||||||
|
|
||||||
* The foreign key relationship is made explicit by a ``FOREIGN KEY``
|
* The foreign key relationship is made explicit by a ``FOREIGN KEY``
|
||||||
constraint. Don't worry about the ``DEFERRABLE`` parts; that's just telling
|
constraint. Don't worry about the ``DEFERRABLE`` parts; it's telling
|
||||||
PostgreSQL to not enforce the foreign key until the end of the transaction.
|
PostgreSQL to not enforce the foreign key until the end of the transaction.
|
||||||
|
|
||||||
* It's tailored to the database you're using, so database-specific field types
|
* It's tailored to the database you're using, so database-specific field types
|
||||||
|
@ -321,7 +321,7 @@ Note the following:
|
||||||
single quotes.
|
single quotes.
|
||||||
|
|
||||||
* The :djadmin:`sqlmigrate` command doesn't actually run the migration on your
|
* The :djadmin:`sqlmigrate` command doesn't actually run the migration on your
|
||||||
database - it just prints it to the screen so that you can see what SQL
|
database - instead, it prints it to the screen so that you can see what SQL
|
||||||
Django thinks is required. It's useful for checking what Django is going to
|
Django thinks is required. It's useful for checking what Django is going to
|
||||||
do or if you have database administrators who require SQL scripts for
|
do or if you have database administrators who require SQL scripts for
|
||||||
changes.
|
changes.
|
||||||
|
@ -640,9 +640,9 @@ Make the poll app modifiable in the admin
|
||||||
|
|
||||||
But where's our poll app? It's not displayed on the admin index page.
|
But where's our poll app? It's not displayed on the admin index page.
|
||||||
|
|
||||||
Just one thing to do: we need to tell the admin that ``Question``
|
Only one more thing to do: we need to tell the admin that ``Question`` objects
|
||||||
objects have an admin interface. To do this, open the :file:`polls/admin.py`
|
have an admin interface. To do this, open the :file:`polls/admin.py` file, and
|
||||||
file, and edit it to look like this:
|
edit it to look like this:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
:caption: polls/admin.py
|
:caption: polls/admin.py
|
||||||
|
|
|
@ -40,16 +40,16 @@ In our poll application, we'll have the following four views:
|
||||||
question.
|
question.
|
||||||
|
|
||||||
In Django, web pages and other content are delivered by views. Each view is
|
In Django, web pages and other content are delivered by views. Each view is
|
||||||
represented by a simple Python function (or method, in the case of class-based
|
represented by a Python function (or method, in the case of class-based views).
|
||||||
views). Django will choose a view by examining the URL that's requested (to be
|
Django will choose a view by examining the URL that's requested (to be precise,
|
||||||
precise, the part of the URL after the domain name).
|
the part of the URL after the domain name).
|
||||||
|
|
||||||
Now in your time on the web you may have come across such beauties as
|
Now in your time on the web you may have come across such beauties as
|
||||||
"ME2/Sites/dirmod.asp?sid=&type=gen&mod=Core+Pages&gid=A6CD4967199A42D9B65B1B".
|
"ME2/Sites/dirmod.asp?sid=&type=gen&mod=Core+Pages&gid=A6CD4967199A42D9B65B1B".
|
||||||
You will be pleased to know that Django allows us much more elegant
|
You will be pleased to know that Django allows us much more elegant
|
||||||
*URL patterns* than that.
|
*URL patterns* than that.
|
||||||
|
|
||||||
A URL pattern is simply the general form of a URL - for example:
|
A URL pattern is the general form of a URL - for example:
|
||||||
``/newsarchive/<year>/<month>/``.
|
``/newsarchive/<year>/<month>/``.
|
||||||
|
|
||||||
To get from a URL to a view, Django uses what are known as 'URLconfs'. A
|
To get from a URL to a view, Django uses what are known as 'URLconfs'. A
|
||||||
|
@ -181,7 +181,7 @@ directory called ``polls``, and within that create a file called
|
||||||
``index.html``. In other words, your template should be at
|
``index.html``. In other words, your template should be at
|
||||||
``polls/templates/polls/index.html``. Because of how the ``app_directories``
|
``polls/templates/polls/index.html``. Because of how the ``app_directories``
|
||||||
template loader works as described above, you can refer to this template within
|
template loader works as described above, you can refer to this template within
|
||||||
Django simply as ``polls/index.html``.
|
Django as ``polls/index.html``.
|
||||||
|
|
||||||
.. admonition:: Template namespacing
|
.. admonition:: Template namespacing
|
||||||
|
|
||||||
|
@ -190,7 +190,7 @@ Django simply as ``polls/index.html``.
|
||||||
but it would actually be a bad idea. Django will choose the first template
|
but it would actually be a bad idea. Django will choose the first template
|
||||||
it finds whose name matches, and if you had a template with the same name
|
it finds whose name matches, and if you had a template with the same name
|
||||||
in a *different* application, Django would be unable to distinguish between
|
in a *different* application, Django would be unable to distinguish between
|
||||||
them. We need to be able to point Django at the right one, and the easiest
|
them. We need to be able to point Django at the right one, and the best
|
||||||
way to ensure this is by *namespacing* them. That is, by putting those
|
way to ensure this is by *namespacing* them. That is, by putting those
|
||||||
templates inside *another* directory named for the application itself.
|
templates inside *another* directory named for the application itself.
|
||||||
|
|
||||||
|
@ -455,4 +455,5 @@ to point at the namespaced detail view:
|
||||||
<li><a href="{% url 'polls:detail' question.id %}">{{ question.question_text }}</a></li>
|
<li><a href="{% url 'polls:detail' question.id %}">{{ question.question_text }}</a></li>
|
||||||
|
|
||||||
When you're comfortable with writing views, read :doc:`part 4 of this tutorial
|
When you're comfortable with writing views, read :doc:`part 4 of this tutorial
|
||||||
</intro/tutorial04>` to learn about simple form processing and generic views.
|
</intro/tutorial04>` to learn the basics about form processing and generic
|
||||||
|
views.
|
||||||
|
|
|
@ -3,11 +3,11 @@ Writing your first Django app, part 4
|
||||||
=====================================
|
=====================================
|
||||||
|
|
||||||
This tutorial begins where :doc:`Tutorial 3 </intro/tutorial03>` left off. We're
|
This tutorial begins where :doc:`Tutorial 3 </intro/tutorial03>` left off. We're
|
||||||
continuing the Web-poll application and will focus on simple form processing and
|
continuing the Web-poll application and will focus on form processing and
|
||||||
cutting down our code.
|
cutting down our code.
|
||||||
|
|
||||||
Write a simple form
|
Write a minimal form
|
||||||
===================
|
====================
|
||||||
|
|
||||||
Let's update our poll detail template ("polls/detail.html") from the last
|
Let's update our poll detail template ("polls/detail.html") from the last
|
||||||
tutorial, so that the template contains an HTML ``<form>`` element:
|
tutorial, so that the template contains an HTML ``<form>`` element:
|
||||||
|
@ -42,17 +42,17 @@ A quick rundown:
|
||||||
``method="get"``) is very important, because the act of submitting this
|
``method="get"``) is very important, because the act of submitting this
|
||||||
form will alter data server-side. Whenever you create a form that alters
|
form will alter data server-side. Whenever you create a form that alters
|
||||||
data server-side, use ``method="post"``. This tip isn't specific to
|
data server-side, use ``method="post"``. This tip isn't specific to
|
||||||
Django; it's just good Web development practice.
|
Django; it's good Web development practice in general.
|
||||||
|
|
||||||
* ``forloop.counter`` indicates how many times the :ttag:`for` tag has gone
|
* ``forloop.counter`` indicates how many times the :ttag:`for` tag has gone
|
||||||
through its loop
|
through its loop
|
||||||
|
|
||||||
* Since we're creating a POST form (which can have the effect of modifying
|
* Since we're creating a POST form (which can have the effect of modifying
|
||||||
data), we need to worry about Cross Site Request Forgeries.
|
data), we need to worry about Cross Site Request Forgeries.
|
||||||
Thankfully, you don't have to worry too hard, because Django comes with
|
Thankfully, you don't have to worry too hard, because Django comes with a
|
||||||
a very easy-to-use system for protecting against it. In short, all POST
|
helpful system for protecting against it. In short, all POST forms that are
|
||||||
forms that are targeted at internal URLs should use the
|
targeted at internal URLs should use the :ttag:`{% csrf_token %}<csrf_token>`
|
||||||
:ttag:`{% csrf_token %}<csrf_token>` template tag.
|
template tag.
|
||||||
|
|
||||||
Now, let's create a Django view that handles the submitted data and does
|
Now, let's create a Django view that handles the submitted data and does
|
||||||
something with it. Remember, in :doc:`Tutorial 3 </intro/tutorial03>`, we
|
something with it. Remember, in :doc:`Tutorial 3 </intro/tutorial03>`, we
|
||||||
|
@ -121,8 +121,8 @@ This code includes a few things we haven't covered yet in this tutorial:
|
||||||
|
|
||||||
As the Python comment above points out, you should always return an
|
As the Python comment above points out, you should always return an
|
||||||
:class:`~django.http.HttpResponseRedirect` after successfully dealing with
|
:class:`~django.http.HttpResponseRedirect` after successfully dealing with
|
||||||
POST data. This tip isn't specific to Django; it's just good Web
|
POST data. This tip isn't specific to Django; it's good Web development
|
||||||
development practice.
|
practice in general.
|
||||||
|
|
||||||
* We are using the :func:`~django.urls.reverse` function in the
|
* We are using the :func:`~django.urls.reverse` function in the
|
||||||
:class:`~django.http.HttpResponseRedirect` constructor in this example.
|
:class:`~django.http.HttpResponseRedirect` constructor in this example.
|
||||||
|
@ -196,7 +196,7 @@ Use generic views: Less code is better
|
||||||
======================================
|
======================================
|
||||||
|
|
||||||
The ``detail()`` (from :doc:`Tutorial 3 </intro/tutorial03>`) and ``results()``
|
The ``detail()`` (from :doc:`Tutorial 3 </intro/tutorial03>`) and ``results()``
|
||||||
views are very simple -- and, as mentioned above, redundant. The ``index()``
|
views are very short -- and, as mentioned above, redundant. The ``index()``
|
||||||
view, which displays a list of polls, is similar.
|
view, which displays a list of polls, is similar.
|
||||||
|
|
||||||
These views represent a common case of basic Web development: getting data from
|
These views represent a common case of basic Web development: getting data from
|
||||||
|
@ -208,8 +208,8 @@ Generic views abstract common patterns to the point where you don't even need
|
||||||
to write Python code to write an app.
|
to write Python code to write an app.
|
||||||
|
|
||||||
Let's convert our poll app to use the generic views system, so we can delete a
|
Let's convert our poll app to use the generic views system, so we can delete a
|
||||||
bunch of our own code. We'll just have to take a few steps to make the
|
bunch of our own code. We'll have to take a few steps to make the conversion.
|
||||||
conversion. We will:
|
We will:
|
||||||
|
|
||||||
#. Convert the URLconf.
|
#. Convert the URLconf.
|
||||||
|
|
||||||
|
@ -331,8 +331,8 @@ However, for ListView, the automatically generated context variable is
|
||||||
``question_list``. To override this we provide the ``context_object_name``
|
``question_list``. To override this we provide the ``context_object_name``
|
||||||
attribute, specifying that we want to use ``latest_question_list`` instead.
|
attribute, specifying that we want to use ``latest_question_list`` instead.
|
||||||
As an alternative approach, you could change your templates to match
|
As an alternative approach, you could change your templates to match
|
||||||
the new default context variables -- but it's a lot easier to just
|
the new default context variables -- but it's a lot easier to tell Django to
|
||||||
tell Django to use the variable you want.
|
use the variable you want.
|
||||||
|
|
||||||
Run the server, and use your new polling app based on generic views.
|
Run the server, and use your new polling app based on generic views.
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@ Introducing automated testing
|
||||||
What are automated tests?
|
What are automated tests?
|
||||||
-------------------------
|
-------------------------
|
||||||
|
|
||||||
Tests are simple routines that check the operation of your code.
|
Tests are routines that check the operation of your code.
|
||||||
|
|
||||||
Testing operates at different levels. Some tests might apply to a tiny detail
|
Testing operates at different levels. Some tests might apply to a tiny detail
|
||||||
(*does a particular model method return values as expected?*) while others
|
(*does a particular model method return values as expected?*) while others
|
||||||
|
@ -51,7 +51,7 @@ interactions between components.
|
||||||
A change in any of those components could have unexpected consequences on the
|
A change in any of those components could have unexpected consequences on the
|
||||||
application's behavior. Checking that it still 'seems to work' could mean
|
application's behavior. Checking that it still 'seems to work' could mean
|
||||||
running through your code's functionality with twenty different variations of
|
running through your code's functionality with twenty different variations of
|
||||||
your test data just to make sure you haven't broken something - not a good use
|
your test data to make sure you haven't broken something - not a good use
|
||||||
of your time.
|
of your time.
|
||||||
|
|
||||||
That's especially true when automated tests could do this for you in seconds.
|
That's especially true when automated tests could do this for you in seconds.
|
||||||
|
@ -83,9 +83,9 @@ Tests make your code more attractive
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
You might have created a brilliant piece of software, but you will find that
|
You might have created a brilliant piece of software, but you will find that
|
||||||
many other developers will simply refuse to look at it because it lacks tests;
|
many other developers will refuse to look at it because it lacks tests; without
|
||||||
without tests, they won't trust it. Jacob Kaplan-Moss, one of Django's
|
tests, they won't trust it. Jacob Kaplan-Moss, one of Django's original
|
||||||
original developers, says "Code without tests is broken by design."
|
developers, says "Code without tests is broken by design."
|
||||||
|
|
||||||
That other developers want to see tests in your software before they take it
|
That other developers want to see tests in your software before they take it
|
||||||
seriously is yet another reason for you to start writing tests.
|
seriously is yet another reason for you to start writing tests.
|
||||||
|
@ -108,7 +108,7 @@ Some programmers follow a discipline called "`test-driven development`_"; they
|
||||||
actually write their tests before they write their code. This might seem
|
actually write their tests before they write their code. This might seem
|
||||||
counter-intuitive, but in fact it's similar to what most people will often do
|
counter-intuitive, but in fact it's similar to what most people will often do
|
||||||
anyway: they describe a problem, then create some code to solve it. Test-driven
|
anyway: they describe a problem, then create some code to solve it. Test-driven
|
||||||
development simply formalizes the problem in a Python test case.
|
development formalizes the problem in a Python test case.
|
||||||
|
|
||||||
More often, a newcomer to testing will create some code and later decide that
|
More often, a newcomer to testing will create some code and later decide that
|
||||||
it should have some tests. Perhaps it would have been better to write some
|
it should have some tests. Perhaps it would have been better to write some
|
||||||
|
@ -270,9 +270,9 @@ After identifying a bug, we wrote a test that exposes it and corrected the bug
|
||||||
in the code so our test passes.
|
in the code so our test passes.
|
||||||
|
|
||||||
Many other things might go wrong with our application in the future, but we can
|
Many other things might go wrong with our application in the future, but we can
|
||||||
be sure that we won't inadvertently reintroduce this bug, because simply
|
be sure that we won't inadvertently reintroduce this bug, because running the
|
||||||
running the test will warn us immediately. We can consider this little portion
|
test will warn us immediately. We can consider this little portion of the
|
||||||
of the application pinned down safely forever.
|
application pinned down safely forever.
|
||||||
|
|
||||||
More comprehensive tests
|
More comprehensive tests
|
||||||
------------------------
|
------------------------
|
||||||
|
@ -308,7 +308,7 @@ more comprehensively:
|
||||||
And now we have three tests that confirm that ``Question.was_published_recently()``
|
And now we have three tests that confirm that ``Question.was_published_recently()``
|
||||||
returns sensible values for past, recent, and future questions.
|
returns sensible values for past, recent, and future questions.
|
||||||
|
|
||||||
Again, ``polls`` is a simple application, but however complex it grows in the
|
Again, ``polls`` is a minimal application, but however complex it grows in the
|
||||||
future and whatever other code it interacts with, we now have some guarantee
|
future and whatever other code it interacts with, we now have some guarantee
|
||||||
that the method we have written tests for will behave in expected ways.
|
that the method we have written tests for will behave in expected ways.
|
||||||
|
|
||||||
|
@ -324,8 +324,8 @@ A test for a view
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
When we fixed the bug above, we wrote the test first and then the code to fix
|
When we fixed the bug above, we wrote the test first and then the code to fix
|
||||||
it. In fact that was a simple example of test-driven development, but it
|
it. In fact that was an example of test-driven development, but it doesn't
|
||||||
doesn't really matter in which order we do the work.
|
really matter in which order we do the work.
|
||||||
|
|
||||||
In our first test, we focused closely on the internal behavior of the code. For
|
In our first test, we focused closely on the internal behavior of the code. For
|
||||||
this test, we want to check its behavior as it would be experienced by a user
|
this test, we want to check its behavior as it would be experienced by a user
|
||||||
|
|
|
@ -11,11 +11,10 @@ to serve additional files — such as images, JavaScript, or CSS — necessary t
|
||||||
render the complete web page. In Django, we refer to these files as "static
|
render the complete web page. In Django, we refer to these files as "static
|
||||||
files".
|
files".
|
||||||
|
|
||||||
For small projects, this isn't a big deal, because you can just keep the
|
For small projects, this isn't a big deal, because you can keep the static
|
||||||
static files somewhere your web server can find it. However, in bigger
|
files somewhere your web server can find it. However, in bigger projects --
|
||||||
projects -- especially those comprised of multiple apps -- dealing with the
|
especially those comprised of multiple apps -- dealing with the multiple sets
|
||||||
multiple sets of static files provided by each application starts to get
|
of static files provided by each application starts to get tricky.
|
||||||
tricky.
|
|
||||||
|
|
||||||
That's what ``django.contrib.staticfiles`` is for: it collects static files
|
That's what ``django.contrib.staticfiles`` is for: it collects static files
|
||||||
from each of your applications (and any other places you specify) into a
|
from each of your applications (and any other places you specify) into a
|
||||||
|
@ -39,8 +38,8 @@ Within the ``static`` directory you have just created, create another directory
|
||||||
called ``polls`` and within that create a file called ``style.css``. In other
|
called ``polls`` and within that create a file called ``style.css``. In other
|
||||||
words, your stylesheet should be at ``polls/static/polls/style.css``. Because
|
words, your stylesheet should be at ``polls/static/polls/style.css``. Because
|
||||||
of how the ``AppDirectoriesFinder`` staticfile finder works, you can refer to
|
of how the ``AppDirectoriesFinder`` staticfile finder works, you can refer to
|
||||||
this static file in Django simply as ``polls/style.css``, similar to how you
|
this static file in Django as ``polls/style.css``, similar to how you reference
|
||||||
reference the path for templates.
|
the path for templates.
|
||||||
|
|
||||||
.. admonition:: Static file namespacing
|
.. admonition:: Static file namespacing
|
||||||
|
|
||||||
|
@ -50,8 +49,8 @@ reference the path for templates.
|
||||||
first static file it finds whose name matches, and if you had a static file
|
first static file it finds whose name matches, and if you had a static file
|
||||||
with the same name in a *different* application, Django would be unable to
|
with the same name in a *different* application, Django would be unable to
|
||||||
distinguish between them. We need to be able to point Django at the right
|
distinguish between them. We need to be able to point Django at the right
|
||||||
one, and the easiest way to ensure this is by *namespacing* them. That is,
|
one, and the best way to ensure this is by *namespacing* them. That is, by
|
||||||
by putting those static files inside *another* directory named for the
|
putting those static files inside *another* directory named for the
|
||||||
application itself.
|
application itself.
|
||||||
|
|
||||||
Put the following code in that stylesheet (``polls/static/polls/style.css``):
|
Put the following code in that stylesheet (``polls/static/polls/style.css``):
|
||||||
|
|
|
@ -79,7 +79,7 @@ OK, we have our Question admin page, but a ``Question`` has multiple
|
||||||
Yet.
|
Yet.
|
||||||
|
|
||||||
There are two ways to solve this problem. The first is to register ``Choice``
|
There are two ways to solve this problem. The first is to register ``Choice``
|
||||||
with the admin just as we did with ``Question``. That's easy:
|
with the admin just as we did with ``Question``:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
:caption: polls/admin.py
|
:caption: polls/admin.py
|
||||||
|
@ -159,8 +159,8 @@ that you can't remove the original three slots. This image shows an added slot:
|
||||||
|
|
||||||
One small problem, though. It takes a lot of screen space to display all the
|
One small problem, though. It takes a lot of screen space to display all the
|
||||||
fields for entering related ``Choice`` objects. For that reason, Django offers a
|
fields for entering related ``Choice`` objects. For that reason, Django offers a
|
||||||
tabular way of displaying inline related objects; you just need to change
|
tabular way of displaying inline related objects. To use it, change the
|
||||||
the ``ChoiceInline`` declaration to read:
|
``ChoiceInline`` declaration to read:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
:caption: polls/admin.py
|
:caption: polls/admin.py
|
||||||
|
@ -201,8 +201,8 @@ object:
|
||||||
# ...
|
# ...
|
||||||
list_display = ('question_text', 'pub_date')
|
list_display = ('question_text', 'pub_date')
|
||||||
|
|
||||||
Just for good measure, let's also include the ``was_published_recently()``
|
For good measure, let's also include the ``was_published_recently()`` method
|
||||||
method from :doc:`Tutorial 2 </intro/tutorial02>`:
|
from :doc:`Tutorial 2 </intro/tutorial02>`:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
:caption: polls/admin.py
|
:caption: polls/admin.py
|
||||||
|
@ -284,9 +284,8 @@ Customize the admin look and feel
|
||||||
Clearly, having "Django administration" at the top of each admin page is
|
Clearly, having "Django administration" at the top of each admin page is
|
||||||
ridiculous. It's just placeholder text.
|
ridiculous. It's just placeholder text.
|
||||||
|
|
||||||
That's easy to change, though, using Django's template system. The Django admin
|
You can change it, though, using Django's template system. The Django admin is
|
||||||
is powered by Django itself, and its interfaces use Django's own template
|
powered by Django itself, and its interfaces use Django's own template system.
|
||||||
system.
|
|
||||||
|
|
||||||
.. _ref-customizing-your-projects-templates:
|
.. _ref-customizing-your-projects-templates:
|
||||||
|
|
||||||
|
@ -346,7 +345,7 @@ template directory in the source code of Django itself
|
||||||
|
|
||||||
$ python -c "import django; print(django.__path__)"
|
$ python -c "import django; print(django.__path__)"
|
||||||
|
|
||||||
Then, just edit the file and replace
|
Then, edit the file and replace
|
||||||
``{{ site_header|default:_('Django administration') }}`` (including the curly
|
``{{ site_header|default:_('Django administration') }}`` (including the curly
|
||||||
braces) with your own site's name as you see fit. You should end up with
|
braces) with your own site's name as you see fit. You should end up with
|
||||||
a section of code like:
|
a section of code like:
|
||||||
|
@ -369,9 +368,8 @@ template language will be evaluated to produce the final HTML page, just like
|
||||||
we saw in :doc:`Tutorial 3 </intro/tutorial03>`.
|
we saw in :doc:`Tutorial 3 </intro/tutorial03>`.
|
||||||
|
|
||||||
Note that any of Django's default admin templates can be overridden. To
|
Note that any of Django's default admin templates can be overridden. To
|
||||||
override a template, just do the same thing you did with ``base_site.html`` --
|
override a template, do the same thing you did with ``base_site.html`` -- copy
|
||||||
copy it from the default directory into your custom directory, and make
|
it from the default directory into your custom directory, and make changes.
|
||||||
changes.
|
|
||||||
|
|
||||||
Customizing your *application's* templates
|
Customizing your *application's* templates
|
||||||
------------------------------------------
|
------------------------------------------
|
||||||
|
|
|
@ -13,9 +13,9 @@ Well, we've always been big fans of learning by doing. At this point you should
|
||||||
know enough to start a project of your own and start fooling around. As you need
|
know enough to start a project of your own and start fooling around. As you need
|
||||||
to learn new tricks, come back to the documentation.
|
to learn new tricks, come back to the documentation.
|
||||||
|
|
||||||
We've put a lot of effort into making Django's documentation useful, easy to
|
We've put a lot of effort into making Django's documentation useful, clear and
|
||||||
read and as complete as possible. The rest of this document explains more about
|
as complete as possible. The rest of this document explains more about how the
|
||||||
how the documentation works so that you can get the most out of it.
|
documentation works so that you can get the most out of it.
|
||||||
|
|
||||||
(Yes, this is documentation about documentation. Rest assured we have no plans
|
(Yes, this is documentation about documentation. Rest assured we have no plans
|
||||||
to write a document about how to read the document about documentation.)
|
to write a document about how to read the document about documentation.)
|
||||||
|
@ -74,8 +74,8 @@ different needs:
|
||||||
* Finally, there's some "specialized" documentation not usually relevant to
|
* Finally, there's some "specialized" documentation not usually relevant to
|
||||||
most developers. This includes the :doc:`release notes </releases/index>` and
|
most developers. This includes the :doc:`release notes </releases/index>` and
|
||||||
:doc:`internals documentation </internals/index>` for those who want to add
|
:doc:`internals documentation </internals/index>` for those who want to add
|
||||||
code to Django itself, and a :doc:`few other things that simply don't fit
|
code to Django itself, and a :doc:`few other things that don't fit elsewhere
|
||||||
elsewhere </misc/index>`.
|
</misc/index>`.
|
||||||
|
|
||||||
|
|
||||||
How documentation is updated
|
How documentation is updated
|
||||||
|
@ -155,7 +155,7 @@ Django document:
|
||||||
As HTML, locally
|
As HTML, locally
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
You can get a local copy of the HTML documentation following a few easy steps:
|
You can get a local copy of the HTML documentation following a few steps:
|
||||||
|
|
||||||
* Django's documentation uses a system called Sphinx__ to convert from
|
* Django's documentation uses a system called Sphinx__ to convert from
|
||||||
plain text to HTML. You'll need to install Sphinx by either downloading
|
plain text to HTML. You'll need to install Sphinx by either downloading
|
||||||
|
@ -165,8 +165,7 @@ You can get a local copy of the HTML documentation following a few easy steps:
|
||||||
|
|
||||||
$ python -m pip install Sphinx
|
$ python -m pip install Sphinx
|
||||||
|
|
||||||
* Then, just use the included ``Makefile`` to turn the documentation into
|
* Then, use the included ``Makefile`` to turn the documentation into HTML:
|
||||||
HTML:
|
|
||||||
|
|
||||||
.. code-block:: console
|
.. code-block:: console
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ Django contains a registry of installed applications that stores configuration
|
||||||
and provides introspection. It also maintains a list of available :doc:`models
|
and provides introspection. It also maintains a list of available :doc:`models
|
||||||
</topics/db/models>`.
|
</topics/db/models>`.
|
||||||
|
|
||||||
This registry is simply called :attr:`~django.apps.apps` and it's available in
|
This registry is called :attr:`~django.apps.apps` and it's available in
|
||||||
:mod:`django.apps`::
|
:mod:`django.apps`::
|
||||||
|
|
||||||
>>> from django.apps import apps
|
>>> from django.apps import apps
|
||||||
|
@ -40,7 +40,7 @@ projects with the :setting:`INSTALLED_APPS` setting and optionally with other
|
||||||
mechanisms such as URLconfs, the :setting:`MIDDLEWARE` setting, or template
|
mechanisms such as URLconfs, the :setting:`MIDDLEWARE` setting, or template
|
||||||
inheritance.
|
inheritance.
|
||||||
|
|
||||||
It is important to understand that a Django application is just a set of code
|
It is important to understand that a Django application is a set of code
|
||||||
that interacts with various parts of the framework. There's no such thing as
|
that interacts with various parts of the framework. There's no such thing as
|
||||||
an ``Application`` object. However, there's a few places where Django needs to
|
an ``Application`` object. However, there's a few places where Django needs to
|
||||||
interact with installed applications, mainly for configuration and also for
|
interact with installed applications, mainly for configuration and also for
|
||||||
|
@ -59,9 +59,8 @@ Configuring applications
|
||||||
To configure an application, subclass :class:`~django.apps.AppConfig` and put
|
To configure an application, subclass :class:`~django.apps.AppConfig` and put
|
||||||
the dotted path to that subclass in :setting:`INSTALLED_APPS`.
|
the dotted path to that subclass in :setting:`INSTALLED_APPS`.
|
||||||
|
|
||||||
When :setting:`INSTALLED_APPS` simply contains the dotted path to an
|
When :setting:`INSTALLED_APPS` contains the dotted path to an application
|
||||||
application module, Django checks for a ``default_app_config`` variable in
|
module, Django checks for a ``default_app_config`` variable in that module.
|
||||||
that module.
|
|
||||||
|
|
||||||
If it's defined, it's the dotted path to the :class:`~django.apps.AppConfig`
|
If it's defined, it's the dotted path to the :class:`~django.apps.AppConfig`
|
||||||
subclass for that application.
|
subclass for that application.
|
||||||
|
@ -99,11 +98,11 @@ subclass by default as follows::
|
||||||
default_app_config = 'rock_n_roll.apps.RockNRollConfig'
|
default_app_config = 'rock_n_roll.apps.RockNRollConfig'
|
||||||
|
|
||||||
That will cause ``RockNRollConfig`` to be used when :setting:`INSTALLED_APPS`
|
That will cause ``RockNRollConfig`` to be used when :setting:`INSTALLED_APPS`
|
||||||
just contains ``'rock_n_roll'``. This allows you to make use of
|
contains ``'rock_n_roll'``. This allows you to make use of
|
||||||
:class:`~django.apps.AppConfig` features without requiring your users to
|
:class:`~django.apps.AppConfig` features without requiring your users to update
|
||||||
update their :setting:`INSTALLED_APPS` setting. Besides this use case, it's
|
their :setting:`INSTALLED_APPS` setting. Besides this use case, it's best to
|
||||||
best to avoid using ``default_app_config`` and instead specify the app config
|
avoid using ``default_app_config`` and instead specify the app config class in
|
||||||
class in :setting:`INSTALLED_APPS` as described next.
|
:setting:`INSTALLED_APPS` as described next.
|
||||||
|
|
||||||
Of course, you can also tell your users to put
|
Of course, you can also tell your users to put
|
||||||
``'rock_n_roll.apps.RockNRollConfig'`` in their :setting:`INSTALLED_APPS`
|
``'rock_n_roll.apps.RockNRollConfig'`` in their :setting:`INSTALLED_APPS`
|
||||||
|
|
|
@ -325,8 +325,8 @@ Security
|
||||||
|
|
||||||
The security checks do not make your site secure. They do not audit code, do
|
The security checks do not make your site secure. They do not audit code, do
|
||||||
intrusion detection, or do anything particularly complex. Rather, they help
|
intrusion detection, or do anything particularly complex. Rather, they help
|
||||||
perform an automated, low-hanging-fruit checklist. They help you remember the
|
perform an automated, low-hanging-fruit checklist, that can help you to improve
|
||||||
simple things that improve your site's security.
|
your site's security.
|
||||||
|
|
||||||
Some of these checks may not be appropriate for your particular deployment
|
Some of these checks may not be appropriate for your particular deployment
|
||||||
configuration. For instance, if you do your HTTP to HTTPS redirection in a load
|
configuration. For instance, if you do your HTTP to HTTPS redirection in a load
|
||||||
|
|
|
@ -332,5 +332,5 @@ Date-based mixins
|
||||||
return the list of years for which ``qs`` has entries. If
|
return the list of years for which ``qs`` has entries. If
|
||||||
``date_type`` isn't provided, the result of
|
``date_type`` isn't provided, the result of
|
||||||
:meth:`~BaseDateListView.get_date_list_period` is used. ``date_type``
|
:meth:`~BaseDateListView.get_date_list_period` is used. ``date_type``
|
||||||
and ``ordering`` are simply passed to
|
and ``ordering`` are passed to
|
||||||
:meth:`QuerySet.dates()<django.db.models.query.QuerySet.dates>`.
|
:meth:`QuerySet.dates()<django.db.models.query.QuerySet.dates>`.
|
||||||
|
|
|
@ -209,8 +209,8 @@ The following mixins are used to construct Django's editing views:
|
||||||
|
|
||||||
.. method:: put(*args, **kwargs)
|
.. method:: put(*args, **kwargs)
|
||||||
|
|
||||||
The ``PUT`` action is also handled and just passes all parameters
|
The ``PUT`` action is also handled and passes all parameters through to
|
||||||
through to :meth:`post`.
|
:meth:`post`.
|
||||||
|
|
||||||
|
|
||||||
``DeletionMixin``
|
``DeletionMixin``
|
||||||
|
|
|
@ -136,8 +136,7 @@ Multiple object mixins
|
||||||
.. method:: get_paginate_by(queryset)
|
.. method:: get_paginate_by(queryset)
|
||||||
|
|
||||||
Returns the number of items to paginate by, or ``None`` for no
|
Returns the number of items to paginate by, or ``None`` for no
|
||||||
pagination. By default this simply returns the value of
|
pagination. By default this returns the value of :attr:`paginate_by`.
|
||||||
:attr:`paginate_by`.
|
|
||||||
|
|
||||||
.. method:: get_paginator(queryset, per_page, orphans=0, allow_empty_first_page=True)
|
.. method:: get_paginator(queryset, per_page, orphans=0, allow_empty_first_page=True)
|
||||||
|
|
||||||
|
@ -147,7 +146,7 @@ Multiple object mixins
|
||||||
.. method:: get_paginate_orphans()
|
.. method:: get_paginate_orphans()
|
||||||
|
|
||||||
An integer specifying the number of "overflow" objects the last page
|
An integer specifying the number of "overflow" objects the last page
|
||||||
can contain. By default this simply returns the value of
|
can contain. By default this returns the value of
|
||||||
:attr:`paginate_orphans`.
|
:attr:`paginate_orphans`.
|
||||||
|
|
||||||
.. method:: get_allow_empty()
|
.. method:: get_allow_empty()
|
||||||
|
|
|
@ -12,7 +12,7 @@ Simple mixins
|
||||||
.. attribute:: extra_context
|
.. attribute:: extra_context
|
||||||
|
|
||||||
A dictionary to include in the context. This is a convenient way of
|
A dictionary to include in the context. This is a convenient way of
|
||||||
specifying some simple context in
|
specifying some context in
|
||||||
:meth:`~django.views.generic.base.View.as_view`. Example usage::
|
:meth:`~django.views.generic.base.View.as_view`. Example usage::
|
||||||
|
|
||||||
from django.views.generic import TemplateView
|
from django.views.generic import TemplateView
|
||||||
|
|
|
@ -63,7 +63,7 @@ Single object mixins
|
||||||
with access to individual objects should be prevented from obtaining
|
with access to individual objects should be prevented from obtaining
|
||||||
this list, setting ``query_pk_and_slug`` to ``True`` will help prevent
|
this list, setting ``query_pk_and_slug`` to ``True`` will help prevent
|
||||||
the guessing of URLs as each URL will require two correct,
|
the guessing of URLs as each URL will require two correct,
|
||||||
non-sequential arguments. Simply using a unique slug may serve the same
|
non-sequential arguments. Using a unique slug may serve the same
|
||||||
purpose, but this scheme allows you to have non-unique slugs.
|
purpose, but this scheme allows you to have non-unique slugs.
|
||||||
|
|
||||||
.. _insecure direct object reference: https://www.owasp.org/index.php/Top_10_2013-A4-Insecure_Direct_Object_References
|
.. _insecure direct object reference: https://www.owasp.org/index.php/Top_10_2013-A4-Insecure_Direct_Object_References
|
||||||
|
@ -128,7 +128,7 @@ Single object mixins
|
||||||
.. method:: get_slug_field()
|
.. method:: get_slug_field()
|
||||||
|
|
||||||
Returns the name of a slug field to be used to look up by slug. By
|
Returns the name of a slug field to be used to look up by slug. By
|
||||||
default this simply returns the value of :attr:`slug_field`.
|
default this returns the value of :attr:`slug_field`.
|
||||||
|
|
||||||
|
|
||||||
``SingleObjectTemplateResponseMixin``
|
``SingleObjectTemplateResponseMixin``
|
||||||
|
|
|
@ -37,10 +37,9 @@ loading in a frame no matter which site made the request.
|
||||||
|
|
||||||
.. _X-Frame-Options: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options
|
.. _X-Frame-Options: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options
|
||||||
|
|
||||||
Django provides a few simple ways to include this header in responses from your
|
Django provides a few ways to include this header in responses from your site:
|
||||||
site:
|
|
||||||
|
|
||||||
#. A simple middleware that sets the header in all responses.
|
#. A middleware that sets the header in all responses.
|
||||||
|
|
||||||
#. A set of view decorators that can be used to override the middleware or to
|
#. A set of view decorators that can be used to override the middleware or to
|
||||||
only set the header for certain views.
|
only set the header for certain views.
|
||||||
|
|
|
@ -9,7 +9,7 @@ then change it." This works well for a majority of use cases. However, if you
|
||||||
need to make the same change to many objects at once, this workflow can be
|
need to make the same change to many objects at once, this workflow can be
|
||||||
quite tedious.
|
quite tedious.
|
||||||
|
|
||||||
In these cases, Django's admin lets you write and register "actions" -- simple
|
In these cases, Django's admin lets you write and register "actions" --
|
||||||
functions that get called with a list of objects selected on the change list
|
functions that get called with a list of objects selected on the change list
|
||||||
page.
|
page.
|
||||||
|
|
||||||
|
@ -43,7 +43,7 @@ Writing actions
|
||||||
The easiest way to explain actions is by example, so let's dive in.
|
The easiest way to explain actions is by example, so let's dive in.
|
||||||
|
|
||||||
A common use case for admin actions is the bulk updating of a model. Imagine a
|
A common use case for admin actions is the bulk updating of a model. Imagine a
|
||||||
simple news application with an ``Article`` model::
|
news application with an ``Article`` model::
|
||||||
|
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
|
||||||
|
@ -71,7 +71,7 @@ Writing action functions
|
||||||
------------------------
|
------------------------
|
||||||
|
|
||||||
First, we'll need to write a function that gets called when the action is
|
First, we'll need to write a function that gets called when the action is
|
||||||
triggered from the admin. Action functions are just regular functions that take
|
triggered from the admin. Action functions are regular functions that take
|
||||||
three arguments:
|
three arguments:
|
||||||
|
|
||||||
* The current :class:`ModelAdmin`
|
* The current :class:`ModelAdmin`
|
||||||
|
@ -89,7 +89,7 @@ request object, but we will use the queryset::
|
||||||
|
|
||||||
For the best performance, we're using the queryset's :ref:`update method
|
For the best performance, we're using the queryset's :ref:`update method
|
||||||
<topics-db-queries-update>`. Other types of actions might need to deal
|
<topics-db-queries-update>`. Other types of actions might need to deal
|
||||||
with each object individually; in these cases we'd just iterate over the
|
with each object individually; in these cases we'd iterate over the
|
||||||
queryset::
|
queryset::
|
||||||
|
|
||||||
for obj in queryset:
|
for obj in queryset:
|
||||||
|
@ -138,7 +138,7 @@ That code will give us an admin change list that looks something like this:
|
||||||
.. image:: _images/adding-actions-to-the-modeladmin.png
|
.. image:: _images/adding-actions-to-the-modeladmin.png
|
||||||
|
|
||||||
That's really all there is to it! If you're itching to write your own actions,
|
That's really all there is to it! If you're itching to write your own actions,
|
||||||
you now know enough to get started. The rest of this document just covers more
|
you now know enough to get started. The rest of this document covers more
|
||||||
advanced techniques.
|
advanced techniques.
|
||||||
|
|
||||||
Handling errors in actions
|
Handling errors in actions
|
||||||
|
@ -159,12 +159,12 @@ advanced options.
|
||||||
Actions as :class:`ModelAdmin` methods
|
Actions as :class:`ModelAdmin` methods
|
||||||
--------------------------------------
|
--------------------------------------
|
||||||
|
|
||||||
The example above shows the ``make_published`` action defined as a simple
|
The example above shows the ``make_published`` action defined as a function.
|
||||||
function. That's perfectly fine, but it's not perfect from a code design point
|
That's perfectly fine, but it's not perfect from a code design point of view:
|
||||||
of view: since the action is tightly coupled to the ``Article`` object, it
|
since the action is tightly coupled to the ``Article`` object, it makes sense
|
||||||
makes sense to hook the action to the ``ArticleAdmin`` object itself.
|
to hook the action to the ``ArticleAdmin`` object itself.
|
||||||
|
|
||||||
That's easy enough to do::
|
You can do it like this::
|
||||||
|
|
||||||
class ArticleAdmin(admin.ModelAdmin):
|
class ArticleAdmin(admin.ModelAdmin):
|
||||||
...
|
...
|
||||||
|
@ -180,9 +180,9 @@ Notice first that we've moved ``make_published`` into a method and renamed the
|
||||||
``'make_published'`` in ``actions`` instead of a direct function reference. This
|
``'make_published'`` in ``actions`` instead of a direct function reference. This
|
||||||
tells the :class:`ModelAdmin` to look up the action as a method.
|
tells the :class:`ModelAdmin` to look up the action as a method.
|
||||||
|
|
||||||
Defining actions as methods gives the action more straightforward, idiomatic
|
Defining actions as methods gives the action more idiomatic access to the
|
||||||
access to the :class:`ModelAdmin` itself, allowing the action to call any of the
|
:class:`ModelAdmin` itself, allowing the action to call any of the methods
|
||||||
methods provided by the admin.
|
provided by the admin.
|
||||||
|
|
||||||
.. _custom-admin-action:
|
.. _custom-admin-action:
|
||||||
|
|
||||||
|
@ -208,17 +208,15 @@ performing an action:
|
||||||
Actions that provide intermediate pages
|
Actions that provide intermediate pages
|
||||||
---------------------------------------
|
---------------------------------------
|
||||||
|
|
||||||
By default, after an action is performed the user is simply redirected back
|
By default, after an action is performed the user is redirected back to the
|
||||||
to the original change list page. However, some actions, especially more
|
original change list page. However, some actions, especially more complex ones,
|
||||||
complex ones, will need to return intermediate pages. For example, the
|
will need to return intermediate pages. For example, the built-in delete action
|
||||||
built-in delete action asks for confirmation before deleting the selected
|
asks for confirmation before deleting the selected objects.
|
||||||
objects.
|
|
||||||
|
|
||||||
To provide an intermediary page, simply return an
|
To provide an intermediary page, return an :class:`~django.http.HttpResponse`
|
||||||
:class:`~django.http.HttpResponse` (or subclass) from your action. For
|
(or subclass) from your action. For example, you might write a export function
|
||||||
example, you might write a simple export function that uses Django's
|
that uses Django's :doc:`serialization functions </topics/serialization>` to
|
||||||
:doc:`serialization functions </topics/serialization>` to dump some selected
|
dump some selected objects as JSON::
|
||||||
objects as JSON::
|
|
||||||
|
|
||||||
from django.core import serializers
|
from django.core import serializers
|
||||||
from django.http import HttpResponse
|
from django.http import HttpResponse
|
||||||
|
@ -236,7 +234,7 @@ This allows you to provide complex interaction logic on the intermediary
|
||||||
pages. For example, if you wanted to provide a more complete export function,
|
pages. For example, if you wanted to provide a more complete export function,
|
||||||
you'd want to let the user choose a format, and possibly a list of fields to
|
you'd want to let the user choose a format, and possibly a list of fields to
|
||||||
include in the export. The best thing to do would be to write a small action
|
include in the export. The best thing to do would be to write a small action
|
||||||
that simply redirects to your custom export view::
|
that redirects to your custom export view::
|
||||||
|
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
from django.contrib.contenttypes.models import ContentType
|
from django.contrib.contenttypes.models import ContentType
|
||||||
|
@ -247,9 +245,9 @@ that simply redirects to your custom export view::
|
||||||
ct = ContentType.objects.get_for_model(queryset.model)
|
ct = ContentType.objects.get_for_model(queryset.model)
|
||||||
return HttpResponseRedirect("/export/?ct=%s&ids=%s" % (ct.pk, ",".join(selected)))
|
return HttpResponseRedirect("/export/?ct=%s&ids=%s" % (ct.pk, ",".join(selected)))
|
||||||
|
|
||||||
As you can see, the action is the simple part; all the complex logic would
|
As you can see, the action is rather short; all the complex logic would belong
|
||||||
belong in your export view. This would need to deal with objects of any type,
|
in your export view. This would need to deal with objects of any type, hence
|
||||||
hence the business with the ``ContentType``.
|
the business with the ``ContentType``.
|
||||||
|
|
||||||
Writing this view is left as an exercise to the reader.
|
Writing this view is left as an exercise to the reader.
|
||||||
|
|
||||||
|
@ -303,8 +301,7 @@ Disabling a site-wide action
|
||||||
site-wide.
|
site-wide.
|
||||||
|
|
||||||
If, however, you need to re-enable a globally-disabled action for one
|
If, however, you need to re-enable a globally-disabled action for one
|
||||||
particular model, simply list it explicitly in your ``ModelAdmin.actions``
|
particular model, list it explicitly in your ``ModelAdmin.actions`` list::
|
||||||
list::
|
|
||||||
|
|
||||||
# Globally disable delete selected
|
# Globally disable delete selected
|
||||||
admin.site.disable_action('delete_selected')
|
admin.site.disable_action('delete_selected')
|
||||||
|
@ -323,8 +320,8 @@ Disabling a site-wide action
|
||||||
Disabling all actions for a particular :class:`ModelAdmin`
|
Disabling all actions for a particular :class:`ModelAdmin`
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
If you want *no* bulk actions available for a given :class:`ModelAdmin`, simply
|
If you want *no* bulk actions available for a given :class:`ModelAdmin`, set
|
||||||
set :attr:`ModelAdmin.actions` to ``None``::
|
:attr:`ModelAdmin.actions` to ``None``::
|
||||||
|
|
||||||
class MyModelAdmin(admin.ModelAdmin):
|
class MyModelAdmin(admin.ModelAdmin):
|
||||||
actions = None
|
actions = None
|
||||||
|
|
|
@ -83,8 +83,7 @@ Other topics
|
||||||
|
|
||||||
The ``ModelAdmin`` class is the representation of a model in the admin
|
The ``ModelAdmin`` class is the representation of a model in the admin
|
||||||
interface. Usually, these are stored in a file named ``admin.py`` in your
|
interface. Usually, these are stored in a file named ``admin.py`` in your
|
||||||
application. Let's take a look at a very simple example of
|
application. Let's take a look at an example of the ``ModelAdmin``::
|
||||||
the ``ModelAdmin``::
|
|
||||||
|
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
from myproject.myapp.models import Author
|
from myproject.myapp.models import Author
|
||||||
|
@ -1195,8 +1194,8 @@ subclass::
|
||||||
A read-only field can not only display data from a model's field, it can
|
A read-only field can not only display data from a model's field, it can
|
||||||
also display the output of a model's method or a method of the
|
also display the output of a model's method or a method of the
|
||||||
``ModelAdmin`` class itself. This is very similar to the way
|
``ModelAdmin`` class itself. This is very similar to the way
|
||||||
:attr:`ModelAdmin.list_display` behaves. This provides an easy way to use
|
:attr:`ModelAdmin.list_display` behaves. This provides a way to use the
|
||||||
the admin interface to provide feedback on the status of the objects being
|
admin interface to provide feedback on the status of the objects being
|
||||||
edited, for example::
|
edited, for example::
|
||||||
|
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
|
@ -1742,7 +1741,7 @@ templates used by the :class:`ModelAdmin` views:
|
||||||
kwargs['form'] = MySuperuserForm
|
kwargs['form'] = MySuperuserForm
|
||||||
return super().get_form(request, obj, **kwargs)
|
return super().get_form(request, obj, **kwargs)
|
||||||
|
|
||||||
You may also simply return a custom :class:`~django.forms.ModelForm` class
|
You may also return a custom :class:`~django.forms.ModelForm` class
|
||||||
directly.
|
directly.
|
||||||
|
|
||||||
.. method:: ModelAdmin.get_formsets_with_inlines(request, obj=None)
|
.. method:: ModelAdmin.get_formsets_with_inlines(request, obj=None)
|
||||||
|
@ -2159,9 +2158,9 @@ return the uncompressed versions of the various JavaScript files, including
|
||||||
Adding custom validation to the admin
|
Adding custom validation to the admin
|
||||||
-------------------------------------
|
-------------------------------------
|
||||||
|
|
||||||
Adding custom validation of data in the admin is quite easy. The automatic
|
You can also add custom validation of data in the admin. The automatic admin
|
||||||
admin interface reuses :mod:`django.forms`, and the ``ModelAdmin`` class gives
|
interface reuses :mod:`django.forms`, and the ``ModelAdmin`` class gives you
|
||||||
you the ability define your own form::
|
the ability define your own form::
|
||||||
|
|
||||||
class ArticleAdmin(admin.ModelAdmin):
|
class ArticleAdmin(admin.ModelAdmin):
|
||||||
form = MyArticleAdminForm
|
form = MyArticleAdminForm
|
||||||
|
@ -2535,8 +2534,7 @@ layout required for multiple widgets will vary depending on the intermediate
|
||||||
model.
|
model.
|
||||||
|
|
||||||
However, we still want to be able to edit that information inline. Fortunately,
|
However, we still want to be able to edit that information inline. Fortunately,
|
||||||
this is easy to do with inline admin models. Suppose we have the following
|
we can do this with inline admin models. Suppose we have the following models::
|
||||||
models::
|
|
||||||
|
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
|
||||||
|
@ -2560,7 +2558,7 @@ define an inline class for the ``Membership`` model::
|
||||||
model = Membership
|
model = Membership
|
||||||
extra = 1
|
extra = 1
|
||||||
|
|
||||||
This simple example uses the default ``InlineModelAdmin`` values for the
|
This example uses the default ``InlineModelAdmin`` values for the
|
||||||
``Membership`` model, and limits the extra add forms to one. This could be
|
``Membership`` model, and limits the extra add forms to one. This could be
|
||||||
customized using any of the options available to ``InlineModelAdmin`` classes.
|
customized using any of the options available to ``InlineModelAdmin`` classes.
|
||||||
|
|
||||||
|
@ -2633,9 +2631,9 @@ specific information.
|
||||||
Overriding admin templates
|
Overriding admin templates
|
||||||
==========================
|
==========================
|
||||||
|
|
||||||
It is relatively easy to override many of the templates which the admin module
|
You can override many of the templates which the admin module uses to generate
|
||||||
uses to generate the various pages of an admin site. You can even override a
|
the various pages of an admin site. You can even override a few of these
|
||||||
few of these templates for a specific app, or a specific model.
|
templates for a specific app, or a specific model.
|
||||||
|
|
||||||
Set up your projects admin template directories
|
Set up your projects admin template directories
|
||||||
-----------------------------------------------
|
-----------------------------------------------
|
||||||
|
@ -2732,7 +2730,7 @@ app or per model. The following can:
|
||||||
* ``submit_line.html``
|
* ``submit_line.html``
|
||||||
|
|
||||||
For those templates that cannot be overridden in this way, you may still
|
For those templates that cannot be overridden in this way, you may still
|
||||||
override them for your entire project. Just place the new version in your
|
override them for your entire project by placing the new version in your
|
||||||
``templates/admin`` directory. This is particularly useful to create custom 404
|
``templates/admin`` directory. This is particularly useful to create custom 404
|
||||||
and 500 pages.
|
and 500 pages.
|
||||||
|
|
||||||
|
@ -2923,11 +2921,11 @@ Customizing the :class:`AdminSite` class
|
||||||
----------------------------------------
|
----------------------------------------
|
||||||
|
|
||||||
If you'd like to set up your own admin site with custom behavior, you're free
|
If you'd like to set up your own admin site with custom behavior, you're free
|
||||||
to subclass ``AdminSite`` and override or add anything you like. Then, simply
|
to subclass ``AdminSite`` and override or add anything you like. Then, create
|
||||||
create an instance of your ``AdminSite`` subclass (the same way you'd
|
an instance of your ``AdminSite`` subclass (the same way you'd instantiate any
|
||||||
instantiate any other Python class) and register your models and
|
other Python class) and register your models and ``ModelAdmin`` subclasses with
|
||||||
``ModelAdmin`` subclasses with it instead of with the default site. Finally,
|
it instead of with the default site. Finally, update :file:`myproject/urls.py`
|
||||||
update :file:`myproject/urls.py` to reference your :class:`AdminSite` subclass.
|
to reference your :class:`AdminSite` subclass.
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
:caption: myapp/admin.py
|
:caption: myapp/admin.py
|
||||||
|
@ -3000,9 +2998,9 @@ returns a site instance.
|
||||||
Multiple admin sites in the same URLconf
|
Multiple admin sites in the same URLconf
|
||||||
----------------------------------------
|
----------------------------------------
|
||||||
|
|
||||||
It's easy to create multiple instances of the admin site on the same
|
You can create multiple instances of the admin site on the same Django-powered
|
||||||
Django-powered website. Just create multiple instances of ``AdminSite`` and
|
website. Create multiple instances of ``AdminSite`` and place each one at a
|
||||||
root each one at a different URL.
|
different URL.
|
||||||
|
|
||||||
In this example, the URLs ``/basic-admin/`` and ``/advanced-admin/`` feature
|
In this example, the URLs ``/basic-admin/`` and ``/advanced-admin/`` feature
|
||||||
separate versions of the admin site -- using the ``AdminSite`` instances
|
separate versions of the admin site -- using the ``AdminSite`` instances
|
||||||
|
|
|
@ -55,9 +55,9 @@ Two points to keep in mind:
|
||||||
various operations in the change form and we need that to be rendered too.
|
various operations in the change form and we need that to be rendered too.
|
||||||
|
|
||||||
Sometimes you'll need to work with ``jQuery`` plugins that are not registered
|
Sometimes you'll need to work with ``jQuery`` plugins that are not registered
|
||||||
in the ``django.jQuery`` namespace. To do that, simply change how the code
|
in the ``django.jQuery`` namespace. To do that, change how the code listens for
|
||||||
listens for events. Instead of wrapping the listener in the ``django.jQuery``
|
events. Instead of wrapping the listener in the ``django.jQuery`` namespace,
|
||||||
namespace, just listen to the event triggered from there. For example:
|
listen to the event triggered from there. For example:
|
||||||
|
|
||||||
.. code-block:: html+django
|
.. code-block:: html+django
|
||||||
|
|
||||||
|
|
|
@ -648,8 +648,8 @@ The following backends are available in :mod:`django.contrib.auth.backends`:
|
||||||
.. method:: authenticate(request, remote_user)
|
.. method:: authenticate(request, remote_user)
|
||||||
|
|
||||||
The username passed as ``remote_user`` is considered trusted. This
|
The username passed as ``remote_user`` is considered trusted. This
|
||||||
method simply returns the user object with the given username, creating
|
method returns the user object with the given username, creating a new
|
||||||
a new user object if :attr:`~RemoteUserBackend.create_unknown_user` is
|
user object if :attr:`~RemoteUserBackend.create_unknown_user` is
|
||||||
``True``.
|
``True``.
|
||||||
|
|
||||||
Returns ``None`` if :attr:`~RemoteUserBackend.create_unknown_user` is
|
Returns ``None`` if :attr:`~RemoteUserBackend.create_unknown_user` is
|
||||||
|
|
|
@ -240,7 +240,7 @@ to go one step further and use
|
||||||
:class:`~django.contrib.contenttypes.models.ContentType` to enable truly
|
:class:`~django.contrib.contenttypes.models.ContentType` to enable truly
|
||||||
generic (sometimes called "polymorphic") relationships between models.
|
generic (sometimes called "polymorphic") relationships between models.
|
||||||
|
|
||||||
A simple example is a tagging system, which might look like this::
|
For example, it could be used for a tagging system like so::
|
||||||
|
|
||||||
from django.contrib.contenttypes.fields import GenericForeignKey
|
from django.contrib.contenttypes.fields import GenericForeignKey
|
||||||
from django.contrib.contenttypes.models import ContentType
|
from django.contrib.contenttypes.models import ContentType
|
||||||
|
@ -438,7 +438,7 @@ it would be deleted at the same time.
|
||||||
Unlike :class:`~django.db.models.ForeignKey`,
|
Unlike :class:`~django.db.models.ForeignKey`,
|
||||||
:class:`~django.contrib.contenttypes.fields.GenericForeignKey` does not accept
|
:class:`~django.contrib.contenttypes.fields.GenericForeignKey` does not accept
|
||||||
an :attr:`~django.db.models.ForeignKey.on_delete` argument to customize this
|
an :attr:`~django.db.models.ForeignKey.on_delete` argument to customize this
|
||||||
behavior; if desired, you can avoid the cascade-deletion simply by not using
|
behavior; if desired, you can avoid the cascade-deletion by not using
|
||||||
:class:`~django.contrib.contenttypes.fields.GenericRelation`, and alternate
|
:class:`~django.contrib.contenttypes.fields.GenericRelation`, and alternate
|
||||||
behavior can be provided via the :data:`~django.db.models.signals.pre_delete`
|
behavior can be provided via the :data:`~django.db.models.signals.pre_delete`
|
||||||
signal.
|
signal.
|
||||||
|
|
|
@ -5,14 +5,14 @@ The flatpages app
|
||||||
.. module:: django.contrib.flatpages
|
.. module:: django.contrib.flatpages
|
||||||
:synopsis: A framework for managing simple ?flat? HTML content in a database.
|
:synopsis: A framework for managing simple ?flat? HTML content in a database.
|
||||||
|
|
||||||
Django comes with an optional "flatpages" application. It lets you store simple
|
Django comes with an optional "flatpages" application. It lets you store "flat"
|
||||||
"flat" HTML content in a database and handles the management for you via
|
HTML content in a database and handles the management for you via Django's
|
||||||
Django's admin interface and a Python API.
|
admin interface and a Python API.
|
||||||
|
|
||||||
A flatpage is a simple object with a URL, title and content. Use it for
|
A flatpage is a object with a URL, title and content. Use it for one-off,
|
||||||
one-off, special-case pages, such as "About" or "Privacy Policy" pages, that
|
special-case pages, such as "About" or "Privacy Policy" pages, that you want to
|
||||||
you want to store in a database but for which you don't want to develop a
|
store in a database but for which you don't want to develop a custom Django
|
||||||
custom Django application.
|
application.
|
||||||
|
|
||||||
A flatpage can use a custom template or a default, systemwide flatpage
|
A flatpage can use a custom template or a default, systemwide flatpage
|
||||||
template. It can be associated with one, or multiple, sites.
|
template. It can be associated with one, or multiple, sites.
|
||||||
|
@ -58,9 +58,9 @@ How it works
|
||||||
============
|
============
|
||||||
|
|
||||||
``manage.py migrate`` creates two tables in your database: ``django_flatpage``
|
``manage.py migrate`` creates two tables in your database: ``django_flatpage``
|
||||||
and ``django_flatpage_sites``. ``django_flatpage`` is a simple lookup table
|
and ``django_flatpage_sites``. ``django_flatpage`` is a lookup table that maps
|
||||||
that simply maps a URL to a title and bunch of text content.
|
a URL to a title and bunch of text content. ``django_flatpage_sites``
|
||||||
``django_flatpage_sites`` associates a flatpage with a site.
|
associates a flatpage with a site.
|
||||||
|
|
||||||
Using the URLconf
|
Using the URLconf
|
||||||
-----------------
|
-----------------
|
||||||
|
@ -229,12 +229,12 @@ By default, flatpages are rendered via the template
|
||||||
particular flatpage: in the admin, a collapsed fieldset titled
|
particular flatpage: in the admin, a collapsed fieldset titled
|
||||||
"Advanced options" (clicking will expand it) contains a field for
|
"Advanced options" (clicking will expand it) contains a field for
|
||||||
specifying a template name. If you're creating a flat page via the
|
specifying a template name. If you're creating a flat page via the
|
||||||
Python API you can simply set the template name as the field
|
Python API you can set the template name as the field ``template_name`` on the
|
||||||
``template_name`` on the ``FlatPage`` object.
|
``FlatPage`` object.
|
||||||
|
|
||||||
Creating the :file:`flatpages/default.html` template is your responsibility;
|
Creating the :file:`flatpages/default.html` template is your responsibility;
|
||||||
in your template directory, just create a :file:`flatpages` directory
|
in your template directory, create a :file:`flatpages` directory containing a
|
||||||
containing a file :file:`default.html`.
|
file :file:`default.html`.
|
||||||
|
|
||||||
Flatpage templates are passed a single context variable, ``flatpage``,
|
Flatpage templates are passed a single context variable, ``flatpage``,
|
||||||
which is the flatpage object.
|
which is the flatpage object.
|
||||||
|
|
|
@ -284,10 +284,10 @@ Then distance queries may be performed as follows::
|
||||||
>>> qs = SouthTexasCity.objects.filter(point__distance_gte=(pnt, D(mi=20)))
|
>>> qs = SouthTexasCity.objects.filter(point__distance_gte=(pnt, D(mi=20)))
|
||||||
>>> qs = SouthTexasCity.objects.filter(point__distance_gte=(pnt, D(chain=100)))
|
>>> qs = SouthTexasCity.objects.filter(point__distance_gte=(pnt, D(chain=100)))
|
||||||
|
|
||||||
Raster queries work the same way by simply replacing the geometry field
|
Raster queries work the same way by replacing the geometry field ``point`` with
|
||||||
``point`` with a raster field, or the ``pnt`` object with a raster object, or
|
a raster field, or the ``pnt`` object with a raster object, or both. To specify
|
||||||
both. To specify the band index of a raster input on the right hand side, a
|
the band index of a raster input on the right hand side, a 3-tuple can be
|
||||||
3-tuple can be passed to the lookup as follows::
|
passed to the lookup as follows::
|
||||||
|
|
||||||
>>> qs = SouthTexasCity.objects.filter(point__distance_gte=(rst, 2, D(km=7)))
|
>>> qs = SouthTexasCity.objects.filter(point__distance_gte=(rst, 2, D(km=7)))
|
||||||
|
|
||||||
|
|
|
@ -88,7 +88,7 @@ Form widgets
|
||||||
GeoDjango form widgets allow you to display and edit geographic data on a
|
GeoDjango form widgets allow you to display and edit geographic data on a
|
||||||
visual map.
|
visual map.
|
||||||
Note that none of the currently available widgets supports 3D geometries, hence
|
Note that none of the currently available widgets supports 3D geometries, hence
|
||||||
geometry fields will fallback using a simple ``Textarea`` widget for such data.
|
geometry fields will fallback using a ``Textarea`` widget for such data.
|
||||||
|
|
||||||
Widget attributes
|
Widget attributes
|
||||||
-----------------
|
-----------------
|
||||||
|
|
|
@ -36,7 +36,7 @@ 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
|
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
|
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
|
have any data of your own to use, GeoDjango tests contain a number of
|
||||||
simple 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::
|
||||||
|
|
||||||
$ wget https://raw.githubusercontent.com/django/django/master/tests/gis_tests/data/cities/cities.{shp,prj,shx,dbf}
|
$ wget https://raw.githubusercontent.com/django/django/master/tests/gis_tests/data/cities/cities.{shp,prj,shx,dbf}
|
||||||
$ wget https://raw.githubusercontent.com/django/django/master/tests/gis_tests/data/rasters/raster.tif
|
$ wget https://raw.githubusercontent.com/django/django/master/tests/gis_tests/data/rasters/raster.tif
|
||||||
|
@ -49,7 +49,7 @@ Vector Data Source Objects
|
||||||
|
|
||||||
:class:`DataSource` is a wrapper for the OGR data source object that
|
:class:`DataSource` is a wrapper for the OGR data source object that
|
||||||
supports reading data from a variety of OGR-supported geospatial file
|
supports reading data from a variety of OGR-supported geospatial file
|
||||||
formats and data sources using a simple, consistent interface. Each
|
formats and data sources using a consistent interface. Each
|
||||||
data source is represented by a :class:`DataSource` object which contains
|
data source is represented by a :class:`DataSource` object which contains
|
||||||
one or more layers of data. Each layer, represented by a :class:`Layer`
|
one or more layers of data. Each layer, represented by a :class:`Layer`
|
||||||
object, contains some number of geographic features (:class:`Feature`),
|
object, contains some number of geographic features (:class:`Feature`),
|
||||||
|
@ -1085,7 +1085,7 @@ Raster Data Objects
|
||||||
|
|
||||||
:class:`GDALRaster` is a wrapper for the GDAL raster source object that
|
:class:`GDALRaster` is a wrapper for the GDAL raster source object that
|
||||||
supports reading data from a variety of GDAL-supported geospatial file
|
supports reading data from a variety of GDAL-supported geospatial file
|
||||||
formats and data sources using a simple, consistent interface. Each
|
formats and data sources using a consistent interface. Each
|
||||||
data source is represented by a :class:`GDALRaster` object which contains
|
data source is represented by a :class:`GDALRaster` object which contains
|
||||||
one or more layers of data named bands. Each band, represented by a
|
one or more layers of data named bands. Each band, represented by a
|
||||||
:class:`GDALBand` object, contains georeferenced image data. For example, an RGB
|
:class:`GDALBand` object, contains georeferenced image data. For example, an RGB
|
||||||
|
|
|
@ -887,8 +887,8 @@ SpatiaLite
|
||||||
Returns a ``GEOMETRYCOLLECTION`` or a ``MULTI`` geometry object from the geometry
|
Returns a ``GEOMETRYCOLLECTION`` or a ``MULTI`` geometry object from the geometry
|
||||||
column. This is analogous to a simplified version of the :class:`Union`
|
column. This is analogous to a simplified version of the :class:`Union`
|
||||||
aggregate, except it can be several orders of magnitude faster than performing
|
aggregate, except it can be several orders of magnitude faster than performing
|
||||||
a union because it simply rolls up geometries into a collection or multi object,
|
a union because it rolls up geometries into a collection or multi object, not
|
||||||
not caring about dissolving boundaries.
|
caring about dissolving boundaries.
|
||||||
|
|
||||||
``Extent``
|
``Extent``
|
||||||
~~~~~~~~~~
|
~~~~~~~~~~
|
||||||
|
|
|
@ -833,7 +833,7 @@ Geometry Collections
|
||||||
Prepared Geometries
|
Prepared Geometries
|
||||||
===================
|
===================
|
||||||
|
|
||||||
In order to obtain a prepared geometry, just access the
|
In order to obtain a prepared geometry, access the
|
||||||
:attr:`GEOSGeometry.prepared` property. Once you have a
|
:attr:`GEOSGeometry.prepared` property. Once you have a
|
||||||
``PreparedGeometry`` instance its spatial predicate methods, listed below,
|
``PreparedGeometry`` instance its spatial predicate methods, listed below,
|
||||||
may be used with other ``GEOSGeometry`` objects. An operation with a prepared
|
may be used with other ``GEOSGeometry`` objects. An operation with a prepared
|
||||||
|
@ -911,8 +911,8 @@ I/O Objects
|
||||||
Reader Objects
|
Reader Objects
|
||||||
--------------
|
--------------
|
||||||
|
|
||||||
The reader I/O classes simply return a :class:`GEOSGeometry` instance from the
|
The reader I/O classes return a :class:`GEOSGeometry` instance from the WKB
|
||||||
WKB and/or WKT input given to their ``read(geom)`` method.
|
and/or WKT input given to their ``read(geom)`` method.
|
||||||
|
|
||||||
.. class:: WKBReader
|
.. class:: WKBReader
|
||||||
|
|
||||||
|
|
|
@ -39,7 +39,7 @@ totally fine with GeoDjango. Your mileage may vary.
|
||||||
|
|
||||||
The GeoDjango interfaces to GEOS, GDAL, and GeoIP may be used
|
The GeoDjango interfaces to GEOS, GDAL, and GeoIP may be used
|
||||||
independently of Django. In other words, no database or settings file
|
independently of Django. In other words, no database or settings file
|
||||||
required -- just import them as normal from :mod:`django.contrib.gis`.
|
required -- import them as normal from :mod:`django.contrib.gis`.
|
||||||
|
|
||||||
.. _PROJ.4: https://github.com/OSGeo/proj.4/wiki/
|
.. _PROJ.4: https://github.com/OSGeo/proj.4/wiki/
|
||||||
__ https://postgis.net/
|
__ https://postgis.net/
|
||||||
|
|
|
@ -272,9 +272,9 @@ KyngChaos packages
|
||||||
~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
William Kyngesburye provides a number of `geospatial library binary packages`__
|
William Kyngesburye provides a number of `geospatial library binary packages`__
|
||||||
that make it simple to get GeoDjango installed on macOS without compiling
|
that help to get GeoDjango installed on macOS without compiling them from
|
||||||
them from source. However, `Xcode`_ is still necessary for compiling the
|
source. However, `Xcode`_ is still necessary for compiling the Python database
|
||||||
Python database adapters :ref:`psycopg2_kyngchaos` (for PostGIS).
|
adapters :ref:`psycopg2_kyngchaos` (for PostGIS).
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
|
@ -385,9 +385,9 @@ PostgreSQL
|
||||||
~~~~~~~~~~
|
~~~~~~~~~~
|
||||||
|
|
||||||
First, download the latest `PostgreSQL 9.x installer`__ from the
|
First, download the latest `PostgreSQL 9.x installer`__ from the
|
||||||
`EnterpriseDB`__ website. After downloading, simply run the installer,
|
`EnterpriseDB`__ website. After downloading, run the installer, follow the
|
||||||
follow the on-screen directions, and keep the default options unless
|
on-screen directions, and keep the default options unless you know the
|
||||||
you know the consequences of changing them.
|
consequences of changing them.
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
|
@ -446,14 +446,13 @@ __ http://www.stickpeople.com/projects/python/win-psycopg/
|
||||||
OSGeo4W
|
OSGeo4W
|
||||||
~~~~~~~
|
~~~~~~~
|
||||||
|
|
||||||
The `OSGeo4W installer`_ makes it simple to install the PROJ.4, GDAL, and GEOS
|
The `OSGeo4W installer`_ helps to install the PROJ.4, GDAL, and GEOS libraries
|
||||||
libraries required by GeoDjango. First, download the `OSGeo4W installer`_,
|
required by GeoDjango. First, download the `OSGeo4W installer`_, and run it.
|
||||||
and run it. Select :menuselection:`Express Web-GIS Install` and click next.
|
Select :menuselection:`Express Web-GIS Install` and click next. In the 'Select
|
||||||
In the 'Select Packages' list, ensure that GDAL is selected; MapServer and
|
Packages' list, ensure that GDAL is selected; MapServer and Apache are also
|
||||||
Apache are also enabled by default, but are not required by GeoDjango and
|
enabled by default, but are not required by GeoDjango and may be unchecked
|
||||||
may be unchecked safely. After clicking next, the packages will be
|
safely. After clicking next, the packages will be automatically downloaded and
|
||||||
automatically downloaded and installed, after which you may exit the
|
installed, after which you may exit the installer.
|
||||||
installer.
|
|
||||||
|
|
||||||
.. _OSGeo4W installer: https://trac.osgeo.org/osgeo4w/
|
.. _OSGeo4W installer: https://trac.osgeo.org/osgeo4w/
|
||||||
|
|
||||||
|
|
|
@ -38,7 +38,7 @@ command line interface and enter the following query::
|
||||||
sqlite> CREATE VIRTUAL TABLE testrtree USING rtree(id,minX,maxX,minY,maxY);
|
sqlite> CREATE VIRTUAL TABLE testrtree USING rtree(id,minX,maxX,minY,maxY);
|
||||||
|
|
||||||
If you obtain an error, you will have to recompile SQLite from source. Otherwise,
|
If you obtain an error, you will have to recompile SQLite from source. Otherwise,
|
||||||
just skip this section.
|
skip this section.
|
||||||
|
|
||||||
To install from sources, download the latest amalgamation source archive from
|
To install from sources, download the latest amalgamation source archive from
|
||||||
the `SQLite download page`__, and extract::
|
the `SQLite download page`__, and extract::
|
||||||
|
|
|
@ -25,8 +25,8 @@ then inserting into a GeoDjango model.
|
||||||
that :class:`LayerMapping` is using too much memory, set
|
that :class:`LayerMapping` is using too much memory, set
|
||||||
:setting:`DEBUG` to ``False`` in your settings. When :setting:`DEBUG`
|
:setting:`DEBUG` to ``False`` in your settings. When :setting:`DEBUG`
|
||||||
is set to ``True``, Django :ref:`automatically logs <faq-see-raw-sql-queries>`
|
is set to ``True``, Django :ref:`automatically logs <faq-see-raw-sql-queries>`
|
||||||
*every* SQL query -- thus, when SQL statements contain geometries, it is
|
*every* SQL query -- and when SQL statements contain geometries, this may
|
||||||
easy to consume more memory than is typical.
|
consume more memory than is typical.
|
||||||
|
|
||||||
Example
|
Example
|
||||||
=======
|
=======
|
||||||
|
@ -75,10 +75,10 @@ Example
|
||||||
Saved: Name: 2
|
Saved: Name: 2
|
||||||
Saved: Name: 3
|
Saved: Name: 3
|
||||||
|
|
||||||
Here, :class:`LayerMapping` just transformed the three geometries from the
|
Here, :class:`LayerMapping` transformed the three geometries from the shapefile
|
||||||
shapefile in their original spatial reference system (WGS84) to the spatial
|
in their original spatial reference system (WGS84) to the spatial reference
|
||||||
reference system of the GeoDjango model (NAD83). If no spatial reference
|
system of the GeoDjango model (NAD83). If no spatial reference system is
|
||||||
system is defined for the layer, use the ``source_srs`` keyword with a
|
defined for the layer, use the ``source_srs`` keyword with a
|
||||||
:class:`~django.contrib.gis.gdal.SpatialReference` object to specify one.
|
:class:`~django.contrib.gis.gdal.SpatialReference` object to specify one.
|
||||||
|
|
||||||
``LayerMapping`` API
|
``LayerMapping`` API
|
||||||
|
|
|
@ -26,8 +26,8 @@ instantiated in units of kilometers (``km``) and miles (``mi``)::
|
||||||
>>> print(d2)
|
>>> print(d2)
|
||||||
5.0 mi
|
5.0 mi
|
||||||
|
|
||||||
Conversions are easy, just access the preferred unit attribute to get a
|
For conversions, access the preferred unit attribute to get a converted
|
||||||
converted distance quantity::
|
distance quantity::
|
||||||
|
|
||||||
>>> print(d1.mi) # Converting 5 kilometers to miles
|
>>> print(d1.mi) # Converting 5 kilometers to miles
|
||||||
3.10685596119
|
3.10685596119
|
||||||
|
|
|
@ -73,8 +73,8 @@ is done from an existing superuser account)::
|
||||||
Windows
|
Windows
|
||||||
-------
|
-------
|
||||||
|
|
||||||
On Windows platforms the pgAdmin III utility may also be used as
|
On Windows platforms you can use the pgAdmin III utility to add superuser
|
||||||
a simple way to add superuser privileges to your database user.
|
privileges to your database user.
|
||||||
|
|
||||||
By default, the PostGIS installer on Windows includes a template
|
By default, the PostGIS installer on Windows includes a template
|
||||||
spatial database entitled ``template_postgis``.
|
spatial database entitled ``template_postgis``.
|
||||||
|
|
|
@ -758,8 +758,8 @@ available with the :class:`~django.contrib.gis.admin.GeoModelAdmin`
|
||||||
The PROJ.4 datum shifting files must be installed (see the :ref:`PROJ.4
|
The PROJ.4 datum shifting files must be installed (see the :ref:`PROJ.4
|
||||||
installation instructions <proj4>` for more details).
|
installation instructions <proj4>` for more details).
|
||||||
|
|
||||||
If you meet this requirement, then just substitute the ``OSMGeoAdmin``
|
If you meet this requirement, then substitute the ``OSMGeoAdmin`` option class
|
||||||
option class in your ``admin.py`` file::
|
in your ``admin.py`` file::
|
||||||
|
|
||||||
admin.site.register(WorldBorder, admin.OSMGeoAdmin)
|
admin.site.register(WorldBorder, admin.OSMGeoAdmin)
|
||||||
|
|
||||||
|
|
|
@ -61,7 +61,7 @@ See the :doc:`contenttypes documentation </ref/contrib/contenttypes>`.
|
||||||
``flatpages``
|
``flatpages``
|
||||||
=============
|
=============
|
||||||
|
|
||||||
A framework for managing simple "flat" HTML content in a database.
|
A framework for managing "flat" HTML content in a database.
|
||||||
|
|
||||||
See the :doc:`flatpages documentation </ref/contrib/flatpages>`.
|
See the :doc:`flatpages documentation </ref/contrib/flatpages>`.
|
||||||
|
|
||||||
|
|
|
@ -194,9 +194,9 @@ If you're using the context processor, your template should be rendered with a
|
||||||
``RequestContext``. Otherwise, ensure ``messages`` is available to
|
``RequestContext``. Otherwise, ensure ``messages`` is available to
|
||||||
the template context.
|
the template context.
|
||||||
|
|
||||||
Even if you know there is only just one message, you should still iterate over
|
Even if you know there is only one message, you should still iterate over the
|
||||||
the ``messages`` sequence, because otherwise the message storage will not be cleared
|
``messages`` sequence, because otherwise the message storage will not be
|
||||||
for the next request.
|
cleared for the next request.
|
||||||
|
|
||||||
The context processor also provides a ``DEFAULT_MESSAGE_LEVELS`` variable which
|
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::
|
||||||
|
@ -235,8 +235,7 @@ The ``Message`` class
|
||||||
.. class:: storage.base.Message
|
.. class:: storage.base.Message
|
||||||
|
|
||||||
When you loop over the list of messages in a template, what you get are
|
When you loop over the list of messages in a template, what you get are
|
||||||
instances of the ``Message`` class. It's quite a simple object, with only a
|
instances of the ``Message`` class. They have only a few attributes:
|
||||||
few attributes:
|
|
||||||
|
|
||||||
* ``message``: The actual text of the message.
|
* ``message``: The actual text of the message.
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,7 @@ may be a good choice for the :ref:`range fields <range-fields>` and
|
||||||
|
|
||||||
.. class:: ArrayField(base_field, size=None, **options)
|
.. class:: ArrayField(base_field, size=None, **options)
|
||||||
|
|
||||||
A field for storing lists of data. Most field types can be used, you simply
|
A field for storing lists of data. Most field types can be used, and you
|
||||||
pass another field instance as the :attr:`base_field
|
pass another field instance as the :attr:`base_field
|
||||||
<ArrayField.base_field>`. You may also specify a :attr:`size
|
<ArrayField.base_field>`. You may also specify a :attr:`size
|
||||||
<ArrayField.size>`. ``ArrayField`` can be nested to store multi-dimensional
|
<ArrayField.size>`. ``ArrayField`` can be nested to store multi-dimensional
|
||||||
|
@ -333,7 +333,7 @@ We will use the following example model::
|
||||||
Key lookups
|
Key lookups
|
||||||
~~~~~~~~~~~
|
~~~~~~~~~~~
|
||||||
|
|
||||||
To query based on a given key, you simply use that key as the lookup name::
|
To query based on a given key, you can use that key as the lookup name::
|
||||||
|
|
||||||
>>> Dog.objects.create(name='Rufus', data={'breed': 'labrador'})
|
>>> Dog.objects.create(name='Rufus', data={'breed': 'labrador'})
|
||||||
>>> Dog.objects.create(name='Meg', data={'breed': 'collie'})
|
>>> Dog.objects.create(name='Meg', data={'breed': 'collie'})
|
||||||
|
@ -537,8 +537,7 @@ We will use the following example model::
|
||||||
Key, index, and path lookups
|
Key, index, and path lookups
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
To query based on a given dictionary key, simply use that key as the lookup
|
To query based on a given dictionary key, use that key as the lookup name::
|
||||||
name::
|
|
||||||
|
|
||||||
>>> Dog.objects.create(name='Rufus', data={
|
>>> Dog.objects.create(name='Rufus', data={
|
||||||
... 'breed': 'labrador',
|
... 'breed': 'labrador',
|
||||||
|
|
|
@ -15,8 +15,7 @@ Fields
|
||||||
|
|
||||||
.. class:: SimpleArrayField(base_field, delimiter=',', max_length=None, min_length=None)
|
.. class:: SimpleArrayField(base_field, delimiter=',', max_length=None, min_length=None)
|
||||||
|
|
||||||
A simple field which maps to an array. It is represented by an HTML
|
A field which maps to an array. It is represented by an HTML ``<input>``.
|
||||||
``<input>``.
|
|
||||||
|
|
||||||
.. attribute:: base_field
|
.. attribute:: base_field
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@ The ``search`` lookup
|
||||||
|
|
||||||
.. fieldlookup:: search
|
.. fieldlookup:: search
|
||||||
|
|
||||||
The simplest way to use full text search is to search a single term against a
|
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::
|
||||||
|
|
||||||
>>> Entry.objects.filter(body_text__search='Cheese')
|
>>> Entry.objects.filter(body_text__search='Cheese')
|
||||||
|
@ -111,9 +111,9 @@ See :ref:`postgresql-fts-search-configuration` for an explanation of the
|
||||||
|
|
||||||
.. class:: SearchRank(vector, query, weights=None)
|
.. class:: SearchRank(vector, query, weights=None)
|
||||||
|
|
||||||
So far, we've just returned the results for which any match between the vector
|
So far, we've returned the results for which any match between the vector and
|
||||||
and the query are possible. It's likely you may wish to order the results by
|
the query are possible. It's likely you may wish to order the results by some
|
||||||
some sort of relevancy. PostgreSQL provides a ranking function which takes into
|
sort of relevancy. PostgreSQL provides a ranking function which takes into
|
||||||
account how often the query terms appear in the document, how close together
|
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
|
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
|
where they occur. The better the match, the higher the value of the rank. To
|
||||||
|
|
|
@ -5,7 +5,7 @@ The redirects app
|
||||||
.. module:: django.contrib.redirects
|
.. module:: django.contrib.redirects
|
||||||
:synopsis: A framework for managing redirects.
|
:synopsis: A framework for managing redirects.
|
||||||
|
|
||||||
Django comes with an optional redirects application. It lets you store simple
|
Django comes with an optional redirects application. It lets you store
|
||||||
redirects in a database and handles the redirecting for you. It uses the HTTP
|
redirects in a database and handles the redirecting for you. It uses the HTTP
|
||||||
response status code ``301 Moved Permanently`` by default.
|
response status code ``301 Moved Permanently`` by default.
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@ How it works
|
||||||
============
|
============
|
||||||
|
|
||||||
``manage.py migrate`` creates a ``django_redirect`` table in your database. This
|
``manage.py migrate`` creates a ``django_redirect`` table in your database. This
|
||||||
is a simple lookup table with ``site_id``, ``old_path`` and ``new_path`` fields.
|
is a lookup table with ``site_id``, ``old_path`` and ``new_path`` fields.
|
||||||
|
|
||||||
The :class:`~django.contrib.redirects.middleware.RedirectFallbackMiddleware`
|
The :class:`~django.contrib.redirects.middleware.RedirectFallbackMiddleware`
|
||||||
does all of the work. Each time any Django application raises a 404
|
does all of the work. Each time any Django application raises a 404
|
||||||
|
|
|
@ -5,8 +5,8 @@ The sitemap framework
|
||||||
.. module:: django.contrib.sitemaps
|
.. module:: django.contrib.sitemaps
|
||||||
:synopsis: A framework for generating Google sitemap XML files.
|
:synopsis: A framework for generating Google sitemap XML files.
|
||||||
|
|
||||||
Django comes with a high-level sitemap-generating framework that makes
|
Django comes with a high-level sitemap-generating framework to create sitemap_
|
||||||
creating sitemap_ XML files easy.
|
XML files.
|
||||||
|
|
||||||
.. _sitemap: https://www.sitemaps.org/
|
.. _sitemap: https://www.sitemaps.org/
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ The Django sitemap framework automates the creation of this XML file by letting
|
||||||
you express this information in Python code.
|
you express this information in Python code.
|
||||||
|
|
||||||
It works much like Django's :doc:`syndication framework
|
It works much like Django's :doc:`syndication framework
|
||||||
</ref/contrib/syndication>`. To create a sitemap, just write a
|
</ref/contrib/syndication>`. To create a sitemap, write a
|
||||||
:class:`~django.contrib.sitemaps.Sitemap` class and point to it in your
|
:class:`~django.contrib.sitemaps.Sitemap` class and point to it in your
|
||||||
:doc:`URLconf </topics/http/urls>`.
|
:doc:`URLconf </topics/http/urls>`.
|
||||||
|
|
||||||
|
@ -76,11 +76,11 @@ a :class:`~django.contrib.sitemaps.Sitemap` class (e.g.,
|
||||||
``Sitemap`` classes
|
``Sitemap`` classes
|
||||||
===================
|
===================
|
||||||
|
|
||||||
A :class:`~django.contrib.sitemaps.Sitemap` class is a simple Python
|
A :class:`~django.contrib.sitemaps.Sitemap` class is a Python class that
|
||||||
class that represents a "section" of entries in your sitemap. For example,
|
represents a "section" of entries in your sitemap. For example, one
|
||||||
one :class:`~django.contrib.sitemaps.Sitemap` class could represent
|
:class:`~django.contrib.sitemaps.Sitemap` class could represent all the entries
|
||||||
all the entries of your Weblog, while another could represent all of the
|
of your Weblog, while another could represent all of the events in your events
|
||||||
events in your events calendar.
|
calendar.
|
||||||
|
|
||||||
In the simplest case, all these sections get lumped together into one
|
In the simplest case, all these sections get lumped together into one
|
||||||
:file:`sitemap.xml`, but it's also possible to use the framework to generate a
|
:file:`sitemap.xml`, but it's also possible to use the framework to generate a
|
||||||
|
@ -90,8 +90,8 @@ sitemap index that references individual sitemap files, one per section. (See
|
||||||
:class:`~django.contrib.sitemaps.Sitemap` classes must subclass
|
:class:`~django.contrib.sitemaps.Sitemap` classes must subclass
|
||||||
``django.contrib.sitemaps.Sitemap``. They can live anywhere in your codebase.
|
``django.contrib.sitemaps.Sitemap``. They can live anywhere in your codebase.
|
||||||
|
|
||||||
A simple example
|
An example
|
||||||
================
|
==========
|
||||||
|
|
||||||
Let's assume you have a blog system, with an ``Entry`` model, and you want your
|
Let's assume you have a blog system, with an ``Entry`` model, and you want your
|
||||||
sitemap to include all the links to your individual blog entries. Here's how
|
sitemap to include all the links to your individual blog entries. Here's how
|
||||||
|
@ -116,11 +116,10 @@ Note:
|
||||||
attributes corresponding to ``<changefreq>`` and ``<priority>`` elements,
|
attributes corresponding to ``<changefreq>`` and ``<priority>`` elements,
|
||||||
respectively. They can be made callable as functions, as
|
respectively. They can be made callable as functions, as
|
||||||
:attr:`~Sitemap.lastmod` was in the example.
|
:attr:`~Sitemap.lastmod` was in the example.
|
||||||
* :attr:`~Sitemap.items()` is simply a method that returns a list of
|
* :attr:`~Sitemap.items()` is a method that returns a list of objects. The
|
||||||
objects. The objects returned will get passed to any callable methods
|
objects returned will get passed to any callable methods corresponding to a
|
||||||
corresponding to a sitemap property (:attr:`~Sitemap.location`,
|
sitemap property (:attr:`~Sitemap.location`, :attr:`~Sitemap.lastmod`,
|
||||||
:attr:`~Sitemap.lastmod`, :attr:`~Sitemap.changefreq`, and
|
:attr:`~Sitemap.changefreq`, and :attr:`~Sitemap.priority`).
|
||||||
:attr:`~Sitemap.priority`).
|
|
||||||
* :attr:`~Sitemap.lastmod` should return a :class:`~datetime.datetime`.
|
* :attr:`~Sitemap.lastmod` should return a :class:`~datetime.datetime`.
|
||||||
* There is no :attr:`~Sitemap.location` method in this example, but you
|
* There is no :attr:`~Sitemap.location` method in this example, but you
|
||||||
can provide it in order to specify the URL for your object. By default,
|
can provide it in order to specify the URL for your object. By default,
|
||||||
|
|
|
@ -13,7 +13,7 @@ the domain names and "verbose" names of your Django-powered sites.
|
||||||
Use it if your single Django installation powers more than one site and you
|
Use it if your single Django installation powers more than one site and you
|
||||||
need to differentiate between those sites in some way.
|
need to differentiate between those sites in some way.
|
||||||
|
|
||||||
The sites framework is mainly based on a simple model:
|
The sites framework is mainly based on this model:
|
||||||
|
|
||||||
.. class:: models.Site
|
.. class:: models.Site
|
||||||
|
|
||||||
|
@ -37,7 +37,7 @@ try to get the current site by comparing the
|
||||||
the :meth:`request.get_host() <django.http.HttpRequest.get_host>` method.
|
the :meth:`request.get_host() <django.http.HttpRequest.get_host>` method.
|
||||||
|
|
||||||
How you use this is up to you, but Django uses it in a couple of ways
|
How you use this is up to you, but Django uses it in a couple of ways
|
||||||
automatically via simple conventions.
|
automatically via a couple of conventions.
|
||||||
|
|
||||||
Example usage
|
Example usage
|
||||||
=============
|
=============
|
||||||
|
@ -58,10 +58,10 @@ publish the same story twice: once for LJWorld.com and again for Lawrence.com.
|
||||||
But that's inefficient for site producers, and it's redundant to store
|
But that's inefficient for site producers, and it's redundant to store
|
||||||
multiple copies of the same story in the database.
|
multiple copies of the same story in the database.
|
||||||
|
|
||||||
The better solution is simple: Both sites use the same article database, and an
|
A better solution removes the content duplication: Both sites use the same
|
||||||
article is associated with one or more sites. In Django model terminology,
|
article database, and an article is associated with one or more sites. In
|
||||||
that's represented by a :class:`~django.db.models.ManyToManyField` in the
|
Django model terminology, that's represented by a
|
||||||
``Article`` model::
|
:class:`~django.db.models.ManyToManyField` in the ``Article`` model::
|
||||||
|
|
||||||
from django.contrib.sites.models import Site
|
from django.contrib.sites.models import Site
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
@ -80,8 +80,8 @@ This accomplishes several things quite nicely:
|
||||||
database; it only has a single record in the database.
|
database; it only has a single record in the database.
|
||||||
|
|
||||||
* It lets the site developers use the same Django view code for both sites.
|
* It lets the site developers use the same Django view code for both sites.
|
||||||
The view code that displays a given story just checks to make sure the
|
The view code that displays a given story checks to make sure the requested
|
||||||
requested story is on the current site. It looks something like this::
|
story is on the current site. It looks something like this::
|
||||||
|
|
||||||
from django.contrib.sites.shortcuts import get_current_site
|
from django.contrib.sites.shortcuts import get_current_site
|
||||||
|
|
||||||
|
@ -215,7 +215,7 @@ subscribing to LJWorld.com alerts." Same goes for the email's message body.
|
||||||
Note that an even more flexible (but more heavyweight) way of doing this would
|
Note that an even more flexible (but more heavyweight) way of doing this would
|
||||||
be to use Django's template system. Assuming Lawrence.com and LJWorld.com have
|
be to use Django's template system. Assuming Lawrence.com and LJWorld.com have
|
||||||
different template directories (:setting:`DIRS <TEMPLATES-DIRS>`), you could
|
different template directories (:setting:`DIRS <TEMPLATES-DIRS>`), you could
|
||||||
simply farm out to the template system like so::
|
farm out to the template system like so::
|
||||||
|
|
||||||
from django.core.mail import send_mail
|
from django.core.mail import send_mail
|
||||||
from django.template import Context, loader
|
from django.template import Context, loader
|
||||||
|
@ -243,7 +243,7 @@ Getting the current domain for full URLs
|
||||||
Django's ``get_absolute_url()`` convention is nice for getting your objects'
|
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
|
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.
|
full URL -- with ``http://`` and the domain and everything -- for an object.
|
||||||
To do this, you can use the sites framework. A simple example::
|
To do this, you can use the sites framework. An example::
|
||||||
|
|
||||||
>>> from django.contrib.sites.models import Site
|
>>> from django.contrib.sites.models import Site
|
||||||
>>> obj = MyModel.objects.get(id=3)
|
>>> obj = MyModel.objects.get(id=3)
|
||||||
|
@ -401,7 +401,7 @@ If you often use this pattern::
|
||||||
site = Site.objects.get_current()
|
site = Site.objects.get_current()
|
||||||
...
|
...
|
||||||
|
|
||||||
there is simple way to avoid repetitions. Add
|
To avoid repetitions, add
|
||||||
:class:`django.contrib.sites.middleware.CurrentSiteMiddleware` to
|
:class:`django.contrib.sites.middleware.CurrentSiteMiddleware` to
|
||||||
:setting:`MIDDLEWARE`. The middleware sets the ``site`` attribute on every
|
:setting:`MIDDLEWARE`. The middleware sets the ``site`` attribute on every
|
||||||
request object, so you can use ``request.site`` to get the current site.
|
request object, so you can use ``request.site`` to get the current site.
|
||||||
|
|
|
@ -387,7 +387,7 @@ hashed names of processed files instead of a static manifest file called
|
||||||
have access to the file system.
|
have access to the file system.
|
||||||
|
|
||||||
If you want to override certain options of the cache backend the storage uses,
|
If you want to override certain options of the cache backend the storage uses,
|
||||||
simply specify a custom entry in the :setting:`CACHES` setting named
|
specify a custom entry in the :setting:`CACHES` setting named
|
||||||
``'staticfiles'``. It falls back to using the ``'default'`` cache backend.
|
``'staticfiles'``. It falls back to using the ``'default'`` cache backend.
|
||||||
|
|
||||||
.. warning::
|
.. warning::
|
||||||
|
|
|
@ -6,8 +6,8 @@ The syndication feed framework
|
||||||
:synopsis: A framework for generating syndication feeds, in RSS and Atom,
|
:synopsis: A framework for generating syndication feeds, in RSS and Atom,
|
||||||
quite easily.
|
quite easily.
|
||||||
|
|
||||||
Django comes with a high-level syndication-feed-generating framework
|
Django comes with a high-level syndication-feed-generating framework for
|
||||||
that makes creating RSS_ and Atom_ feeds easy.
|
creating RSS_ and Atom_ feeds.
|
||||||
|
|
||||||
To create any syndication feed, all you have to do is write a short
|
To create any syndication feed, all you have to do is write a short
|
||||||
Python class. You can create as many feeds as you want.
|
Python class. You can create as many feeds as you want.
|
||||||
|
@ -94,13 +94,12 @@ Note:
|
||||||
standard RSS ``<title>``, ``<link>`` and ``<description>`` elements,
|
standard RSS ``<title>``, ``<link>`` and ``<description>`` elements,
|
||||||
respectively.
|
respectively.
|
||||||
|
|
||||||
* ``items()`` is, simply, a method that returns a list of objects that
|
* ``items()`` is, a method that returns a list of objects that should be
|
||||||
should be included in the feed as ``<item>`` elements. Although this
|
included in the feed as ``<item>`` elements. Although this example returns
|
||||||
example returns ``NewsItem`` objects using Django's
|
``NewsItem`` objects using Django's :doc:`object-relational mapper
|
||||||
:doc:`object-relational mapper </ref/models/querysets>`, ``items()``
|
</ref/models/querysets>`, ``items()`` doesn't have to return model instances.
|
||||||
doesn't have to return model instances. Although you get a few bits of
|
Although you get a few bits of functionality "for free" by using Django
|
||||||
functionality "for free" by using Django models, ``items()`` can
|
models, ``items()`` can return any type of object you want.
|
||||||
return any type of object you want.
|
|
||||||
|
|
||||||
* If you're creating an Atom feed, rather than an RSS feed, set the
|
* If you're creating an Atom feed, rather than an RSS feed, set the
|
||||||
``subtitle`` attribute instead of the ``description`` attribute.
|
``subtitle`` attribute instead of the ``description`` attribute.
|
||||||
|
@ -246,7 +245,7 @@ Here's the code for these beat-specific feeds::
|
||||||
|
|
||||||
To generate the feed's ``<title>``, ``<link>`` and ``<description>``, Django
|
To generate the feed's ``<title>``, ``<link>`` and ``<description>``, Django
|
||||||
uses the ``title()``, ``link()`` and ``description()`` methods. In
|
uses the ``title()``, ``link()`` and ``description()`` methods. In
|
||||||
the previous example, they were simple string class attributes, but this example
|
the previous example, they were string class attributes, but this example
|
||||||
illustrates that they can be either strings *or* methods. For each of
|
illustrates that they can be either strings *or* methods. For each of
|
||||||
``title``, ``link`` and ``description``, Django follows this
|
``title``, ``link`` and ``description``, Django follows this
|
||||||
algorithm:
|
algorithm:
|
||||||
|
@ -262,7 +261,8 @@ Also note that ``items()`` also follows the same algorithm -- first, it
|
||||||
tries ``items(obj)``, then ``items()``, then finally an ``items``
|
tries ``items(obj)``, then ``items()``, then finally an ``items``
|
||||||
class attribute (which should be a list).
|
class attribute (which should be a list).
|
||||||
|
|
||||||
We are using a template for the item descriptions. It can be very simple:
|
We are using a template for the item descriptions. It can be as minimal as
|
||||||
|
this:
|
||||||
|
|
||||||
.. code-block:: html+django
|
.. code-block:: html+django
|
||||||
|
|
||||||
|
@ -333,10 +333,9 @@ Publishing Atom and RSS feeds in tandem
|
||||||
---------------------------------------
|
---------------------------------------
|
||||||
|
|
||||||
Some developers like to make available both Atom *and* RSS versions of their
|
Some developers like to make available both Atom *and* RSS versions of their
|
||||||
feeds. That's easy to do with Django: Just create a subclass of your
|
feeds. To do that, you can create a subclass of your
|
||||||
:class:`~django.contrib.syndication.views.Feed`
|
:class:`~django.contrib.syndication.views.Feed` class and set the ``feed_type``
|
||||||
class and set the ``feed_type`` to something different. Then update your
|
to something different. Then update your URLconf to add the extra versions.
|
||||||
URLconf to add the extra versions.
|
|
||||||
|
|
||||||
Here's a full example::
|
Here's a full example::
|
||||||
|
|
||||||
|
@ -367,8 +366,8 @@ Here's a full example::
|
||||||
subtitle and description are not necessarily the same thing. Instead, you
|
subtitle and description are not necessarily the same thing. Instead, you
|
||||||
should define a ``subtitle`` attribute.
|
should define a ``subtitle`` attribute.
|
||||||
|
|
||||||
In the above example, we simply set the Atom feed's ``subtitle`` to the
|
In the above example, we set the Atom feed's ``subtitle`` to the RSS feed's
|
||||||
RSS feed's ``description``, because it's quite short already.
|
``description``, because it's quite short already.
|
||||||
|
|
||||||
And the accompanying URLconf::
|
And the accompanying URLconf::
|
||||||
|
|
||||||
|
@ -1073,5 +1072,5 @@ For example, you might start implementing an iTunes RSS feed generator like so::
|
||||||
super().add_root_elements(handler)
|
super().add_root_elements(handler)
|
||||||
handler.addQuickElement('itunes:explicit', 'clean')
|
handler.addQuickElement('itunes:explicit', 'clean')
|
||||||
|
|
||||||
Obviously there's a lot more work to be done for a complete custom feed class,
|
There's a lot more work to be done for a complete custom feed class, but the
|
||||||
but the above example should demonstrate the basic idea.
|
above example should demonstrate the basic idea.
|
||||||
|
|
|
@ -80,7 +80,7 @@ set if you've enabled CSRF protection for your views as outlined above.
|
||||||
The CSRF token cookie is named ``csrftoken`` by default, but you can control
|
The CSRF token cookie is named ``csrftoken`` by default, but you can control
|
||||||
the cookie name via the :setting:`CSRF_COOKIE_NAME` setting.
|
the cookie name via the :setting:`CSRF_COOKIE_NAME` setting.
|
||||||
|
|
||||||
Acquiring the token is straightforward:
|
You can acquire the token like this:
|
||||||
|
|
||||||
.. code-block:: javascript
|
.. code-block:: javascript
|
||||||
|
|
||||||
|
@ -227,7 +227,7 @@ when, due to a programming error, the CSRF token has not been included with a
|
||||||
POST form.
|
POST form.
|
||||||
|
|
||||||
The error page, however, is not very friendly, so you may want to provide your
|
The error page, however, is not very friendly, so you may want to provide your
|
||||||
own view for handling this condition. To do this, simply set the
|
own view for handling this condition. To do this, set the
|
||||||
:setting:`CSRF_FAILURE_VIEW` setting.
|
:setting:`CSRF_FAILURE_VIEW` setting.
|
||||||
|
|
||||||
CSRF failures are logged as warnings to the :ref:`django.security.csrf
|
CSRF failures are logged as warnings to the :ref:`django.security.csrf
|
||||||
|
|
|
@ -710,8 +710,8 @@ If you're getting this error, you can solve it by:
|
||||||
# ...
|
# ...
|
||||||
}
|
}
|
||||||
|
|
||||||
This will simply make SQLite wait a bit longer before throwing "database
|
This will make SQLite wait a bit longer before throwing "database is locked"
|
||||||
is locked" errors; it won't really do anything to solve them.
|
errors; it won't really do anything to solve them.
|
||||||
|
|
||||||
``QuerySet.select_for_update()`` not supported
|
``QuerySet.select_for_update()`` not supported
|
||||||
----------------------------------------------
|
----------------------------------------------
|
||||||
|
|
|
@ -213,7 +213,7 @@ specified in your :setting:`USER`, :setting:`PASSWORD`, etc., settings.
|
||||||
* For SQLite, this runs the ``sqlite3`` command-line client.
|
* For SQLite, this runs the ``sqlite3`` command-line client.
|
||||||
* For Oracle, this runs the ``sqlplus`` command-line client.
|
* For Oracle, this runs the ``sqlplus`` command-line client.
|
||||||
|
|
||||||
This command assumes the programs are on your ``PATH`` so that a simple call to
|
This command assumes the programs are on your ``PATH`` so that a call to
|
||||||
the program name (``psql``, ``mysql``, ``sqlite3``, ``sqlplus``) will find the
|
the program name (``psql``, ``mysql``, ``sqlite3``, ``sqlplus``) will find the
|
||||||
program in the right place. There's no way to specify the location of the
|
program in the right place. There's no way to specify the location of the
|
||||||
program manually.
|
program manually.
|
||||||
|
@ -400,7 +400,7 @@ By default, ``inspectdb`` creates unmanaged models. That is, ``managed = False``
|
||||||
in the model's ``Meta`` class tells Django not to manage each table's creation,
|
in the model's ``Meta`` class tells Django not to manage each table's creation,
|
||||||
modification, and deletion. If you do want to allow Django to manage the
|
modification, and deletion. If you do want to allow Django to manage the
|
||||||
table's lifecycle, you'll need to change the
|
table's lifecycle, you'll need to change the
|
||||||
:attr:`~django.db.models.Options.managed` option to ``True`` (or simply remove
|
:attr:`~django.db.models.Options.managed` option to ``True`` (or remove
|
||||||
it because ``True`` is its default value).
|
it because ``True`` is its default value).
|
||||||
|
|
||||||
Database-specific notes
|
Database-specific notes
|
||||||
|
@ -537,7 +537,7 @@ raise an exception::
|
||||||
|
|
||||||
post_save.connect(my_handler, sender=MyModel)
|
post_save.connect(my_handler, sender=MyModel)
|
||||||
|
|
||||||
You could also write a simple decorator to encapsulate this logic::
|
You could also write a decorator to encapsulate this logic::
|
||||||
|
|
||||||
from functools import wraps
|
from functools import wraps
|
||||||
|
|
||||||
|
@ -917,7 +917,7 @@ project for some common errors (see the :djadmin:`check` command). If any
|
||||||
errors are found, they will be printed to standard output.
|
errors are found, they will be printed to standard output.
|
||||||
|
|
||||||
You can run as many concurrent servers as you want, as long as they're on
|
You can run as many concurrent servers as you want, as long as they're on
|
||||||
separate ports. Just execute ``django-admin runserver`` more than once.
|
separate ports by executing ``django-admin runserver`` more than once.
|
||||||
|
|
||||||
Note that the default IP address, ``127.0.0.1``, is not accessible from other
|
Note that the default IP address, ``127.0.0.1``, is not accessible from other
|
||||||
machines on your network. To make your development server viewable to other
|
machines on your network. To make your development server viewable to other
|
||||||
|
@ -1729,7 +1729,7 @@ Example usage::
|
||||||
.. django-admin-option:: --traceback
|
.. django-admin-option:: --traceback
|
||||||
|
|
||||||
Displays a full stack trace when a :exc:`~django.core.management.CommandError`
|
Displays a full stack trace when a :exc:`~django.core.management.CommandError`
|
||||||
is raised. By default, ``django-admin`` will show a simple error message when a
|
is raised. By default, ``django-admin`` will show an error message when a
|
||||||
``CommandError`` occurs and a full stack trace for any other exception.
|
``CommandError`` occurs and a full stack trace for any other exception.
|
||||||
|
|
||||||
Example usage::
|
Example usage::
|
||||||
|
|
|
@ -12,8 +12,8 @@ Uploaded files
|
||||||
|
|
||||||
During file uploads, the actual file data is stored in :attr:`request.FILES
|
During file uploads, the actual file data is stored in :attr:`request.FILES
|
||||||
<django.http.HttpRequest.FILES>`. Each entry in this dictionary is an
|
<django.http.HttpRequest.FILES>`. Each entry in this dictionary is an
|
||||||
``UploadedFile`` object (or a subclass) -- a simple wrapper around an uploaded
|
``UploadedFile`` object (or a subclass) -- a wrapper around an uploaded file.
|
||||||
file. You'll usually use one of these methods to access the uploaded content:
|
You'll usually use one of these methods to access the uploaded content:
|
||||||
|
|
||||||
.. method:: UploadedFile.read()
|
.. method:: UploadedFile.read()
|
||||||
|
|
||||||
|
@ -33,9 +33,9 @@ file. You'll usually use one of these methods to access the uploaded content:
|
||||||
A generator returning chunks of the file. If ``multiple_chunks()`` is
|
A generator returning chunks of the file. If ``multiple_chunks()`` is
|
||||||
``True``, you should use this method in a loop instead of ``read()``.
|
``True``, you should use this method in a loop instead of ``read()``.
|
||||||
|
|
||||||
In practice, it's often easiest simply to use ``chunks()`` all the time.
|
In practice, it's often easiest to use ``chunks()`` all the time. Looping
|
||||||
Looping over ``chunks()`` instead of using ``read()`` ensures that large
|
over ``chunks()`` instead of using ``read()`` ensures that large files
|
||||||
files don't overwhelm your system's memory.
|
don't overwhelm your system's memory.
|
||||||
|
|
||||||
Here are some useful attributes of ``UploadedFile``:
|
Here are some useful attributes of ``UploadedFile``:
|
||||||
|
|
||||||
|
@ -72,8 +72,8 @@ Here are some useful attributes of ``UploadedFile``:
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
Like regular Python files, you can read the file line-by-line simply by
|
Like regular Python files, you can read the file line-by-line by iterating
|
||||||
iterating over the uploaded file:
|
over the uploaded file:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,7 @@ A :class:`Form` instance is either **bound** to a set of data, or **unbound**.
|
||||||
|
|
||||||
.. class:: Form
|
.. class:: Form
|
||||||
|
|
||||||
To create an unbound :class:`Form` instance, simply instantiate the class::
|
To create an unbound :class:`Form` instance, instantiate the class::
|
||||||
|
|
||||||
>>> f = ContactForm()
|
>>> f = ContactForm()
|
||||||
|
|
||||||
|
@ -158,8 +158,9 @@ By default, ``as_json()`` does not escape its output. If you are using it for
|
||||||
something like AJAX requests to a form view where the client interprets the
|
something like AJAX requests to a form view where the client interprets the
|
||||||
response and inserts errors into the page, you'll want to be sure to escape the
|
response and inserts errors into the page, you'll want to be sure to escape the
|
||||||
results on the client-side to avoid the possibility of a cross-site scripting
|
results on the client-side to avoid the possibility of a cross-site scripting
|
||||||
attack. It's trivial to do so using a JavaScript library like jQuery - simply
|
attack. You can do this in JavaScript with ``element.textContent = errorText``
|
||||||
use ``$(el).text(errorText)`` rather than ``.html()``.
|
or with jQuery's ``$(el).text(errorText)`` (rather than its ``.html()``
|
||||||
|
function).
|
||||||
|
|
||||||
If for some reason you don't want to use client-side escaping, you can also
|
If for some reason you don't want to use client-side escaping, you can also
|
||||||
set ``escape_html=True`` and error messages will be escaped so you can use them
|
set ``escape_html=True`` and error messages will be escaped so you can use them
|
||||||
|
@ -185,7 +186,7 @@ should be added. If its value is ``None`` the error will be treated as
|
||||||
a non-field error as returned by :meth:`Form.non_field_errors()
|
a non-field error as returned by :meth:`Form.non_field_errors()
|
||||||
<django.forms.Form.non_field_errors>`.
|
<django.forms.Form.non_field_errors>`.
|
||||||
|
|
||||||
The ``error`` argument can be a simple string, or preferably an instance of
|
The ``error`` argument can be a string, or preferably an instance of
|
||||||
``ValidationError``. See :ref:`raising-validation-error` for best practices
|
``ValidationError``. See :ref:`raising-validation-error` for best practices
|
||||||
when defining form errors.
|
when defining form errors.
|
||||||
|
|
||||||
|
@ -434,7 +435,7 @@ Outputting forms as HTML
|
||||||
========================
|
========================
|
||||||
|
|
||||||
The second task of a ``Form`` object is to render itself as HTML. To do so,
|
The second task of a ``Form`` object is to render itself as HTML. To do so,
|
||||||
simply ``print`` it::
|
``print`` it::
|
||||||
|
|
||||||
>>> f = ContactForm()
|
>>> f = ContactForm()
|
||||||
>>> print(f)
|
>>> print(f)
|
||||||
|
@ -563,7 +564,7 @@ errors. For example, you might want to present required form rows in bold and
|
||||||
highlight errors in red.
|
highlight errors in red.
|
||||||
|
|
||||||
The :class:`Form` class has a couple of hooks you can use to add ``class``
|
The :class:`Form` class has a couple of hooks you can use to add ``class``
|
||||||
attributes to required rows or to rows with errors: simply set the
|
attributes to required rows or to rows with errors: set the
|
||||||
:attr:`Form.error_css_class` and/or :attr:`Form.required_css_class`
|
:attr:`Form.error_css_class` and/or :attr:`Form.required_css_class`
|
||||||
attributes::
|
attributes::
|
||||||
|
|
||||||
|
@ -634,7 +635,7 @@ tags nor ``id`` attributes::
|
||||||
<p>Cc myself: <input type="checkbox" name="cc_myself"></p>
|
<p>Cc myself: <input type="checkbox" name="cc_myself"></p>
|
||||||
|
|
||||||
If ``auto_id`` is set to ``True``, then the form output *will* include
|
If ``auto_id`` is set to ``True``, then the form output *will* include
|
||||||
``<label>`` tags and will simply use the field name as its ``id`` for each form
|
``<label>`` tags and will use the field name as its ``id`` for each form
|
||||||
field::
|
field::
|
||||||
|
|
||||||
>>> f = ContactForm(auto_id=True)
|
>>> f = ContactForm(auto_id=True)
|
||||||
|
@ -750,7 +751,7 @@ In the ``as_p()``, ``as_ul()`` and ``as_table()`` shortcuts, the fields are
|
||||||
displayed in the order in which you define them in your form class. For
|
displayed in the order in which you define them in your form class. For
|
||||||
example, in the ``ContactForm`` example, the fields are defined in the order
|
example, in the ``ContactForm`` example, the fields are defined in the order
|
||||||
``subject``, ``message``, ``sender``, ``cc_myself``. To reorder the HTML
|
``subject``, ``message``, ``sender``, ``cc_myself``. To reorder the HTML
|
||||||
output, just change the order in which those fields are listed in the class.
|
output, change the order in which those fields are listed in the class.
|
||||||
|
|
||||||
There are several other ways to customize the order:
|
There are several other ways to customize the order:
|
||||||
|
|
||||||
|
@ -833,7 +834,7 @@ pass that in at construction time::
|
||||||
More granular output
|
More granular output
|
||||||
====================
|
====================
|
||||||
|
|
||||||
The ``as_p()``, ``as_ul()``, and ``as_table()`` methods are simply shortcuts --
|
The ``as_p()``, ``as_ul()``, and ``as_table()`` methods are shortcuts --
|
||||||
they're not the only way a form object can be displayed.
|
they're not the only way a form object can be displayed.
|
||||||
|
|
||||||
.. class:: BoundField
|
.. class:: BoundField
|
||||||
|
@ -1121,8 +1122,8 @@ form data)::
|
||||||
# Bound form with an image field, data from the request
|
# Bound form with an image field, data from the request
|
||||||
>>> f = ContactFormWithMugshot(request.POST, request.FILES)
|
>>> f = ContactFormWithMugshot(request.POST, request.FILES)
|
||||||
|
|
||||||
Constructing an unbound form is the same as always -- just omit both
|
Constructing an unbound form is the same as always -- omit both form data *and*
|
||||||
form data *and* file data::
|
file data::
|
||||||
|
|
||||||
# Unbound form with an image field
|
# Unbound form with an image field
|
||||||
>>> f = ContactFormWithMugshot()
|
>>> f = ContactFormWithMugshot()
|
||||||
|
|
|
@ -1239,12 +1239,11 @@ method::
|
||||||
Creating custom fields
|
Creating custom fields
|
||||||
======================
|
======================
|
||||||
|
|
||||||
If the built-in ``Field`` classes don't meet your needs, you can easily create
|
If the built-in ``Field`` classes don't meet your needs, you can create custom
|
||||||
custom ``Field`` classes. To do this, just create a subclass of
|
``Field`` classes. To do this, create a subclass of ``django.forms.Field``. Its
|
||||||
``django.forms.Field``. Its only requirements are that it implement a
|
only requirements are that it implement a ``clean()`` method and that its
|
||||||
``clean()`` method and that its ``__init__()`` method accept the core arguments
|
``__init__()`` method accept the core arguments mentioned above (``required``,
|
||||||
mentioned above (``required``, ``label``, ``initial``, ``widget``,
|
``label``, ``initial``, ``widget``, ``help_text``).
|
||||||
``help_text``).
|
|
||||||
|
|
||||||
You can also customize how a field will be accessed by overriding
|
You can also customize how a field will be accessed by overriding
|
||||||
:meth:`~django.forms.Field.get_bound_field()`.
|
:meth:`~django.forms.Field.get_bound_field()`.
|
||||||
|
|
|
@ -19,10 +19,10 @@ for the best practice in raising ``ValidationError``. If no ``ValidationError``
|
||||||
is raised, the method should return the cleaned (normalized) data as a Python
|
is raised, the method should return the cleaned (normalized) data as a Python
|
||||||
object.
|
object.
|
||||||
|
|
||||||
Most validation can be done using `validators`_ - simple helpers that can be
|
Most validation can be done using `validators`_ - helpers that can be reused.
|
||||||
reused easily. Validators are simple functions (or callables) that take a single
|
Validators are functions (or callables) that take a single argument and raise
|
||||||
argument and raise ``ValidationError`` on invalid input. Validators are run
|
``ValidationError`` on invalid input. Validators are run after the field's
|
||||||
after the field's ``to_python`` and ``validate`` methods have been called.
|
``to_python`` and ``validate`` methods have been called.
|
||||||
|
|
||||||
Validation of a form is split into several steps, which can be customized or
|
Validation of a form is split into several steps, which can be customized or
|
||||||
overridden:
|
overridden:
|
||||||
|
@ -65,9 +65,9 @@ overridden:
|
||||||
For example, if you wanted to validate that the contents of a
|
For example, if you wanted to validate that the contents of a
|
||||||
``CharField`` called ``serialnumber`` was unique,
|
``CharField`` called ``serialnumber`` was unique,
|
||||||
``clean_serialnumber()`` would be the right place to do this. You don't
|
``clean_serialnumber()`` would be the right place to do this. You don't
|
||||||
need a specific field (it's just a ``CharField``), but you want a
|
need a specific field (it's a ``CharField``), but you want a
|
||||||
formfield-specific piece of validation and, possibly,
|
formfield-specific piece of validation and, possibly, cleaning/normalizing
|
||||||
cleaning/normalizing the data.
|
the data.
|
||||||
|
|
||||||
The return value of this method replaces the existing value in
|
The return value of this method replaces the existing value in
|
||||||
``cleaned_data``, so it must be the field's value from ``cleaned_data`` (even
|
``cleaned_data``, so it must be the field's value from ``cleaned_data`` (even
|
||||||
|
@ -218,16 +218,16 @@ previous features.
|
||||||
Using validators
|
Using validators
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
Django's form (and model) fields support use of simple utility functions and
|
Django's form (and model) fields support use of utility functions and classes
|
||||||
classes known as validators. A validator is merely a callable object or
|
known as validators. A validator is a callable object or function that takes a
|
||||||
function that takes a value and simply returns nothing if the value is valid or
|
value and returns nothing if the value is valid or raises a
|
||||||
raises a :exc:`~django.core.exceptions.ValidationError` if not. These can be
|
:exc:`~django.core.exceptions.ValidationError` if not. These can be passed to a
|
||||||
passed to a field's constructor, via the field's ``validators`` argument, or
|
field's constructor, via the field's ``validators`` argument, or defined on the
|
||||||
defined on the :class:`~django.forms.Field` class itself with the
|
:class:`~django.forms.Field` class itself with the ``default_validators``
|
||||||
``default_validators`` attribute.
|
attribute.
|
||||||
|
|
||||||
Simple validators can be used to validate values inside the field, let's have
|
Validators can be used to validate values inside the field, let's have a look
|
||||||
a look at Django's ``SlugField``::
|
at Django's ``SlugField``::
|
||||||
|
|
||||||
from django.core import validators
|
from django.core import validators
|
||||||
from django.forms import CharField
|
from django.forms import CharField
|
||||||
|
@ -235,9 +235,9 @@ a look at Django's ``SlugField``::
|
||||||
class SlugField(CharField):
|
class SlugField(CharField):
|
||||||
default_validators = [validators.validate_slug]
|
default_validators = [validators.validate_slug]
|
||||||
|
|
||||||
As you can see, ``SlugField`` is just a ``CharField`` with a customized
|
As you can see, ``SlugField`` is a ``CharField`` with a customized validator
|
||||||
validator that validates that submitted text obeys to some character rules.
|
that validates that submitted text obeys to some character rules. This can also
|
||||||
This can also be done on field definition so::
|
be done on field definition so::
|
||||||
|
|
||||||
slug = forms.SlugField()
|
slug = forms.SlugField()
|
||||||
|
|
||||||
|
@ -281,8 +281,7 @@ Every form that uses this field will have these methods run before anything
|
||||||
else can be done with the field's data. This is cleaning that is specific to
|
else can be done with the field's data. This is cleaning that is specific to
|
||||||
this type of field, regardless of how it is subsequently used.
|
this type of field, regardless of how it is subsequently used.
|
||||||
|
|
||||||
Let's create a simple ``ContactForm`` to demonstrate how you'd use this
|
Let's create a ``ContactForm`` to demonstrate how you'd use this field::
|
||||||
field::
|
|
||||||
|
|
||||||
class ContactForm(forms.Form):
|
class ContactForm(forms.Form):
|
||||||
subject = forms.CharField(max_length=100)
|
subject = forms.CharField(max_length=100)
|
||||||
|
@ -291,10 +290,10 @@ field::
|
||||||
recipients = MultiEmailField()
|
recipients = MultiEmailField()
|
||||||
cc_myself = forms.BooleanField(required=False)
|
cc_myself = forms.BooleanField(required=False)
|
||||||
|
|
||||||
Simply use ``MultiEmailField`` like any other form field. When the
|
Use ``MultiEmailField`` like any other form field. When the ``is_valid()``
|
||||||
``is_valid()`` method is called on the form, the ``MultiEmailField.clean()``
|
method is called on the form, the ``MultiEmailField.clean()`` method will be
|
||||||
method will be run as part of the cleaning process and it will, in turn, call
|
run as part of the cleaning process and it will, in turn, call the custom
|
||||||
the custom ``to_python()`` and ``validate()`` methods.
|
``to_python()`` and ``validate()`` methods.
|
||||||
|
|
||||||
Cleaning a specific field attribute
|
Cleaning a specific field attribute
|
||||||
-----------------------------------
|
-----------------------------------
|
||||||
|
@ -403,7 +402,7 @@ work out what works effectively in your particular situation. Our new code
|
||||||
self.add_error('cc_myself', msg)
|
self.add_error('cc_myself', msg)
|
||||||
self.add_error('subject', msg)
|
self.add_error('subject', msg)
|
||||||
|
|
||||||
The second argument of ``add_error()`` can be a simple string, or preferably
|
The second argument of ``add_error()`` can be a string, or preferably an
|
||||||
an instance of ``ValidationError``. See :ref:`raising-validation-error` for
|
instance of ``ValidationError``. See :ref:`raising-validation-error` for more
|
||||||
more details. Note that ``add_error()`` automatically removes the field
|
details. Note that ``add_error()`` automatically removes the field from
|
||||||
from ``cleaned_data``.
|
``cleaned_data``.
|
||||||
|
|
|
@ -34,8 +34,7 @@ which widget is used on which field, see the documentation about
|
||||||
:ref:`built-in-fields`.
|
:ref:`built-in-fields`.
|
||||||
|
|
||||||
However, if you want to use a different widget for a field, you can
|
However, if you want to use a different widget for a field, you can
|
||||||
just use the :attr:`~Field.widget` argument on the field definition. For
|
use the :attr:`~Field.widget` argument on the field definition. For example::
|
||||||
example::
|
|
||||||
|
|
||||||
from django import forms
|
from django import forms
|
||||||
|
|
||||||
|
@ -127,7 +126,7 @@ need to specify additional attributes at the time when the widget object is
|
||||||
instantiated and assigned to a form field (and perhaps add some rules to your
|
instantiated and assigned to a form field (and perhaps add some rules to your
|
||||||
CSS files).
|
CSS files).
|
||||||
|
|
||||||
For example, take the following simple form::
|
For example, take the following form::
|
||||||
|
|
||||||
from django import forms
|
from django import forms
|
||||||
|
|
||||||
|
@ -770,8 +769,8 @@ that specifies the template used to render each choice. For example, for the
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
If you decide not to loop over the radio buttons -- e.g., if your template
|
If you decide not to loop over the radio buttons -- e.g., if your template
|
||||||
simply includes ``{{ myform.beatles }}`` -- they'll be output in a ``<ul>``
|
includes ``{{ myform.beatles }}`` -- they'll be output in a ``<ul>`` with
|
||||||
with ``<li>`` tags, as above.
|
``<li>`` tags, as above.
|
||||||
|
|
||||||
The outer ``<ul>`` container receives the ``id`` attribute of the widget,
|
The outer ``<ul>`` container receives the ``id`` attribute of the widget,
|
||||||
if defined, or :attr:`BoundField.auto_id` otherwise.
|
if defined, or :attr:`BoundField.auto_id` otherwise.
|
||||||
|
|
|
@ -20,10 +20,10 @@ manipulation. You can also write your own ``Operation`` classes if you want
|
||||||
to encapsulate a custom change you commonly make.
|
to encapsulate a custom change you commonly make.
|
||||||
|
|
||||||
If you need an empty migration file to write your own ``Operation`` objects
|
If you need an empty migration file to write your own ``Operation`` objects
|
||||||
into, just use ``python manage.py makemigrations --empty yourappname``,
|
into, use ``python manage.py makemigrations --empty yourappname``, but be aware
|
||||||
but be aware that manually adding schema-altering operations can confuse the
|
that manually adding schema-altering operations can confuse the migration
|
||||||
migration autodetector and make resulting runs of :djadmin:`makemigrations`
|
autodetector and make resulting runs of :djadmin:`makemigrations` output
|
||||||
output incorrect code.
|
incorrect code.
|
||||||
|
|
||||||
All of the core Django operations are available from the
|
All of the core Django operations are available from the
|
||||||
``django.db.migrations.operations`` module.
|
``django.db.migrations.operations`` module.
|
||||||
|
@ -53,8 +53,8 @@ The field instance should be an unbound field (so just
|
||||||
``bases`` is an optional list of other classes to have this model inherit from;
|
``bases`` is an optional list of other classes to have this model inherit from;
|
||||||
it can contain both class objects as well as strings in the format
|
it can contain both class objects as well as strings in the format
|
||||||
``"appname.ModelName"`` if you want to depend on another model (so you inherit
|
``"appname.ModelName"`` if you want to depend on another model (so you inherit
|
||||||
from the historical version). If it's not supplied, it defaults to just
|
from the historical version). If it's not supplied, it defaults to inheriting
|
||||||
inheriting from the standard ``models.Model``.
|
from the standard ``models.Model``.
|
||||||
|
|
||||||
``managers`` takes a list of 2-tuples of ``(manager_name, manager_instance)``.
|
``managers`` takes a list of 2-tuples of ``(manager_name, manager_instance)``.
|
||||||
The first manager in the list will be the default manager for this model during
|
The first manager in the list will be the default manager for this model during
|
||||||
|
@ -318,9 +318,8 @@ The optional ``elidable`` argument determines whether or not the operation will
|
||||||
be removed (elided) when :ref:`squashing migrations <migration-squashing>`.
|
be removed (elided) when :ref:`squashing migrations <migration-squashing>`.
|
||||||
|
|
||||||
You are advised to write the code as a separate function above the ``Migration``
|
You are advised to write the code as a separate function above the ``Migration``
|
||||||
class in the migration file, and just pass it to ``RunPython``. Here's an
|
class in the migration file, and pass it to ``RunPython``. Here's an example of
|
||||||
example of using ``RunPython`` to create some initial objects on a ``Country``
|
using ``RunPython`` to create some initial objects on a ``Country`` model::
|
||||||
model::
|
|
||||||
|
|
||||||
from django.db import migrations
|
from django.db import migrations
|
||||||
|
|
||||||
|
@ -423,8 +422,8 @@ Writing your own
|
||||||
================
|
================
|
||||||
|
|
||||||
Operations have a relatively simple API, and they're designed so that you can
|
Operations have a relatively simple API, and they're designed so that you can
|
||||||
easily write your own to supplement the built-in Django ones. The basic structure
|
easily write your own to supplement the built-in Django ones. The basic
|
||||||
of an ``Operation`` looks like this::
|
structure of an ``Operation`` looks like this::
|
||||||
|
|
||||||
from django.db.migrations.operations.base import Operation
|
from django.db.migrations.operations.base import Operation
|
||||||
|
|
||||||
|
@ -462,21 +461,21 @@ of an ``Operation`` looks like this::
|
||||||
return "Custom Operation"
|
return "Custom Operation"
|
||||||
|
|
||||||
You can take this template and work from it, though we suggest looking at the
|
You can take this template and work from it, though we suggest looking at the
|
||||||
built-in Django operations in ``django.db.migrations.operations`` - they're
|
built-in Django operations in ``django.db.migrations.operations`` - they cover
|
||||||
easy to read and cover a lot of the example usage of semi-internal aspects
|
a lot of the example usage of semi-internal aspects of the migration framework
|
||||||
of the migration framework like ``ProjectState`` and the patterns used to get
|
like ``ProjectState`` and the patterns used to get historical models, as well
|
||||||
historical models, as well as ``ModelState`` and the patterns used to mutate
|
as ``ModelState`` and the patterns used to mutate historical models in
|
||||||
historical models in ``state_forwards()``.
|
``state_forwards()``.
|
||||||
|
|
||||||
Some things to note:
|
Some things to note:
|
||||||
|
|
||||||
* You don't need to learn too much about ``ProjectState`` to just write simple
|
* You don't need to learn too much about ``ProjectState`` to write migrations;
|
||||||
migrations; just know that it has an ``apps`` property that gives access to
|
just know that it has an ``apps`` property that gives access to an app
|
||||||
an app registry (which you can then call ``get_model`` on).
|
registry (which you can then call ``get_model`` on).
|
||||||
|
|
||||||
* ``database_forwards`` and ``database_backwards`` both get two states passed
|
* ``database_forwards`` and ``database_backwards`` both get two states passed
|
||||||
to them; these just represent the difference the ``state_forwards`` method
|
to them; these represent the difference the ``state_forwards`` method would
|
||||||
would have applied, but are given to you for convenience and speed reasons.
|
have applied, but are given to you for convenience and speed reasons.
|
||||||
|
|
||||||
* If you want to work with model classes or model instances from the
|
* If you want to work with model classes or model instances from the
|
||||||
``from_state`` argument in ``database_forwards()`` or
|
``from_state`` argument in ``database_forwards()`` or
|
||||||
|
@ -506,9 +505,9 @@ Some things to note:
|
||||||
for the :class:`~django.db.models.Manager` instances in
|
for the :class:`~django.db.models.Manager` instances in
|
||||||
``ModelState.managers``.
|
``ModelState.managers``.
|
||||||
|
|
||||||
As a simple example, let's make an operation that loads PostgreSQL extensions
|
As an example, let's make an operation that loads PostgreSQL extensions (which
|
||||||
(which contain some of PostgreSQL's more exciting features). It's simple enough;
|
contain some of PostgreSQL's more exciting features). Since there's no model
|
||||||
there's no model state changes, and all it does is run one command::
|
state changes, all it does is run one command::
|
||||||
|
|
||||||
from django.db.migrations.operations.base import Operation
|
from django.db.migrations.operations.base import Operation
|
||||||
|
|
||||||
|
|
|
@ -96,7 +96,7 @@ A ``Case()`` expression is like the :keyword:`if` ... :keyword:`elif` ...
|
||||||
truthful value. The ``result`` expression from the matching ``When()`` object
|
truthful value. The ``result`` expression from the matching ``When()`` object
|
||||||
is returned.
|
is returned.
|
||||||
|
|
||||||
A simple example::
|
An example::
|
||||||
|
|
||||||
>>>
|
>>>
|
||||||
>>> from datetime import date, timedelta
|
>>> from datetime import date, timedelta
|
||||||
|
|
|
@ -98,8 +98,7 @@ into Python memory.
|
||||||
Instead, Django uses the ``F()`` object to generate an SQL expression that
|
Instead, Django uses the ``F()`` object to generate an SQL expression that
|
||||||
describes the required operation at the database level.
|
describes the required operation at the database level.
|
||||||
|
|
||||||
This is easiest to understand through an example. Normally, one might do
|
Let's try this with an example. Normally, one might do something like this::
|
||||||
something like this::
|
|
||||||
|
|
||||||
# Tintin filed a news story!
|
# Tintin filed a news story!
|
||||||
reporter = Reporters.objects.get(name='Tintin')
|
reporter = Reporters.objects.get(name='Tintin')
|
||||||
|
@ -167,7 +166,7 @@ Python - update a field's value avoids a *race condition*.
|
||||||
If two Python threads execute the code in the first example above, one thread
|
If two Python threads execute the code in the first example above, one thread
|
||||||
could retrieve, increment, and save a field's value after the other has
|
could retrieve, increment, and save a field's value after the other has
|
||||||
retrieved it from the database. The value that the second thread saves will be
|
retrieved it from the database. The value that the second thread saves will be
|
||||||
based on the original value; the work of the first thread will simply be lost.
|
based on the original value; the work of the first thread will be lost.
|
||||||
|
|
||||||
If the database is responsible for updating the field, the process is more
|
If the database is responsible for updating the field, the process is more
|
||||||
robust: it will only ever update the field based on the value of the field in
|
robust: it will only ever update the field based on the value of the field in
|
||||||
|
@ -443,9 +442,9 @@ into the ``template`` attribute.
|
||||||
Creating your own Aggregate Functions
|
Creating your own Aggregate Functions
|
||||||
-------------------------------------
|
-------------------------------------
|
||||||
|
|
||||||
Creating your own aggregate is extremely easy. At a minimum, you need
|
You can create your own aggregate functions, too. At a minimum, you need to
|
||||||
to define ``function``, but you can also completely customize the
|
define ``function``, but you can also completely customize the SQL that is
|
||||||
SQL that is generated. Here's a brief example::
|
generated. Here's a brief example::
|
||||||
|
|
||||||
from django.db.models import Aggregate
|
from django.db.models import Aggregate
|
||||||
|
|
||||||
|
@ -496,8 +495,8 @@ output value.
|
||||||
|
|
||||||
.. class:: ExpressionWrapper(expression, output_field)
|
.. class:: ExpressionWrapper(expression, output_field)
|
||||||
|
|
||||||
``ExpressionWrapper`` simply surrounds another expression and provides access
|
``ExpressionWrapper`` surrounds another expression and provides access to
|
||||||
to properties, such as ``output_field``, that may not be available on other
|
properties, such as ``output_field``, that may not be available on other
|
||||||
expressions. ``ExpressionWrapper`` is necessary when using arithmetic on
|
expressions. ``ExpressionWrapper`` is necessary when using arithmetic on
|
||||||
``F()`` expressions with different types as described in
|
``F()`` expressions with different types as described in
|
||||||
:ref:`using-f-with-annotations`.
|
:ref:`using-f-with-annotations`.
|
||||||
|
@ -754,8 +753,8 @@ The ``order_by`` argument accepts a sequence of expressions on which you can
|
||||||
call :meth:`~django.db.models.Expression.asc` and
|
call :meth:`~django.db.models.Expression.asc` and
|
||||||
:meth:`~django.db.models.Expression.desc`. The ordering controls the order in
|
:meth:`~django.db.models.Expression.desc`. The ordering controls the order in
|
||||||
which the expression is applied. For example, if you sum over the rows in a
|
which the expression is applied. For example, if you sum over the rows in a
|
||||||
partition, the first result is just the value of the first row, the second is
|
partition, the first result is the value of the first row, the second is the
|
||||||
the sum of first and second row.
|
sum of first and second row.
|
||||||
|
|
||||||
The ``frame`` parameter specifies which other rows that should be used in the
|
The ``frame`` parameter specifies which other rows that should be used in the
|
||||||
computation. See :ref:`window-frames` for details.
|
computation. See :ref:`window-frames` for details.
|
||||||
|
@ -773,7 +772,7 @@ the same studio in the same genre and release year::
|
||||||
>>> ),
|
>>> ),
|
||||||
>>> )
|
>>> )
|
||||||
|
|
||||||
This makes it easy to check if a movie is rated better or worse than its peers.
|
This allows you to check if a movie is rated better or worse than its peers.
|
||||||
|
|
||||||
You may want to apply multiple expressions over the same window, i.e., the
|
You may want to apply multiple expressions over the same window, i.e., the
|
||||||
same partition and frame. For example, you could modify the previous example
|
same partition and frame. For example, you could modify the previous example
|
||||||
|
@ -1061,7 +1060,7 @@ We do some basic validation on the parameters, including requiring at least
|
||||||
the eventual result to.
|
the eventual result to.
|
||||||
|
|
||||||
Now we implement the pre-processing and validation. Since we do not have
|
Now we implement the pre-processing and validation. Since we do not have
|
||||||
any of our own validation at this point, we just delegate to the nested
|
any of our own validation at this point, we delegate to the nested
|
||||||
expressions::
|
expressions::
|
||||||
|
|
||||||
def resolve_expression(self, query=None, allow_joins=True, reuse=None, summarize=False, for_save=False):
|
def resolve_expression(self, query=None, allow_joins=True, reuse=None, summarize=False, for_save=False):
|
||||||
|
|
|
@ -127,7 +127,7 @@ define a suitably-named constant for each value::
|
||||||
Though you can define a choices list outside of a model class and then
|
Though you can define a choices list outside of a model class and then
|
||||||
refer to it, defining the choices and names for each choice inside the
|
refer to it, defining the choices and names for each choice inside the
|
||||||
model class keeps all of that information with the class that uses it,
|
model class keeps all of that information with the class that uses it,
|
||||||
and makes the choices easy to reference (e.g, ``Student.SOPHOMORE``
|
and helps reference the choices (e.g, ``Student.SOPHOMORE``
|
||||||
will work anywhere that the ``Student`` model has been imported).
|
will work anywhere that the ``Student`` model has been imported).
|
||||||
|
|
||||||
In addition, Django provides enumeration types that you can subclass to define
|
In addition, Django provides enumeration types that you can subclass to define
|
||||||
|
@ -634,10 +634,10 @@ Any combination of these options will result in an error.
|
||||||
The ``auto_now`` and ``auto_now_add`` options will always use the date in
|
The ``auto_now`` and ``auto_now_add`` options will always use the date in
|
||||||
the :ref:`default timezone <default-current-time-zone>` at the moment of
|
the :ref:`default timezone <default-current-time-zone>` at the moment of
|
||||||
creation or update. If you need something different, you may want to
|
creation or update. If you need something different, you may want to
|
||||||
consider simply using your own callable default or overriding ``save()``
|
consider using your own callable default or overriding ``save()`` instead
|
||||||
instead of using ``auto_now`` or ``auto_now_add``; or using a
|
of using ``auto_now`` or ``auto_now_add``; or using a ``DateTimeField``
|
||||||
``DateTimeField`` instead of a ``DateField`` and deciding how to handle the
|
instead of a ``DateField`` and deciding how to handle the conversion from
|
||||||
conversion from datetime to date at display time.
|
datetime to date at display time.
|
||||||
|
|
||||||
``DateTimeField``
|
``DateTimeField``
|
||||||
-----------------
|
-----------------
|
||||||
|
@ -1582,7 +1582,7 @@ The possible values for :attr:`~ForeignKey.on_delete` are found in
|
||||||
if it is a profile model designed specifically for your custom user model.
|
if it is a profile model designed specifically for your custom user model.
|
||||||
|
|
||||||
Setting it to ``False`` does not mean you can reference a swappable model
|
Setting it to ``False`` does not mean you can reference a swappable model
|
||||||
even if it is swapped out - ``False`` just means that the migrations made
|
even if it is swapped out - ``False`` means that the migrations made
|
||||||
with this ForeignKey will always reference the exact model you specify
|
with this ForeignKey will always reference the exact model you specify
|
||||||
(so it will fail hard if the user tries to run with a User model you don't
|
(so it will fail hard if the user tries to run with a User model you don't
|
||||||
support, for example).
|
support, for example).
|
||||||
|
|
|
@ -16,14 +16,14 @@ Throughout this reference we'll use the :ref:`example Weblog models
|
||||||
Creating objects
|
Creating objects
|
||||||
================
|
================
|
||||||
|
|
||||||
To create a new instance of a model, just instantiate it like any other Python
|
To create a new instance of a model, instantiate it like any other Python
|
||||||
class:
|
class:
|
||||||
|
|
||||||
.. class:: Model(**kwargs)
|
.. class:: Model(**kwargs)
|
||||||
|
|
||||||
The keyword arguments are simply the names of the fields you've defined on your
|
The keyword arguments are the names of the fields you've defined on your model.
|
||||||
model. Note that instantiating a model in no way touches your database; for
|
Note that instantiating a model in no way touches your database; for that, you
|
||||||
that, you need to :meth:`~Model.save()`.
|
need to :meth:`~Model.save()`.
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
|
@ -116,8 +116,8 @@ are loaded from the database::
|
||||||
super().save(*args, **kwargs)
|
super().save(*args, **kwargs)
|
||||||
|
|
||||||
The example above shows a full ``from_db()`` implementation to clarify how that
|
The example above shows a full ``from_db()`` implementation to clarify how that
|
||||||
is done. In this case it would of course be possible to just use ``super()`` call
|
is done. In this case it would of course be possible to use ``super()`` call in
|
||||||
in the ``from_db()`` method.
|
the ``from_db()`` method.
|
||||||
|
|
||||||
Refreshing objects from database
|
Refreshing objects from database
|
||||||
================================
|
================================
|
||||||
|
@ -396,8 +396,8 @@ Explicitly specifying auto-primary-key values
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
If a model has an :class:`~django.db.models.AutoField` but you want to define a
|
If a model has an :class:`~django.db.models.AutoField` but you want to define a
|
||||||
new object's ID explicitly when saving, just define it explicitly before
|
new object's ID explicitly when saving, define it explicitly before saving,
|
||||||
saving, rather than relying on the auto-assignment of the ID::
|
rather than relying on the auto-assignment of the ID::
|
||||||
|
|
||||||
>>> b3 = Blog(id=3, name='Cheddar Talk', tagline='Thoughts on cheese.')
|
>>> b3 = Blog(id=3, name='Cheddar Talk', tagline='Thoughts on cheese.')
|
||||||
>>> b3.id # Returns 3.
|
>>> b3.id # Returns 3.
|
||||||
|
@ -500,8 +500,8 @@ In some rare circumstances, it's necessary to be able to force the
|
||||||
doing an ``UPDATE``. Or vice-versa: update, if possible, but not insert a new
|
doing an ``UPDATE``. Or vice-versa: update, if possible, but not insert a new
|
||||||
row. In these cases you can pass the ``force_insert=True`` or
|
row. In these cases you can pass the ``force_insert=True`` or
|
||||||
``force_update=True`` parameters to the :meth:`~Model.save()` method.
|
``force_update=True`` parameters to the :meth:`~Model.save()` method.
|
||||||
Obviously, passing both parameters is an error: you cannot both insert *and*
|
Passing both parameters is an error: you cannot both insert *and* update at the
|
||||||
update at the same time!
|
same time!
|
||||||
|
|
||||||
It should be very rare that you'll need to use these parameters. Django will
|
It should be very rare that you'll need to use these parameters. Django will
|
||||||
almost always do the right thing and trying to override that will lead to
|
almost always do the right thing and trying to override that will lead to
|
||||||
|
@ -749,9 +749,9 @@ This template code is much better:
|
||||||
<a href="{{ object.get_absolute_url }}">{{ object.name }}</a>
|
<a href="{{ object.get_absolute_url }}">{{ object.name }}</a>
|
||||||
|
|
||||||
The logic here is that if you change the URL structure of your objects, even
|
The logic here is that if you change the URL structure of your objects, even
|
||||||
for something simple such as correcting a spelling error, you don't want to
|
for something small like correcting a spelling error, you don't want to have to
|
||||||
have to track down every place that the URL might be created. Specify it once,
|
track down every place that the URL might be created. Specify it once, in
|
||||||
in ``get_absolute_url()`` and have all your other code call that one place.
|
``get_absolute_url()`` and have all your other code call that one place.
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
The string you return from ``get_absolute_url()`` **must** contain only
|
The string you return from ``get_absolute_url()`` **must** contain only
|
||||||
|
|
|
@ -151,8 +151,8 @@ Here's the formal declaration of a ``QuerySet``:
|
||||||
The ``query`` parameter to :class:`QuerySet` exists so that specialized
|
The ``query`` parameter to :class:`QuerySet` exists so that specialized
|
||||||
query subclasses can reconstruct internal query state. The value of the
|
query subclasses can reconstruct internal query state. The value of the
|
||||||
parameter is an opaque representation of that query state and is not
|
parameter is an opaque representation of that query state and is not
|
||||||
part of a public API. To put it simply: if you need to ask, you don't
|
part of a public API. To put it another way: if you need to ask, you
|
||||||
need to use it.
|
don't need to use it.
|
||||||
|
|
||||||
.. currentmodule:: django.db.models.query.QuerySet
|
.. currentmodule:: django.db.models.query.QuerySet
|
||||||
|
|
||||||
|
@ -1943,7 +1943,7 @@ details. The internal implementation has some more error-checking than this and
|
||||||
handles some extra edge-conditions; if you're interested, read the code.
|
handles some extra edge-conditions; if you're interested, read the code.
|
||||||
|
|
||||||
If you have a field named ``defaults`` and want to use it as an exact lookup in
|
If you have a field named ``defaults`` and want to use it as an exact lookup in
|
||||||
``get_or_create()``, just use ``'defaults__exact'``, like so::
|
``get_or_create()``, use ``'defaults__exact'``, like so::
|
||||||
|
|
||||||
Foo.objects.get_or_create(defaults__exact='bar', defaults={'defaults': 'baz'})
|
Foo.objects.get_or_create(defaults__exact='bar', defaults={'defaults': 'baz'})
|
||||||
|
|
||||||
|
@ -2418,8 +2418,8 @@ gains).
|
||||||
Additionally, if a ``some_queryset`` has not yet been evaluated, but you know
|
Additionally, if a ``some_queryset`` has not yet been evaluated, but you know
|
||||||
that it will be at some point, then using ``some_queryset.exists()`` will do
|
that it will be at some point, then using ``some_queryset.exists()`` will do
|
||||||
more overall work (one query for the existence check plus an extra one to later
|
more overall work (one query for the existence check plus an extra one to later
|
||||||
retrieve the results) than simply using ``bool(some_queryset)``, which
|
retrieve the results) than using ``bool(some_queryset)``, which retrieves the
|
||||||
retrieves the results and then checks if any were returned.
|
results and then checks if any were returned.
|
||||||
|
|
||||||
``update()``
|
``update()``
|
||||||
~~~~~~~~~~~~
|
~~~~~~~~~~~~
|
||||||
|
|
|
@ -91,7 +91,7 @@ Related objects reference
|
||||||
|
|
||||||
# No need to call e.save() at this point -- it's already been saved.
|
# No need to call e.save() at this point -- it's already been saved.
|
||||||
|
|
||||||
This is equivalent to (but much simpler than)::
|
This is equivalent to (but simpler than)::
|
||||||
|
|
||||||
>>> b = Blog.objects.get(id=1)
|
>>> b = Blog.objects.get(id=1)
|
||||||
>>> e = Entry(
|
>>> e = Entry(
|
||||||
|
|
|
@ -34,10 +34,10 @@ If you are writing or maintaining a third-party database backend for Django,
|
||||||
you will need to provide a ``SchemaEditor`` implementation in order to work with
|
you will need to provide a ``SchemaEditor`` implementation in order to work with
|
||||||
1.7's migration functionality - however, as long as your database is relatively
|
1.7's migration functionality - however, as long as your database is relatively
|
||||||
standard in its use of SQL and relational design, you should be able to
|
standard in its use of SQL and relational design, you should be able to
|
||||||
subclass one of the built-in Django ``SchemaEditor`` classes and just tweak the
|
subclass one of the built-in Django ``SchemaEditor`` classes and tweak the
|
||||||
syntax a little. Also note that there are a few new database features that
|
syntax a little. Also note that there are a few new database features that
|
||||||
migrations will look for: ``can_rollback_ddl`` and
|
migrations will look for: ``can_rollback_ddl``
|
||||||
``supports_combined_alters`` are the most important.
|
and ``supports_combined_alters`` are the most important.
|
||||||
|
|
||||||
Methods
|
Methods
|
||||||
=======
|
=======
|
||||||
|
@ -48,8 +48,8 @@ Methods
|
||||||
.. method:: BaseDatabaseSchemaEditor.execute(sql, params=[])
|
.. method:: BaseDatabaseSchemaEditor.execute(sql, params=[])
|
||||||
|
|
||||||
Executes the SQL statement passed in, with parameters if supplied. This
|
Executes the SQL statement passed in, with parameters if supplied. This
|
||||||
is a simple wrapper around the normal database cursors that allows
|
is a wrapper around the normal database cursors that allows capture of the SQL
|
||||||
capture of the SQL to a ``.sql`` file if the user wishes.
|
to a ``.sql`` file if the user wishes.
|
||||||
|
|
||||||
``create_model()``
|
``create_model()``
|
||||||
------------------
|
------------------
|
||||||
|
|
|
@ -196,8 +196,8 @@ See the :ref:`cache documentation <cache_key_prefixing>` for more information.
|
||||||
Default: ``''`` (Empty string)
|
Default: ``''`` (Empty string)
|
||||||
|
|
||||||
The location of the cache to use. This might be the directory for a
|
The location of the cache to use. This might be the directory for a
|
||||||
file system cache, a host and port for a memcache server, or simply an
|
file system cache, a host and port for a memcache server, or an identifying
|
||||||
identifying name for a local memory cache. e.g.::
|
name for a local memory cache. e.g.::
|
||||||
|
|
||||||
CACHES = {
|
CACHES = {
|
||||||
'default': {
|
'default': {
|
||||||
|
@ -2443,8 +2443,8 @@ A list containing the settings for all template engines to be used with
|
||||||
Django. Each item of the list is a dictionary containing the options for an
|
Django. Each item of the list is a dictionary containing the options for an
|
||||||
individual engine.
|
individual engine.
|
||||||
|
|
||||||
Here's a simple setup that tells the Django template engine to load templates
|
Here's a setup that tells the Django template engine to load templates from the
|
||||||
from the ``templates`` subdirectory inside each installed application::
|
``templates`` subdirectory inside each installed application::
|
||||||
|
|
||||||
TEMPLATES = [
|
TEMPLATES = [
|
||||||
{
|
{
|
||||||
|
@ -2657,7 +2657,7 @@ the correct environment.
|
||||||
Default: ``True``
|
Default: ``True``
|
||||||
|
|
||||||
A boolean that specifies whether Django's translation system should be enabled.
|
A boolean that specifies whether Django's translation system should be enabled.
|
||||||
This provides an easy way to turn it off, for performance. If this is set to
|
This provides a way to turn it off, for performance. If this is set to
|
||||||
``False``, Django will make some optimizations so as not to load the
|
``False``, Django will make some optimizations so as not to load the
|
||||||
translation machinery.
|
translation machinery.
|
||||||
|
|
||||||
|
@ -2759,7 +2759,7 @@ Default: ``None``
|
||||||
|
|
||||||
The full Python path of the WSGI application object that Django's built-in
|
The full Python path of the WSGI application object that Django's built-in
|
||||||
servers (e.g. :djadmin:`runserver`) will use. The :djadmin:`django-admin
|
servers (e.g. :djadmin:`runserver`) will use. The :djadmin:`django-admin
|
||||||
startproject <startproject>` management command will create a simple
|
startproject <startproject>` management command will create a standard
|
||||||
``wsgi.py`` file with an ``application`` callable in it, and point this setting
|
``wsgi.py`` file with an ``application`` callable in it, and point this setting
|
||||||
to that ``application``.
|
to that ``application``.
|
||||||
|
|
||||||
|
@ -3374,7 +3374,7 @@ setting.
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
When using the ``AppDirectoriesFinder`` finder, make sure your apps
|
When using the ``AppDirectoriesFinder`` finder, make sure your apps
|
||||||
can be found by staticfiles. Simply add the app to the
|
can be found by staticfiles by adding the app to the
|
||||||
:setting:`INSTALLED_APPS` setting of your site.
|
:setting:`INSTALLED_APPS` setting of your site.
|
||||||
|
|
||||||
Static file finders are currently considered a private interface, and this
|
Static file finders are currently considered a private interface, and this
|
||||||
|
|
|
@ -239,7 +239,7 @@ Some operations -- such as caching -- cannot be performed on an
|
||||||
unrendered template. They must be performed on a fully complete and
|
unrendered template. They must be performed on a fully complete and
|
||||||
rendered response.
|
rendered response.
|
||||||
|
|
||||||
If you're using middleware, the solution is easy. Middleware provides
|
If you're using middleware, you can do that. Middleware provides
|
||||||
multiple opportunities to process a response on exit from a view. If
|
multiple opportunities to process a response on exit from a view. If
|
||||||
you put behavior in the response middleware, it's guaranteed to execute
|
you put behavior in the response middleware, it's guaranteed to execute
|
||||||
after template rendering has taken place.
|
after template rendering has taken place.
|
||||||
|
@ -253,7 +253,7 @@ be invoked when rendering has completed. Using this callback, you can
|
||||||
defer critical processing until a point where you can guarantee that
|
defer critical processing until a point where you can guarantee that
|
||||||
rendered content will be available.
|
rendered content will be available.
|
||||||
|
|
||||||
To define a post-render callback, just define a function that takes
|
To define a post-render callback, define a function that takes
|
||||||
a single argument -- response -- and register that function with
|
a single argument -- response -- and register that function with
|
||||||
the template response::
|
the template response::
|
||||||
|
|
||||||
|
@ -285,8 +285,8 @@ A :class:`TemplateResponse` object can be used anywhere that a normal
|
||||||
:class:`django.http.HttpResponse` can be used. It can also be used as an
|
:class:`django.http.HttpResponse` can be used. It can also be used as an
|
||||||
alternative to calling :func:`~django.shortcuts.render()`.
|
alternative to calling :func:`~django.shortcuts.render()`.
|
||||||
|
|
||||||
For example, the following simple view returns a :class:`TemplateResponse`
|
For example, the following view returns a :class:`TemplateResponse` with a
|
||||||
with a simple template and a context containing a queryset::
|
template and a context containing a queryset::
|
||||||
|
|
||||||
from django.template.response import TemplateResponse
|
from django.template.response import TemplateResponse
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ The Django template language: for Python programmers
|
||||||
.. currentmodule:: django.template
|
.. currentmodule:: django.template
|
||||||
|
|
||||||
This document explains the Django template system from a technical
|
This document explains the Django template system from a technical
|
||||||
perspective -- how it works and how to extend it. If you're just looking for
|
perspective -- how it works and how to extend it. If you're looking for
|
||||||
reference on the language syntax, see :doc:`/ref/templates/language`.
|
reference on the language syntax, see :doc:`/ref/templates/language`.
|
||||||
|
|
||||||
It assumes an understanding of templates, contexts, variables, tags, and
|
It assumes an understanding of templates, contexts, variables, tags, and
|
||||||
|
@ -41,12 +41,12 @@ lower level APIs:
|
||||||
Configuring an engine
|
Configuring an engine
|
||||||
=====================
|
=====================
|
||||||
|
|
||||||
If you are simply using the
|
If you are using the :class:`~django.template.backends.django.DjangoTemplates`
|
||||||
:class:`~django.template.backends.django.DjangoTemplates` backend, this
|
backend, this probably isn't the documentation you're looking for. An instance
|
||||||
probably isn't the documentation you're looking for. An instance of the
|
of the ``Engine`` class described below is accessible using the ``engine``
|
||||||
``Engine`` class described below is accessible using the ``engine`` attribute
|
attribute of that backend and any attribute defaults mentioned below are
|
||||||
of that backend and any attribute defaults mentioned below are overridden by
|
overridden by what's passed by
|
||||||
what's passed by :class:`~django.template.backends.django.DjangoTemplates`.
|
:class:`~django.template.backends.django.DjangoTemplates`.
|
||||||
|
|
||||||
.. class:: Engine(dirs=None, app_dirs=False, context_processors=None, debug=False, loaders=None, string_if_invalid='', file_charset='utf-8', libraries=None, builtins=None, autoescape=True)
|
.. class:: Engine(dirs=None, app_dirs=False, context_processors=None, debug=False, loaders=None, string_if_invalid='', file_charset='utf-8', libraries=None, builtins=None, autoescape=True)
|
||||||
|
|
||||||
|
@ -315,9 +315,8 @@ straight lookups. Here are some things to keep in mind:
|
||||||
|
|
||||||
.. _alters-data-description:
|
.. _alters-data-description:
|
||||||
|
|
||||||
* Obviously, there can be side effects when calling some variables, and
|
* There can be side effects when calling some variables, and it'd be either
|
||||||
it'd be either foolish or a security hole to allow the template system
|
foolish or a security hole to allow the template system to access them.
|
||||||
to access them.
|
|
||||||
|
|
||||||
A good example is the :meth:`~django.db.models.Model.delete` method on
|
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
|
each Django model object. The template system shouldn't be allowed to do
|
||||||
|
@ -754,10 +753,10 @@ variables:
|
||||||
Writing your own context processors
|
Writing your own context processors
|
||||||
-----------------------------------
|
-----------------------------------
|
||||||
|
|
||||||
A context processor has a very simple interface: It's a Python function
|
A context processor has a simple interface: It's a Python function that takes
|
||||||
that takes one argument, an :class:`~django.http.HttpRequest` object, and
|
one argument, an :class:`~django.http.HttpRequest` object, and returns a
|
||||||
returns a dictionary that gets added to the template context. Each context
|
dictionary that gets added to the template context. Each context processor
|
||||||
processor *must* return a dictionary.
|
*must* return a dictionary.
|
||||||
|
|
||||||
Custom context processors can live anywhere in your code base. All Django
|
Custom context processors can live anywhere in your code base. All Django
|
||||||
cares about is that your custom context processors are pointed to by the
|
cares about is that your custom context processors are pointed to by the
|
||||||
|
@ -859,7 +858,7 @@ loaders that come with Django:
|
||||||
subdirectory. If the directory exists, Django looks for templates in there.
|
subdirectory. If the directory exists, Django looks for templates in there.
|
||||||
|
|
||||||
This means you can store templates with your individual apps. This also
|
This means you can store templates with your individual apps. This also
|
||||||
makes it easy to distribute Django apps with default templates.
|
helps to distribute Django apps with default templates.
|
||||||
|
|
||||||
For example, for this setting::
|
For example, for this setting::
|
||||||
|
|
||||||
|
@ -885,8 +884,8 @@ loaders that come with Django:
|
||||||
it caches a list of which :setting:`INSTALLED_APPS` packages have a
|
it caches a list of which :setting:`INSTALLED_APPS` packages have a
|
||||||
``templates`` subdirectory.
|
``templates`` subdirectory.
|
||||||
|
|
||||||
You can enable this loader simply by setting
|
You can enable this loader by setting :setting:`APP_DIRS
|
||||||
:setting:`APP_DIRS <TEMPLATES-APP_DIRS>` to ``True``::
|
<TEMPLATES-APP_DIRS>` to ``True``::
|
||||||
|
|
||||||
TEMPLATES = [{
|
TEMPLATES = [{
|
||||||
'BACKEND': 'django.template.backends.django.DjangoTemplates',
|
'BACKEND': 'django.template.backends.django.DjangoTemplates',
|
||||||
|
|
|
@ -123,7 +123,7 @@ You can mix variables and strings::
|
||||||
|
|
||||||
In some cases you might want to refer to the current value of a cycle
|
In some cases you might want to refer to the current value of a cycle
|
||||||
without advancing to the next value. To do this,
|
without advancing to the next value. To do this,
|
||||||
just give the ``{% cycle %}`` tag a name, using "as", like this::
|
give the ``{% cycle %}`` tag a name, using "as", like this::
|
||||||
|
|
||||||
{% cycle 'row1' 'row2' as rowcolors %}
|
{% cycle 'row1' 'row2' as rowcolors %}
|
||||||
|
|
||||||
|
@ -2182,9 +2182,9 @@ the output will be the string ``"01:23"`` (The ``"TIME_FORMAT"`` format
|
||||||
specifier for the ``de`` locale as shipped with Django is ``"H:i"``).
|
specifier for the ``de`` locale as shipped with Django is ``"H:i"``).
|
||||||
|
|
||||||
The ``time`` filter will only accept parameters in the format string that
|
The ``time`` filter will only accept parameters in the format string that
|
||||||
relate to the time of day, not the date (for obvious reasons). If you need to
|
relate to the time of day, not the date. If you need to format a ``date``
|
||||||
format a ``date`` value, use the :tfilter:`date` filter instead (or along
|
value, use the :tfilter:`date` filter instead (or along with :tfilter:`time` if
|
||||||
``time`` if you need to render a full :py:class:`~datetime.datetime` value).
|
you need to render a full :py:class:`~datetime.datetime` value).
|
||||||
|
|
||||||
There is one exception the above rule: When passed a ``datetime`` value with
|
There is one exception the above rule: When passed a ``datetime`` value with
|
||||||
attached timezone information (a :ref:`time-zone-aware
|
attached timezone information (a :ref:`time-zone-aware
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue