mirror of https://github.com/django/django.git
Refs #34140 -- Corrected rst code-block and various formatting issues in docs.
This commit is contained in:
parent
c67ea79aa9
commit
ba755ca131
|
@ -51,7 +51,7 @@ Lookup registration can also be done using a decorator pattern::
|
|||
|
||||
@Field.register_lookup
|
||||
class NotEqualLookup(Lookup):
|
||||
# ...
|
||||
...
|
||||
|
||||
We can now use ``foo__ne`` for any field ``foo``. You will need to ensure that
|
||||
this registration happens before you try to create any querysets using it. You
|
||||
|
|
|
@ -117,7 +117,7 @@ file ``general.log`` (at the project root):
|
|||
:emphasize-lines: 3-8
|
||||
|
||||
LOGGING = {
|
||||
[...]
|
||||
# ...
|
||||
'handlers': {
|
||||
'file': {
|
||||
'class': 'logging.FileHandler',
|
||||
|
@ -156,7 +156,7 @@ example:
|
|||
:emphasize-lines: 3-8
|
||||
|
||||
LOGGING = {
|
||||
[...]
|
||||
# ...
|
||||
'loggers': {
|
||||
'': {
|
||||
'level': 'DEBUG',
|
||||
|
@ -195,7 +195,7 @@ formatters named ``verbose`` and ``simple``:
|
|||
:emphasize-lines: 3-12
|
||||
|
||||
LOGGING = {
|
||||
[...]
|
||||
# ...
|
||||
'formatters': {
|
||||
'verbose': {
|
||||
'format': '{name} {levelname} {asctime} {module} {process:d} {thread:d} {message}',
|
||||
|
@ -226,7 +226,7 @@ dictionary referring to the formatter by name, for example:
|
|||
'filename': 'general.log',
|
||||
'formatter': 'verbose',
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
.. _naming-loggers:
|
||||
|
||||
|
@ -253,7 +253,7 @@ A logger mapping named ``my_app.views`` will capture records from this logger:
|
|||
:emphasize-lines: 4
|
||||
|
||||
LOGGING = {
|
||||
[...]
|
||||
# ...
|
||||
'loggers': {
|
||||
'my_app.views': {
|
||||
...
|
||||
|
@ -269,7 +269,7 @@ from loggers anywhere within the ``my_app`` namespace (including
|
|||
:emphasize-lines: 4
|
||||
|
||||
LOGGING = {
|
||||
[...]
|
||||
# ...
|
||||
'loggers': {
|
||||
'my_app': {
|
||||
...
|
||||
|
@ -297,16 +297,16 @@ by a mapping for both ``my_app`` and ``my_app.views``.
|
|||
To manage this behavior, set the propagation key on the mappings you define::
|
||||
|
||||
LOGGING = {
|
||||
[...]
|
||||
# ...
|
||||
'loggers': {
|
||||
'my_app': {
|
||||
[...]
|
||||
# ...
|
||||
},
|
||||
'my_app.views': {
|
||||
[...]
|
||||
# ...
|
||||
},
|
||||
'my_app.views.private': {
|
||||
[...]
|
||||
# ...
|
||||
'propagate': False,
|
||||
},
|
||||
},
|
||||
|
|
|
@ -42,7 +42,7 @@ called ``blog``, which provides the templates ``blog/post.html`` and
|
|||
'BACKEND': 'django.template.backends.django.DjangoTemplates',
|
||||
'DIRS': [BASE_DIR / 'templates'],
|
||||
'APP_DIRS': True,
|
||||
...
|
||||
# ...
|
||||
},
|
||||
]
|
||||
|
||||
|
@ -77,9 +77,9 @@ First, make sure your template settings are checking inside app directories::
|
|||
|
||||
TEMPLATES = [
|
||||
{
|
||||
...,
|
||||
# ...
|
||||
'APP_DIRS': True,
|
||||
...
|
||||
# ...
|
||||
},
|
||||
]
|
||||
|
||||
|
|
|
@ -199,9 +199,10 @@ Imports
|
|||
|
||||
|
||||
class Example:
|
||||
# ...
|
||||
...
|
||||
|
||||
* Use convenience imports whenever available. For example, do this::
|
||||
* Use convenience imports whenever available. For example, do this
|
||||
::
|
||||
|
||||
from django.views import View
|
||||
|
||||
|
@ -236,12 +237,12 @@ View style
|
|||
Do this::
|
||||
|
||||
def my_view(request, foo):
|
||||
# ...
|
||||
...
|
||||
|
||||
Don't do this::
|
||||
|
||||
def my_view(req, foo):
|
||||
# ...
|
||||
...
|
||||
|
||||
Model style
|
||||
===========
|
||||
|
|
|
@ -207,6 +207,7 @@ You can also add a test for the deprecation warning::
|
|||
msg = 'Expected deprecation message'
|
||||
with self.assertWarnsMessage(RemovedInDjangoXXWarning, msg):
|
||||
# invoke deprecated behavior
|
||||
...
|
||||
|
||||
Finally, there are a couple of updates to Django's documentation to make:
|
||||
|
||||
|
|
|
@ -163,7 +163,7 @@ this. For a small app like polls, this process isn't too difficult.
|
|||
1. Add "polls" to your INSTALLED_APPS setting like this::
|
||||
|
||||
INSTALLED_APPS = [
|
||||
...
|
||||
...,
|
||||
'polls',
|
||||
]
|
||||
|
||||
|
|
|
@ -115,7 +115,9 @@ and traverses the patterns in order. After finding the match at ``'polls/'``,
|
|||
it strips off the matching text (``"polls/"``) and sends the remaining text --
|
||||
``"34/"`` -- to the 'polls.urls' URLconf for further processing. There it
|
||||
matches ``'<int:question_id>/'``, resulting in a call to the ``detail()`` view
|
||||
like so::
|
||||
like so:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
detail(request=<HttpRequest object>, question_id=34)
|
||||
|
||||
|
|
|
@ -171,7 +171,7 @@ tabular way of displaying inline related objects. To use it, change the
|
|||
:caption: ``polls/admin.py``
|
||||
|
||||
class ChoiceInline(admin.TabularInline):
|
||||
#...
|
||||
...
|
||||
|
||||
With that ``TabularInline`` (instead of ``StackedInline``), the
|
||||
related objects are displayed in a more compact, table-based format:
|
||||
|
|
|
@ -76,9 +76,9 @@ Alternatively, :setting:`INSTALLED_APPS` may contain the dotted path to a
|
|||
configuration class to specify it explicitly::
|
||||
|
||||
INSTALLED_APPS = [
|
||||
...
|
||||
...,
|
||||
'polls.apps.PollsAppConfig',
|
||||
...
|
||||
...,
|
||||
]
|
||||
|
||||
For application authors
|
||||
|
|
|
@ -58,9 +58,9 @@ To set the same ``X-Frame-Options`` value for all responses in your site, put
|
|||
:setting:`MIDDLEWARE`::
|
||||
|
||||
MIDDLEWARE = [
|
||||
...
|
||||
...,
|
||||
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
||||
...
|
||||
...,
|
||||
]
|
||||
|
||||
This middleware is enabled in the settings file generated by
|
||||
|
|
|
@ -722,6 +722,8 @@ subclass::
|
|||
like::
|
||||
|
||||
@admin.display(ordering='-first_name')
|
||||
def colored_first_name(self):
|
||||
...
|
||||
|
||||
The ``ordering`` argument supports query lookups to sort by values on
|
||||
related models. This example includes an "author first name" column in
|
||||
|
@ -752,7 +754,8 @@ subclass::
|
|||
def full_name(self):
|
||||
return self.first_name + ' ' + self.last_name
|
||||
|
||||
* Elements of ``list_display`` can also be properties::
|
||||
* Elements of ``list_display`` can also be properties
|
||||
::
|
||||
|
||||
class Person(models.Model):
|
||||
first_name = models.CharField(max_length=50)
|
||||
|
@ -2993,9 +2996,9 @@ returns a site instance.
|
|||
:caption: ``myproject/settings.py``
|
||||
|
||||
INSTALLED_APPS = [
|
||||
...
|
||||
# ...
|
||||
'myproject.apps.MyAdminConfig', # replaces 'django.contrib.admin'
|
||||
...
|
||||
# ...
|
||||
]
|
||||
|
||||
.. _multiple-admin-sites:
|
||||
|
|
|
@ -139,7 +139,7 @@ Geometry Lookups
|
|||
Geographic queries with geometries take the following general form (assuming
|
||||
the ``Zipcode`` model used in the :doc:`model-api`):
|
||||
|
||||
.. code-block:: pycon
|
||||
.. code-block:: text
|
||||
|
||||
>>> qs = Zipcode.objects.filter(<field>__<lookup_type>=<parameter>)
|
||||
>>> qs = Zipcode.objects.exclude(...)
|
||||
|
@ -175,7 +175,7 @@ band index can be specified.
|
|||
This results in the following general form for lookups involving rasters
|
||||
(assuming the ``Elevation`` model used in the :doc:`model-api`):
|
||||
|
||||
.. code-block:: pycon
|
||||
.. code-block:: text
|
||||
|
||||
>>> qs = Elevation.objects.filter(<field>__<lookup_type>=<parameter>)
|
||||
>>> qs = Elevation.objects.filter(<field>__<band_index>__<lookup_type>=<parameter>)
|
||||
|
|
|
@ -1007,15 +1007,15 @@ Coordinate System Objects
|
|||
>>> proj = '+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs '
|
||||
>>> wgs84 = SpatialReference(proj) # PROJ string
|
||||
>>> wgs84 = SpatialReference("""GEOGCS["WGS 84",
|
||||
DATUM["WGS_1984",
|
||||
SPHEROID["WGS 84",6378137,298.257223563,
|
||||
AUTHORITY["EPSG","7030"]],
|
||||
AUTHORITY["EPSG","6326"]],
|
||||
PRIMEM["Greenwich",0,
|
||||
AUTHORITY["EPSG","8901"]],
|
||||
UNIT["degree",0.01745329251994328,
|
||||
AUTHORITY["EPSG","9122"]],
|
||||
AUTHORITY["EPSG","4326"]]""") # OGC WKT
|
||||
... DATUM["WGS_1984",
|
||||
... SPHEROID["WGS 84",6378137,298.257223563,
|
||||
... AUTHORITY["EPSG","7030"]],
|
||||
... AUTHORITY["EPSG","6326"]],
|
||||
... PRIMEM["Greenwich",0,
|
||||
... AUTHORITY["EPSG","8901"]],
|
||||
... UNIT["degree",0.01745329251994328,
|
||||
... AUTHORITY["EPSG","9122"]],
|
||||
... AUTHORITY["EPSG","4326"]]""") # OGC WKT
|
||||
|
||||
.. method:: __getitem__(target)
|
||||
|
||||
|
@ -1025,7 +1025,7 @@ Coordinate System Objects
|
|||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> wkt = 'GEOGCS["WGS 84", DATUM["WGS_1984, ... AUTHORITY["EPSG","4326"]]')
|
||||
>>> wkt = 'GEOGCS["WGS 84", DATUM["WGS_1984, ... AUTHORITY["EPSG","4326"]]'
|
||||
>>> srs = SpatialReference(wkt) # could also use 'WGS84', or 4326
|
||||
>>> print(srs['GEOGCS'])
|
||||
WGS 84
|
||||
|
|
|
@ -702,11 +702,13 @@ Distance Lookups
|
|||
For an overview on performing distance queries, please refer to
|
||||
the :ref:`distance queries introduction <distance-queries>`.
|
||||
|
||||
Distance lookups take the following form::
|
||||
Distance lookups take the following form:
|
||||
|
||||
<field>__<distance lookup>=(<geometry/raster>, <distance value>[, 'spheroid'])
|
||||
<field>__<distance lookup>=(<raster>, <band_index>, <distance value>[, 'spheroid'])
|
||||
<field>__<band_index>__<distance lookup>=(<raster>, <band_index>, <distance value>[, 'spheroid'])
|
||||
.. code-block:: text
|
||||
|
||||
<field>__<distance lookup>=(<geometry/raster>, <distance value>[, "spheroid"])
|
||||
<field>__<distance lookup>=(<raster>, <band_index>, <distance value>[, "spheroid"])
|
||||
<field>__<band_index>__<distance lookup>=(<raster>, <band_index>, <distance value>[, "spheroid"])
|
||||
|
||||
The value passed into a distance lookup is a tuple; the first two
|
||||
values are mandatory, and are the geometry to calculate distances to,
|
||||
|
|
|
@ -822,7 +822,7 @@ Other Properties & Methods
|
|||
.. code-block:: pycon
|
||||
|
||||
>>> if poly_1.area > poly_2.area:
|
||||
>>> pass
|
||||
... pass
|
||||
|
||||
.. _geos-geometry-collections:
|
||||
|
||||
|
|
|
@ -70,9 +70,10 @@ Example
|
|||
|
||||
>>> from django.contrib.gis.utils import LayerMapping
|
||||
>>> from geoapp.models import TestGeo
|
||||
>>> mapping = {'name' : 'str', # The 'name' model field maps to the 'str' layer field.
|
||||
'poly' : 'POLYGON', # For geometry fields use OGC name.
|
||||
} # The mapping is a dictionary
|
||||
>>> mapping = {
|
||||
... 'name': 'str', # The 'name' model field maps to the 'str' layer field.
|
||||
... 'poly': 'POLYGON', # For geometry fields use OGC name.
|
||||
... } # The mapping is a dictionary
|
||||
>>> lm = LayerMapping(TestGeo, 'test_poly.shp', mapping)
|
||||
>>> lm.save(verbose=True) # Save the layermap, imports the data.
|
||||
Saved: Name: 1
|
||||
|
|
|
@ -575,7 +575,6 @@ Here's a sample configuration which uses a MySQL option file::
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
# my.cnf
|
||||
|
@ -1017,14 +1016,14 @@ using RAC or pluggable databases without ``tnsnames.ora``, for example.
|
|||
|
||||
Example of an Easy Connect string::
|
||||
|
||||
'NAME': 'localhost:1521/orclpdb1',
|
||||
'NAME': 'localhost:1521/orclpdb1'
|
||||
|
||||
Example of a full DSN string::
|
||||
|
||||
'NAME': (
|
||||
'(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=localhost)(PORT=1521))'
|
||||
'(CONNECT_DATA=(SERVICE_NAME=orclpdb1)))'
|
||||
),
|
||||
)
|
||||
|
||||
Threaded option
|
||||
---------------
|
||||
|
@ -1035,7 +1034,7 @@ the ``threaded`` option of your Oracle database configuration to ``True``::
|
|||
|
||||
'OPTIONS': {
|
||||
'threaded': True,
|
||||
},
|
||||
}
|
||||
|
||||
Failure to do this may result in crashes and other odd behavior.
|
||||
|
||||
|
@ -1051,7 +1050,7 @@ The ``RETURNING INTO`` clause can be disabled by setting the
|
|||
|
||||
'OPTIONS': {
|
||||
'use_returning_into': False,
|
||||
},
|
||||
}
|
||||
|
||||
In this case, the Oracle backend will use a separate ``SELECT`` query to
|
||||
retrieve ``AutoField`` values.
|
||||
|
@ -1160,7 +1159,7 @@ file::
|
|||
DATABASES = {
|
||||
'default': {
|
||||
'ENGINE': 'mydbengine',
|
||||
...
|
||||
# ...
|
||||
},
|
||||
}
|
||||
|
||||
|
|
|
@ -1429,7 +1429,7 @@ need to bind the file data containing the mugshot image:
|
|||
... 'message': 'Hi there',
|
||||
... 'sender': 'foo@example.com',
|
||||
... 'cc_myself': True}
|
||||
>>> file_data = {'mugshot': SimpleUploadedFile('face.jpg', <file data>)}
|
||||
>>> file_data = {'mugshot': SimpleUploadedFile('face.jpg', b"file data")}
|
||||
>>> f = ContactFormWithMugshot(data, file_data)
|
||||
|
||||
In practice, you will usually specify ``request.FILES`` as the source
|
||||
|
|
|
@ -746,7 +746,7 @@ For each field, we describe the default widget used if you don't specify
|
|||
>>> from django.core.files.uploadedfile import SimpleUploadedFile
|
||||
>>> class ImageForm(forms.Form):
|
||||
... img = forms.ImageField()
|
||||
>>> file_data = {'img': SimpleUploadedFile('test.png', <file data>)}
|
||||
>>> file_data = {'img': SimpleUploadedFile('test.png', b"file data")}
|
||||
>>> form = ImageForm({}, file_data)
|
||||
# Pillow closes the underlying file descriptor.
|
||||
>>> form.is_valid()
|
||||
|
|
|
@ -228,17 +228,21 @@ logger, but only to the ``django.security`` logger.
|
|||
To silence a particular type of ``SuspiciousOperation``, you can override that
|
||||
specific logger following this example::
|
||||
|
||||
'handlers': {
|
||||
'null': {
|
||||
'class': 'logging.NullHandler',
|
||||
LOGGING = {
|
||||
# ...
|
||||
'handlers': {
|
||||
'null': {
|
||||
'class': 'logging.NullHandler',
|
||||
},
|
||||
},
|
||||
},
|
||||
'loggers': {
|
||||
'django.security.DisallowedHost': {
|
||||
'handlers': ['null'],
|
||||
'propagate': False,
|
||||
'loggers': {
|
||||
'django.security.DisallowedHost': {
|
||||
'handlers': ['null'],
|
||||
'propagate': False,
|
||||
},
|
||||
},
|
||||
},
|
||||
# ...
|
||||
}
|
||||
|
||||
Other ``django.security`` loggers not based on ``SuspiciousOperation`` are:
|
||||
|
||||
|
@ -286,7 +290,7 @@ Python logging module <python:logging.handlers>`.
|
|||
'class': 'django.utils.log.AdminEmailHandler',
|
||||
'include_html': True,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
Be aware of the :ref:`security implications of logging
|
||||
<logging-security-implications>` when using the ``AdminEmailHandler``.
|
||||
|
@ -301,7 +305,7 @@ Python logging module <python:logging.handlers>`.
|
|||
'class': 'django.utils.log.AdminEmailHandler',
|
||||
'email_backend': 'django.core.mail.backends.filebased.EmailBackend',
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
By default, an instance of the email backend specified in
|
||||
:setting:`EMAIL_BACKEND` will be used.
|
||||
|
@ -318,7 +322,7 @@ Python logging module <python:logging.handlers>`.
|
|||
'include_html': True,
|
||||
'reporter_class': 'somepackage.error_reporter.CustomErrorReporter',
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
.. method:: send_mail(subject, message, *args, **kwargs)
|
||||
|
||||
|
@ -354,19 +358,23 @@ logging module.
|
|||
|
||||
and then add it to your logging config::
|
||||
|
||||
'filters': {
|
||||
'skip_unreadable_posts': {
|
||||
'()': 'django.utils.log.CallbackFilter',
|
||||
'callback': skip_unreadable_post,
|
||||
LOGGING = {
|
||||
# ...
|
||||
'filters': {
|
||||
'skip_unreadable_posts': {
|
||||
'()': 'django.utils.log.CallbackFilter',
|
||||
'callback': skip_unreadable_post,
|
||||
},
|
||||
},
|
||||
},
|
||||
'handlers': {
|
||||
'mail_admins': {
|
||||
'level': 'ERROR',
|
||||
'filters': ['skip_unreadable_posts'],
|
||||
'class': 'django.utils.log.AdminEmailHandler',
|
||||
'handlers': {
|
||||
'mail_admins': {
|
||||
'level': 'ERROR',
|
||||
'filters': ['skip_unreadable_posts'],
|
||||
'class': 'django.utils.log.AdminEmailHandler',
|
||||
},
|
||||
},
|
||||
},
|
||||
# ...
|
||||
}
|
||||
|
||||
.. class:: RequireDebugFalse()
|
||||
|
||||
|
@ -376,18 +384,22 @@ logging module.
|
|||
configuration to ensure that the :class:`AdminEmailHandler` only sends
|
||||
error emails to admins when :setting:`DEBUG` is ``False``::
|
||||
|
||||
'filters': {
|
||||
'require_debug_false': {
|
||||
'()': 'django.utils.log.RequireDebugFalse',
|
||||
LOGGING = {
|
||||
# ...
|
||||
'filters': {
|
||||
'require_debug_false': {
|
||||
'()': 'django.utils.log.RequireDebugFalse',
|
||||
},
|
||||
},
|
||||
},
|
||||
'handlers': {
|
||||
'mail_admins': {
|
||||
'level': 'ERROR',
|
||||
'filters': ['require_debug_false'],
|
||||
'class': 'django.utils.log.AdminEmailHandler',
|
||||
'handlers': {
|
||||
'mail_admins': {
|
||||
'level': 'ERROR',
|
||||
'filters': ['require_debug_false'],
|
||||
'class': 'django.utils.log.AdminEmailHandler',
|
||||
},
|
||||
},
|
||||
},
|
||||
# ...
|
||||
}
|
||||
|
||||
.. class:: RequireDebugTrue()
|
||||
|
||||
|
|
|
@ -1885,7 +1885,9 @@ more frequently.
|
|||
.. class:: PercentRank(*expressions, **extra)
|
||||
|
||||
Computes the relative rank of the rows in the frame clause. This computation is
|
||||
equivalent to evaluating::
|
||||
equivalent to evaluating:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
(rank - 1) / (total rows - 1)
|
||||
|
||||
|
|
|
@ -21,20 +21,20 @@ constants, variables, and even other expressions.
|
|||
Some examples
|
||||
=============
|
||||
|
||||
.. code-block:: python
|
||||
.. code-block:: pycon
|
||||
|
||||
from django.db.models import Count, F, Value
|
||||
from django.db.models.functions import Length, Upper
|
||||
from django.db.models.lookups import GreaterThan
|
||||
>>> from django.db.models import Count, F, Value
|
||||
>>> from django.db.models.functions import Length, Upper
|
||||
>>> from django.db.models.lookups import GreaterThan
|
||||
|
||||
# Find companies that have more employees than chairs.
|
||||
Company.objects.filter(num_employees__gt=F('num_chairs'))
|
||||
>>> Company.objects.filter(num_employees__gt=F('num_chairs'))
|
||||
|
||||
# Find companies that have at least twice as many employees
|
||||
# as chairs. Both the querysets below are equivalent.
|
||||
Company.objects.filter(num_employees__gt=F('num_chairs') * 2)
|
||||
Company.objects.filter(
|
||||
num_employees__gt=F('num_chairs') + F('num_chairs'))
|
||||
>>> Company.objects.filter(num_employees__gt=F('num_chairs') * 2)
|
||||
>>> Company.objects.filter(
|
||||
... num_employees__gt=F('num_chairs') + F('num_chairs'))
|
||||
|
||||
# How many chairs are needed for each company to seat all employees?
|
||||
>>> company = Company.objects.filter(
|
||||
|
@ -813,12 +813,12 @@ the same studio in the same genre and release year:
|
|||
|
||||
>>> from django.db.models import Avg, F, Window
|
||||
>>> Movie.objects.annotate(
|
||||
>>> avg_rating=Window(
|
||||
>>> expression=Avg('rating'),
|
||||
>>> partition_by=[F('studio'), F('genre')],
|
||||
>>> order_by='released__year',
|
||||
>>> ),
|
||||
>>> )
|
||||
... avg_rating=Window(
|
||||
... expression=Avg('rating'),
|
||||
... partition_by=[F('studio'), F('genre')],
|
||||
... order_by='released__year',
|
||||
... ),
|
||||
... )
|
||||
|
||||
This allows you to check if a movie is rated better or worse than its peers.
|
||||
|
||||
|
@ -833,20 +833,20 @@ to reduce repetition:
|
|||
|
||||
>>> from django.db.models import Avg, F, Max, Min, Window
|
||||
>>> window = {
|
||||
>>> 'partition_by': [F('studio'), F('genre')],
|
||||
>>> 'order_by': 'released__year',
|
||||
>>> }
|
||||
... 'partition_by': [F('studio'), F('genre')],
|
||||
... 'order_by': 'released__year',
|
||||
... }
|
||||
>>> Movie.objects.annotate(
|
||||
>>> avg_rating=Window(
|
||||
>>> expression=Avg('rating'), **window,
|
||||
>>> ),
|
||||
>>> best=Window(
|
||||
>>> expression=Max('rating'), **window,
|
||||
>>> ),
|
||||
>>> worst=Window(
|
||||
>>> expression=Min('rating'), **window,
|
||||
>>> ),
|
||||
>>> )
|
||||
... avg_rating=Window(
|
||||
... expression=Avg('rating'), **window,
|
||||
... ),
|
||||
... best=Window(
|
||||
... expression=Max('rating'), **window,
|
||||
... ),
|
||||
... worst=Window(
|
||||
... expression=Min('rating'), **window,
|
||||
... ),
|
||||
... )
|
||||
|
||||
Filtering against window functions is supported as long as lookups are not
|
||||
disjunctive (not using ``OR`` or ``XOR`` as a connector) and against a queryset
|
||||
|
@ -860,13 +860,13 @@ from groups to be included:
|
|||
.. code-block:: pycon
|
||||
|
||||
>>> qs = Movie.objects.annotate(
|
||||
>>> category_rank=Window(
|
||||
>>> Rank(), partition_by='category', order_by='-rating'
|
||||
>>> ),
|
||||
>>> scenes_count=Count('actors'),
|
||||
>>> ).filter(
|
||||
>>> Q(category_rank__lte=3) | Q(title__contains='Batman')
|
||||
>>> )
|
||||
... category_rank=Window(
|
||||
... Rank(), partition_by='category', order_by='-rating'
|
||||
... ),
|
||||
... scenes_count=Count('actors'),
|
||||
... ).filter(
|
||||
... Q(category_rank__lte=3) | Q(title__contains='Batman')
|
||||
... )
|
||||
>>> list(qs)
|
||||
NotImplementedError: Heterogeneous disjunctive predicates against window functions
|
||||
are not implemented when performing conditional aggregation.
|
||||
|
@ -945,13 +945,13 @@ with the average rating of a movie's two prior and two following peers:
|
|||
|
||||
>>> from django.db.models import Avg, F, RowRange, Window
|
||||
>>> Movie.objects.annotate(
|
||||
>>> avg_rating=Window(
|
||||
>>> expression=Avg('rating'),
|
||||
>>> partition_by=[F('studio'), F('genre')],
|
||||
>>> order_by='released__year',
|
||||
>>> frame=RowRange(start=-2, end=2),
|
||||
>>> ),
|
||||
>>> )
|
||||
... avg_rating=Window(
|
||||
... expression=Avg('rating'),
|
||||
... partition_by=[F('studio'), F('genre')],
|
||||
... order_by='released__year',
|
||||
... frame=RowRange(start=-2, end=2),
|
||||
... ),
|
||||
... )
|
||||
|
||||
If the database supports it, you can specify the start and end points based on
|
||||
values of an expression in the partition. If the ``released`` field of the
|
||||
|
@ -963,13 +963,13 @@ released between twelve months before and twelve months after the each movie:
|
|||
|
||||
>>> from django.db.models import Avg, F, ValueRange, Window
|
||||
>>> Movie.objects.annotate(
|
||||
>>> avg_rating=Window(
|
||||
>>> expression=Avg('rating'),
|
||||
>>> partition_by=[F('studio'), F('genre')],
|
||||
>>> order_by='released__year',
|
||||
>>> frame=ValueRange(start=-12, end=12),
|
||||
>>> ),
|
||||
>>> )
|
||||
... avg_rating=Window(
|
||||
... expression=Avg('rating'),
|
||||
... partition_by=[F('studio'), F('genre')],
|
||||
... order_by='released__year',
|
||||
... frame=ValueRange(start=-12, end=12),
|
||||
... ),
|
||||
... )
|
||||
|
||||
.. currentmodule:: django.db.models
|
||||
|
||||
|
|
|
@ -24,7 +24,8 @@ Related objects reference
|
|||
In the above example, the methods below will be available on
|
||||
the manager ``blog.entry_set``.
|
||||
|
||||
* Both sides of a :class:`~django.db.models.ManyToManyField` relation::
|
||||
* Both sides of a :class:`~django.db.models.ManyToManyField` relation
|
||||
::
|
||||
|
||||
class Topping(models.Model):
|
||||
# ...
|
||||
|
|
|
@ -499,7 +499,7 @@ Use of both ``and`` and ``or`` clauses within the same tag is allowed, with
|
|||
|
||||
will be interpreted like:
|
||||
|
||||
.. code-block:: python
|
||||
.. code-block:: pycon
|
||||
|
||||
if (athlete_list and coach_list) or cheerleader_list
|
||||
|
||||
|
@ -1118,14 +1118,16 @@ Example usage:
|
|||
|
||||
This example would return this HTML::
|
||||
|
||||
<h1>José Mourinho</h1>
|
||||
<p class="odd">Thibaut Courtois</p>
|
||||
<p class="even">John Terry</p>
|
||||
<p class="odd">Eden Hazard</p>
|
||||
.. code-block:: html
|
||||
|
||||
<h1>Carlo Ancelotti</h1>
|
||||
<p class="odd">Manuel Neuer</p>
|
||||
<p class="even">Thomas Müller</p>
|
||||
<h1>Gareth</h1>
|
||||
<p class="odd">Harry</p>
|
||||
<p class="even">John</p>
|
||||
<p class="odd">Nick</p>
|
||||
|
||||
<h1>John</h1>
|
||||
<p class="odd">Andrea</p>
|
||||
<p class="even">Melissa</p>
|
||||
|
||||
Notice how the first block ends with ``class="odd"`` and the new one starts
|
||||
with ``class="odd"``. Without the ``{% resetcycle %}`` tag, the second block
|
||||
|
@ -1264,6 +1266,8 @@ such as this:
|
|||
|
||||
...then, in a template, you can create a link to this view like this::
|
||||
|
||||
.. code-block:: html+django
|
||||
|
||||
{% url 'app-views-client' client.id %}
|
||||
|
||||
The template tag will output the string ``/clients/client/123/``.
|
||||
|
|
|
@ -539,14 +539,14 @@ https://web.archive.org/web/20110718035220/http://diveintomark.org/archives/2004
|
|||
|
||||
from django.utils.functional import keep_lazy, keep_lazy_text
|
||||
|
||||
def fancy_utility_function(s, ...):
|
||||
def fancy_utility_function(s, *args, **kwargs):
|
||||
# Do some conversion on string 's'
|
||||
...
|
||||
fancy_utility_function = keep_lazy(str)(fancy_utility_function)
|
||||
|
||||
# Or more succinctly:
|
||||
@keep_lazy(str)
|
||||
def fancy_utility_function(s, ...):
|
||||
def fancy_utility_function(s, *args, **kwargs):
|
||||
...
|
||||
|
||||
The ``keep_lazy()`` decorator takes a number of extra arguments (``*args``)
|
||||
|
@ -571,12 +571,12 @@ https://web.archive.org/web/20110718035220/http://diveintomark.org/archives/2004
|
|||
|
||||
# Our previous example was:
|
||||
@keep_lazy(str)
|
||||
def fancy_utility_function(s, ...):
|
||||
def fancy_utility_function(s, *args, **kwargs):
|
||||
...
|
||||
|
||||
# Which can be rewritten as:
|
||||
@keep_lazy_text
|
||||
def fancy_utility_function(s, ...):
|
||||
def fancy_utility_function(s, *args, **kwargs):
|
||||
...
|
||||
|
||||
``django.utils.html``
|
||||
|
|
|
@ -36,12 +36,16 @@ differences as a result of this change.
|
|||
However, **users on 64-bit platforms may experience some problems** using the
|
||||
``reset`` management command. Prior to this change, 64-bit platforms
|
||||
would generate a 64-bit, 16 character digest in the constraint name; for
|
||||
example::
|
||||
example:
|
||||
|
||||
.. code-block:: sql
|
||||
|
||||
ALTER TABLE myapp_sometable ADD CONSTRAINT object_id_refs_id_5e8f10c132091d1e FOREIGN KEY ...
|
||||
|
||||
Following this change, all platforms, regardless of word size, will generate a
|
||||
32-bit, 8 character digest in the constraint name; for example::
|
||||
32-bit, 8 character digest in the constraint name; for example:
|
||||
|
||||
.. code-block:: sql
|
||||
|
||||
ALTER TABLE myapp_sometable ADD CONSTRAINT object_id_refs_id_32091d1e FOREIGN KEY ...
|
||||
|
||||
|
|
|
@ -545,14 +545,18 @@ Database backend API
|
|||
``select_related()`` prohibits non-relational fields for nested relations
|
||||
-------------------------------------------------------------------------
|
||||
|
||||
Django 1.8 added validation for non-relational fields in ``select_related()``::
|
||||
Django 1.8 added validation for non-relational fields in ``select_related()``:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Book.objects.select_related('title')
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
FieldError: Non-relational field given in select_related: 'title'
|
||||
|
||||
But it didn't prohibit nested non-relation fields as it does now::
|
||||
But it didn't prohibit nested non-relation fields as it does now:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Book.objects.select_related('author__name')
|
||||
Traceback (most recent call last):
|
||||
|
@ -620,6 +624,8 @@ disable Django's logging configuration or override it with your own, you'll
|
|||
need to add the appropriate logging configuration if you want to see that
|
||||
output::
|
||||
|
||||
LOGGING = {
|
||||
# ...
|
||||
'formatters': {
|
||||
'django.server': {
|
||||
'()': 'django.utils.log.ServerFormatter',
|
||||
|
@ -639,7 +645,8 @@ output::
|
|||
'level': 'INFO',
|
||||
'propagate': False,
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
``auth.CustomUser`` and ``auth.ExtensionUser`` test models were removed
|
||||
-----------------------------------------------------------------------
|
||||
|
@ -725,7 +732,7 @@ custom lookup for it. For example::
|
|||
class MyFieldExact(Exact):
|
||||
def get_prep_lookup(self):
|
||||
# do_custom_stuff_for_myfield
|
||||
....
|
||||
...
|
||||
|
||||
MyField.register_lookup(MyFieldExact)
|
||||
|
||||
|
@ -931,13 +938,17 @@ Features deprecated in 1.10
|
|||
Direct assignment to a reverse foreign key or many-to-many relation
|
||||
-------------------------------------------------------------------
|
||||
|
||||
Instead of assigning related objects using direct assignment::
|
||||
Instead of assigning related objects using direct assignment:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> new_list = [obj1, obj2, obj3]
|
||||
>>> e.related_set = new_list
|
||||
|
||||
Use the :meth:`~django.db.models.fields.related.RelatedManager.set` method
|
||||
added in Django 1.9::
|
||||
added in Django 1.9:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> e.related_set.set([obj1, obj2, obj3])
|
||||
|
||||
|
@ -1022,12 +1033,16 @@ Assume the following models::
|
|||
In older versions, :attr:`~django.db.models.Options.default_related_name`
|
||||
couldn't be used as a query lookup. This is fixed and support for the old
|
||||
lookup name is deprecated. For example, since ``default_related_name`` is set
|
||||
in model ``Bar``, instead of using the model name ``bar`` as the lookup::
|
||||
in model ``Bar``, instead of using the model name ``bar`` as the lookup:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> bar = Bar.objects.get(pk=1)
|
||||
>>> Foo.objects.get(bar=bar)
|
||||
|
||||
use the default_related_name ``bars``::
|
||||
use the default_related_name ``bars``:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Foo.objects.get(bars=bar)
|
||||
|
||||
|
|
|
@ -453,42 +453,42 @@ several functions to support conversion of Python values into
|
|||
database-compatible values. A custom field might look something like::
|
||||
|
||||
class CustomModelField(models.Field):
|
||||
# ...
|
||||
...
|
||||
def db_type(self):
|
||||
# ...
|
||||
...
|
||||
|
||||
def get_db_prep_save(self, value):
|
||||
# ...
|
||||
...
|
||||
|
||||
def get_db_prep_value(self, value):
|
||||
# ...
|
||||
...
|
||||
|
||||
def get_db_prep_lookup(self, lookup_type, value):
|
||||
# ...
|
||||
...
|
||||
|
||||
In 1.2, these three methods have undergone a change in prototype, and
|
||||
two extra methods have been introduced::
|
||||
|
||||
class CustomModelField(models.Field):
|
||||
# ...
|
||||
...
|
||||
|
||||
def db_type(self, connection):
|
||||
# ...
|
||||
...
|
||||
|
||||
def get_prep_value(self, value):
|
||||
# ...
|
||||
...
|
||||
|
||||
def get_prep_lookup(self, lookup_type, value):
|
||||
# ...
|
||||
...
|
||||
|
||||
def get_db_prep_save(self, value, connection):
|
||||
# ...
|
||||
...
|
||||
|
||||
def get_db_prep_value(self, value, connection, prepared=False):
|
||||
# ...
|
||||
...
|
||||
|
||||
def get_db_prep_lookup(self, lookup_type, value, connection, prepared=False):
|
||||
# ...
|
||||
...
|
||||
|
||||
These changes are required to support multiple databases --
|
||||
``db_type`` and ``get_db_prep_*`` can no longer make any assumptions
|
||||
|
@ -537,21 +537,29 @@ You may also need to update your templates if you were relying on the
|
|||
implementation of Django's template tags *not* being thread safe. The
|
||||
:ttag:`cycle` tag is the most likely to be affected in this way,
|
||||
especially when used in conjunction with the :ttag:`include` tag.
|
||||
Consider the following template fragment::
|
||||
Consider the following template fragment:
|
||||
|
||||
.. code-block:: html+django
|
||||
|
||||
{% for object in object_list %}
|
||||
{% include "subtemplate.html" %}
|
||||
{% endfor %}
|
||||
|
||||
with a ``subtemplate.html`` that reads::
|
||||
with a ``subtemplate.html`` that reads:
|
||||
|
||||
.. code-block:: html+django
|
||||
|
||||
{% cycle 'even' 'odd' %}
|
||||
|
||||
Using the non-thread-safe, pre-Django 1.2 renderer, this would output::
|
||||
Using the non-thread-safe, pre-Django 1.2 renderer, this would output:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
even odd even odd ...
|
||||
|
||||
Using the thread-safe Django 1.2 renderer, you will instead get::
|
||||
Using the thread-safe Django 1.2 renderer, you will instead get:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
even even even even ...
|
||||
|
||||
|
@ -1133,14 +1141,18 @@ is using a supported spatial database backend.
|
|||
differs across spatial databases, the ``SpatialRefSys`` and
|
||||
``GeometryColumns`` models can no longer be associated with
|
||||
the ``gis`` application name. Thus, no models will be returned
|
||||
when using the ``get_models`` method in the following example::
|
||||
when using the ``get_models`` method in the following example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.db.models import get_app, get_models
|
||||
>>> get_models(get_app('gis'))
|
||||
[]
|
||||
|
||||
To get the correct ``SpatialRefSys`` and ``GeometryColumns``
|
||||
for your spatial database use the methods provided by the spatial backend::
|
||||
for your spatial database use the methods provided by the spatial backend:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> from django.db import connections
|
||||
>>> SpatialRefSys = connections['my_spatialite'].ops.spatial_ref_sys()
|
||||
|
|
|
@ -20,7 +20,9 @@ as was reported to us recently. The Host header parsing in Django 1.3.3 and
|
|||
Django 1.4.1 -- specifically, ``django.http.HttpRequest.get_host()`` -- was
|
||||
incorrectly handling username/password information in the header. Thus, for
|
||||
example, the following Host header would be accepted by Django when running on
|
||||
``validsite.com``::
|
||||
``validsite.com``:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
Host: validsite.com:random@evilsite.com
|
||||
|
||||
|
|
|
@ -141,7 +141,7 @@ Users of Python 2.5 and above may now use transaction management functions as
|
|||
context managers. For example::
|
||||
|
||||
with transaction.autocommit():
|
||||
# ...
|
||||
...
|
||||
|
||||
Configurable delete-cascade
|
||||
---------------------------
|
||||
|
@ -419,7 +419,9 @@ If you have an existing project that is using the database session
|
|||
backend, you don't have to do anything to accommodate this change.
|
||||
However, you may get a significant performance boost if you manually
|
||||
add the new index to the session table. The SQL that will add the
|
||||
index can be found by running the ``sqlindexes`` admin command::
|
||||
index can be found by running the ``sqlindexes`` admin command:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
python manage.py sqlindexes sessions
|
||||
|
||||
|
@ -476,14 +478,18 @@ passed empty dictionary. This was inconsistent with behavior in other parts of
|
|||
the framework. Starting with 1.3 if you pass in empty dictionary the
|
||||
``FormSet`` will raise a ``ValidationError``.
|
||||
|
||||
For example with a ``FormSet``::
|
||||
For example with a ``FormSet``:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> class ArticleForm(Form):
|
||||
... title = CharField()
|
||||
... pub_date = DateField()
|
||||
>>> ArticleFormSet = formset_factory(ArticleForm)
|
||||
|
||||
the following code will raise a ``ValidationError``::
|
||||
the following code will raise a ``ValidationError``:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> ArticleFormSet({})
|
||||
Traceback (most recent call last):
|
||||
|
@ -491,7 +497,9 @@ the following code will raise a ``ValidationError``::
|
|||
ValidationError: [u'ManagementForm data is missing or has been tampered with']
|
||||
|
||||
if you need to instantiate an empty ``FormSet``, don't pass in the data or use
|
||||
``None``::
|
||||
``None``:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> formset = ArticleFormSet()
|
||||
>>> formset = ArticleFormSet(data=None)
|
||||
|
@ -502,7 +510,9 @@ Callables in templates
|
|||
Previously, a callable in a template would only be called automatically as part
|
||||
of the variable resolution process if it was retrieved via attribute
|
||||
lookup. This was an inconsistency that could result in confusing and unhelpful
|
||||
behavior::
|
||||
behavior:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Template("{{ user.get_full_name }}").render(Context({'user': user}))
|
||||
u'Joe Bloggs'
|
||||
|
@ -720,12 +730,16 @@ Changes to ``url`` and ``ssi``
|
|||
------------------------------
|
||||
|
||||
Most template tags will allow you to pass in either constants or
|
||||
variables as arguments -- for example::
|
||||
variables as arguments -- for example:
|
||||
|
||||
.. code-block:: html+django
|
||||
|
||||
{% extends "base.html" %}
|
||||
|
||||
allows you to specify a base template as a constant, but if you have a
|
||||
context variable ``templ`` that contains the value ``base.html``::
|
||||
context variable ``templ`` that contains the value ``base.html``:
|
||||
|
||||
.. code-block:: html+django
|
||||
|
||||
{% extends templ %}
|
||||
|
||||
|
@ -741,11 +755,15 @@ accident. Django 1.3 adds a new template library -- ``future`` -- that
|
|||
provides alternate implementations of the ``url`` and ``ssi``
|
||||
template tags. This ``future`` library implement behavior that makes
|
||||
the handling of the first argument consistent with the handling of all
|
||||
other variables. So, an existing template that contains::
|
||||
other variables. So, an existing template that contains:
|
||||
|
||||
.. code-block:: html+django
|
||||
|
||||
{% url sample %}
|
||||
|
||||
should be replaced with::
|
||||
should be replaced with:
|
||||
|
||||
.. code-block:: html+django
|
||||
|
||||
{% load url from future %}
|
||||
{% url 'sample' %}
|
||||
|
@ -840,7 +858,9 @@ Rationale for this decision:
|
|||
generate spurious error messages when the project directory is added
|
||||
to the Python path (``manage.py runserver`` does this) and then it
|
||||
clashes with the equally named standard library module, this is a
|
||||
typical warning message::
|
||||
typical warning message:
|
||||
|
||||
.. code-block:: pytb
|
||||
|
||||
/usr/lib/python2.6/gettext.py:49: ImportWarning: Not importing directory '/path/to/project/locale': missing __init__.py.
|
||||
import locale, copy, os, re, struct, sys
|
||||
|
|
|
@ -20,7 +20,9 @@ as was reported to us recently. The Host header parsing in Django 1.3.3 and
|
|||
Django 1.4.1 -- specifically, ``django.http.HttpRequest.get_host()`` -- was
|
||||
incorrectly handling username/password information in the header. Thus, for
|
||||
example, the following Host header would be accepted by Django when running on
|
||||
``validsite.com``::
|
||||
``validsite.com``:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
Host: validsite.com:random@evilsite.com
|
||||
|
||||
|
|
|
@ -152,7 +152,9 @@ using the project name prefix (e.g. ``myproject.settings``, ``ROOT_URLCONF =
|
|||
directory up, so it is outside the project package rather than adjacent to
|
||||
``settings.py`` and ``urls.py``.
|
||||
|
||||
For instance, with the following layout::
|
||||
For instance, with the following layout:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
manage.py
|
||||
mysite/
|
||||
|
@ -168,7 +170,9 @@ but not ``settings``, ``urls``, or ``myapp`` as top-level modules.
|
|||
|
||||
Anything imported as a top-level module can be placed adjacent to the new
|
||||
``manage.py``. For instance, to decouple ``myapp`` from the project module and
|
||||
import it as just ``myapp``, place it outside the ``mysite/`` directory::
|
||||
import it as just ``myapp``, place it outside the ``mysite/`` directory:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
manage.py
|
||||
myapp/
|
||||
|
@ -191,12 +195,16 @@ now have a ``--template`` option for specifying a path or URL to a custom app
|
|||
or project template.
|
||||
|
||||
For example, Django will use the ``/path/to/my_project_template`` directory
|
||||
when you run the following command::
|
||||
when you run the following command:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
django-admin.py startproject --template=/path/to/my_project_template myproject
|
||||
|
||||
You can also now provide a destination directory as the second
|
||||
argument to both :djadmin:`startapp` and :djadmin:`startproject`::
|
||||
argument to both :djadmin:`startapp` and :djadmin:`startproject`:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
django-admin.py startapp myapp /path/to/new/app
|
||||
django-admin.py startproject myproject /path/to/new/project
|
||||
|
@ -1136,7 +1144,9 @@ Development Server Multithreading
|
|||
|
||||
The development server is now is multithreaded by default. Use the
|
||||
:option:`runserver --nothreading` option to disable the use of threading in the
|
||||
development server::
|
||||
development server:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
django-admin.py runserver --nothreading
|
||||
|
||||
|
@ -1199,18 +1209,21 @@ To increase the flexibility of error logging for requests, the
|
|||
separate filter attached to :class:`django.utils.log.AdminEmailHandler` to
|
||||
prevent admin error emails in ``DEBUG`` mode::
|
||||
|
||||
'filters': {
|
||||
'require_debug_false': {
|
||||
'()': 'django.utils.log.RequireDebugFalse'
|
||||
}
|
||||
},
|
||||
'handlers': {
|
||||
'mail_admins': {
|
||||
'level': 'ERROR',
|
||||
'filters': ['require_debug_false'],
|
||||
'class': 'django.utils.log.AdminEmailHandler'
|
||||
}
|
||||
},
|
||||
LOGGING = {
|
||||
# ...
|
||||
'filters': {
|
||||
'require_debug_false': {
|
||||
'()': 'django.utils.log.RequireDebugFalse',
|
||||
}
|
||||
},
|
||||
'handlers': {
|
||||
'mail_admins': {
|
||||
'level': 'ERROR',
|
||||
'filters': ['require_debug_false'],
|
||||
'class': 'django.utils.log.AdminEmailHandler'
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
If your project was created prior to this change, your :setting:`LOGGING`
|
||||
setting will not include this new filter. In order to maintain
|
||||
|
|
|
@ -155,7 +155,9 @@ Caching of related model instances
|
|||
----------------------------------
|
||||
|
||||
When traversing relations, the ORM will avoid re-fetching objects that were
|
||||
previously loaded. For example, with the tutorial's models::
|
||||
previously loaded. For example, with the tutorial's models:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> first_poll = Poll.objects.all()[0]
|
||||
>>> first_choice = first_poll.choice_set.all()[0]
|
||||
|
@ -403,7 +405,9 @@ Context in year and month archive class-based views
|
|||
provide a ``date_list`` sorted in ascending order in the context, like their
|
||||
function-based predecessors, but it actually was in descending order. In 1.5,
|
||||
the documented order was restored. You may want to add (or remove) the
|
||||
``reversed`` keyword when you're iterating on ``date_list`` in a template::
|
||||
``reversed`` keyword when you're iterating on ``date_list`` in a template:
|
||||
|
||||
.. code-block:: html+django
|
||||
|
||||
{% for date in date_list reversed %}
|
||||
|
||||
|
|
|
@ -463,11 +463,14 @@ explicitly import the User model in your test module::
|
|||
@override_settings(AUTH_USER_MODEL='auth.CustomUser')
|
||||
class CustomUserFeatureTests(TestCase):
|
||||
def test_something(self):
|
||||
# Test code here ...
|
||||
# Test code here
|
||||
...
|
||||
|
||||
This import forces the custom user model to be registered. Without this import,
|
||||
the test will be unable to swap in the custom user model, and you will get an
|
||||
error reporting::
|
||||
error reporting:
|
||||
|
||||
.. code-block:: pytb
|
||||
|
||||
ImproperlyConfigured: AUTH_USER_MODEL refers to model 'auth.CustomUser' that has not been installed
|
||||
|
||||
|
@ -1010,11 +1013,15 @@ Django 1.6 starts a process to correct this inconsistency. The ``future``
|
|||
template library provides alternate implementations of :ttag:`cycle` and
|
||||
:ttag:`firstof` that autoescape their inputs. If you're using these tags,
|
||||
you're encouraged to include the following line at the top of your templates to
|
||||
enable the new behavior::
|
||||
enable the new behavior:
|
||||
|
||||
.. code-block:: html+django
|
||||
|
||||
{% load cycle from future %}
|
||||
|
||||
or::
|
||||
or:
|
||||
|
||||
.. code-block:: html+django
|
||||
|
||||
{% load firstof from future %}
|
||||
|
||||
|
|
|
@ -1009,7 +1009,9 @@ Standalone scripts
|
|||
If you're using Django in a plain Python script — rather than a management
|
||||
command — and you rely on the :envvar:`DJANGO_SETTINGS_MODULE` environment
|
||||
variable, you must now explicitly initialize Django at the beginning of your
|
||||
script with::
|
||||
script with:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> import django
|
||||
>>> django.setup()
|
||||
|
@ -1134,13 +1136,13 @@ method::
|
|||
|
||||
# Old pattern:
|
||||
try:
|
||||
# ...
|
||||
...
|
||||
except ValidationError as e:
|
||||
self._errors = e.update_error_dict(self._errors)
|
||||
|
||||
# New pattern:
|
||||
try:
|
||||
# ...
|
||||
...
|
||||
except ValidationError as e:
|
||||
self.add_error(None, e)
|
||||
|
||||
|
@ -1150,7 +1152,7 @@ wasn't available before Django 1.7, but you can use the following
|
|||
workaround to convert any ``list`` into ``ErrorList``::
|
||||
|
||||
try:
|
||||
# ...
|
||||
...
|
||||
except ValidationError as e:
|
||||
self._errors = e.update_error_dict(self._errors)
|
||||
|
||||
|
@ -1195,8 +1197,8 @@ manager will *not* be reset. This was necessary to resolve an inconsistency in
|
|||
the way routing information cascaded over joins. See :ticket:`13724` for more
|
||||
details.
|
||||
|
||||
pytz may be required
|
||||
--------------------
|
||||
``pytz`` may be required
|
||||
------------------------
|
||||
|
||||
If your project handles datetimes before 1970 or after 2037 and Django raises
|
||||
a :exc:`ValueError` when encountering them, you will have to install pytz_. You
|
||||
|
|
|
@ -696,7 +696,9 @@ Assigning unsaved objects to relations raises an error
|
|||
.. note::
|
||||
|
||||
To more easily allow in-memory usage of models, this change was reverted in
|
||||
Django 1.8.4 and replaced with a check during ``model.save()``. For example::
|
||||
Django 1.8.4 and replaced with a check during ``model.save()``. For example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> book = Book.objects.create(name="Django")
|
||||
>>> book.author = Author(name="John")
|
||||
|
@ -713,7 +715,9 @@ Assigning unsaved objects to a :class:`~django.db.models.ForeignKey`,
|
|||
:class:`~django.db.models.OneToOneField` now raises a :exc:`ValueError`.
|
||||
|
||||
Previously, the assignment of an unsaved object would be silently ignored.
|
||||
For example::
|
||||
For example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> book = Book.objects.create(name="Django")
|
||||
>>> book.author = Author(name="John")
|
||||
|
@ -724,7 +728,9 @@ For example::
|
|||
>>> book.author
|
||||
>>>
|
||||
|
||||
Now, an error will be raised to prevent data loss::
|
||||
Now, an error will be raised to prevent data loss:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> book.author = Author(name="john")
|
||||
Traceback (most recent call last):
|
||||
|
@ -790,7 +796,9 @@ Querying for model lookups now checks if the object passed is of correct type
|
|||
and raises a :exc:`ValueError` if not. Previously, Django didn't care if the
|
||||
object was of correct type; it just used the object's related field attribute
|
||||
(e.g. ``id``) for the lookup. Now, an error is raised to prevent incorrect
|
||||
lookups::
|
||||
lookups:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> book = Book.objects.create(name="Django")
|
||||
>>> book = Book.objects.filter(author=book)
|
||||
|
@ -802,14 +810,18 @@ lookups::
|
|||
--------------------------------------------
|
||||
|
||||
``select_related()`` now validates that the given fields actually exist.
|
||||
Previously, nonexistent fields were silently ignored. Now, an error is raised::
|
||||
Previously, nonexistent fields were silently ignored. Now, an error is raised:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> book = Book.objects.select_related('nonexistent_field')
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
FieldError: Invalid field name(s) given in select_related: 'nonexistent_field'
|
||||
|
||||
The validation also makes sure that the given field is relational::
|
||||
The validation also makes sure that the given field is relational:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> book = Book.objects.select_related('name')
|
||||
Traceback (most recent call last):
|
||||
|
@ -966,7 +978,9 @@ returns the relationship as ``django.db.models.fields.related.ManyToOneRel``
|
|||
is set to the target of the relationship instead of the source. The source
|
||||
model is accessible on the ``related_model`` attribute instead.
|
||||
|
||||
Consider this example from the tutorial in Django 1.8::
|
||||
Consider this example from the tutorial in Django 1.8:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> p = Poll.objects.get(pk=1)
|
||||
>>> p._meta.get_all_related_objects()
|
||||
|
@ -976,7 +990,9 @@ Consider this example from the tutorial in Django 1.8::
|
|||
>>> p._meta.get_all_related_objects()[0].related_model
|
||||
<class 'polls.models.Choice'>
|
||||
|
||||
and compare it to the behavior on older versions::
|
||||
and compare it to the behavior on older versions:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> p._meta.get_all_related_objects()
|
||||
[<RelatedObject: polls:choice related to poll>]
|
||||
|
|
|
@ -1018,7 +1018,9 @@ to 2.1.4. jQuery 2.x has the same API as jQuery 1.x, but does not support
|
|||
Internet Explorer 6, 7, or 8, allowing for better performance and a smaller
|
||||
file size. If you need to support IE8 and must also use the latest version of
|
||||
Django, you can override the admin's copy of jQuery with your own by creating
|
||||
a Django application with this structure::
|
||||
a Django application with this structure:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
app/static/admin/js/vendor/
|
||||
jquery.js
|
||||
|
@ -1029,7 +1031,9 @@ a Django application with this structure::
|
|||
``SyntaxError`` when installing Django setuptools 5.5.x
|
||||
-------------------------------------------------------
|
||||
|
||||
When installing Django 1.9 or 1.9.1 with setuptools 5.5.x, you'll see::
|
||||
When installing Django 1.9 or 1.9.1 with setuptools 5.5.x, you'll see:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
Compiling django/conf/app_template/apps.py ...
|
||||
File "django/conf/app_template/apps.py", line 4
|
||||
|
@ -1313,7 +1317,9 @@ the included URLconf sets an application namespace.
|
|||
``current_app`` parameter to ``contrib.auth`` views
|
||||
---------------------------------------------------
|
||||
|
||||
All views in ``django.contrib.auth.views`` have the following structure::
|
||||
All views in ``django.contrib.auth.views`` have the following structure:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
def view(request, ..., current_app=None, ...):
|
||||
|
||||
|
|
|
@ -454,7 +454,9 @@ If you wish to keep this restriction in the admin when editing users, set
|
|||
|
||||
Calling ``QuerySet.reverse()`` or ``last()`` on a sliced queryset leads to
|
||||
unexpected results due to the slice being applied after reordering. This is
|
||||
now prohibited, e.g.::
|
||||
now prohibited, e.g.:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Model.objects.all()[:2].reverse()
|
||||
Traceback (most recent call last):
|
||||
|
|
|
@ -392,7 +392,9 @@ existing row will result in an ``IntegrityError``.
|
|||
|
||||
In order to update an existing model for a specific primary key value, use the
|
||||
:meth:`~django.db.models.query.QuerySet.update_or_create` method or
|
||||
``QuerySet.filter(pk=…).update(…)`` instead. For example::
|
||||
``QuerySet.filter(pk=…).update(…)`` instead. For example:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> MyModel.objects.update_or_create(pk=existing_pk, defaults={'name': 'new name'})
|
||||
>>> MyModel.objects.filter(pk=existing_pk).update(name='new name')
|
||||
|
|
|
@ -705,8 +705,8 @@ Miscellaneous
|
|||
``SimpleTestCase.assertFormError()`` and ``assertFormsetError()`` is
|
||||
deprecated. Use::
|
||||
|
||||
assertFormError(response.context['form_name'], …)
|
||||
assertFormsetError(response.context['formset_name'], …)
|
||||
assertFormError(response.context['form_name'], ...)
|
||||
assertFormsetError(response.context['formset_name'], ...)
|
||||
|
||||
or pass the form/formset object directly instead.
|
||||
|
||||
|
|
|
@ -91,11 +91,11 @@ Detailed notes can be found in :ref:`async-queries`, but in short:
|
|||
|
||||
Django also supports some asynchronous model methods that use the database::
|
||||
|
||||
async def make_book(...):
|
||||
async def make_book(*args, **kwargs):
|
||||
book = Book(...)
|
||||
await book.asave(using="secondary")
|
||||
|
||||
async def make_book_with_tags(tags, ...):
|
||||
async def make_book_with_tags(tags, *args, **kwargs):
|
||||
book = await Book.objects.acreate(...)
|
||||
await book.tags.aset(tags)
|
||||
|
||||
|
@ -227,13 +227,13 @@ as either a direct wrapper or a decorator::
|
|||
|
||||
from asgiref.sync import async_to_sync
|
||||
|
||||
async def get_data(...):
|
||||
async def get_data():
|
||||
...
|
||||
|
||||
sync_get_data = async_to_sync(get_data)
|
||||
|
||||
@async_to_sync
|
||||
async def get_other_data(...):
|
||||
async def get_other_data():
|
||||
...
|
||||
|
||||
The async function is run in the event loop for the current thread, if one is
|
||||
|
@ -264,7 +264,7 @@ as either a direct wrapper or a decorator::
|
|||
async_function = sync_to_async(sensitive_sync_function, thread_sensitive=True)
|
||||
|
||||
@sync_to_async
|
||||
def sync_function(...):
|
||||
def sync_function():
|
||||
...
|
||||
|
||||
Threadlocals and contextvars values are preserved across the boundary in both
|
||||
|
|
|
@ -134,8 +134,10 @@ Authenticating users
|
|||
user = authenticate(username='john', password='secret')
|
||||
if user is not None:
|
||||
# A backend authenticated the credentials
|
||||
...
|
||||
else:
|
||||
# No backend authenticated the credentials
|
||||
...
|
||||
|
||||
``request`` is an optional :class:`~django.http.HttpRequest` which is
|
||||
passed on the ``authenticate()`` method of the authentication backends.
|
||||
|
@ -950,7 +952,9 @@ in your own URLconf, for example::
|
|||
path('accounts/', include('django.contrib.auth.urls')),
|
||||
]
|
||||
|
||||
This will include the following URL patterns::
|
||||
This will include the following URL patterns:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
accounts/login/ [name='login']
|
||||
accounts/logout/ [name='logout']
|
||||
|
|
|
@ -24,7 +24,9 @@ How Django stores passwords
|
|||
Django provides a flexible password storage system and uses PBKDF2 by default.
|
||||
|
||||
The :attr:`~django.contrib.auth.models.User.password` attribute of a
|
||||
:class:`~django.contrib.auth.models.User` object is a string in this format::
|
||||
:class:`~django.contrib.auth.models.User` object is a string in this format:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
<algorithm>$<iterations>$<salt>$<hash>
|
||||
|
||||
|
@ -215,7 +217,8 @@ parameter (use the ``rounds`` parameter when subclassing a bcrypt hasher). For
|
|||
example, to increase the number of iterations used by the default PBKDF2
|
||||
algorithm:
|
||||
|
||||
#. Create a subclass of ``django.contrib.auth.hashers.PBKDF2PasswordHasher``::
|
||||
#. Create a subclass of ``django.contrib.auth.hashers.PBKDF2PasswordHasher``
|
||||
::
|
||||
|
||||
from django.contrib.auth.hashers import PBKDF2PasswordHasher
|
||||
|
||||
|
|
|
@ -18,7 +18,9 @@ That's where caching comes in.
|
|||
|
||||
To cache something is to save the result of an expensive calculation so that
|
||||
you don't have to perform the calculation next time. Here's some pseudocode
|
||||
explaining how this would work for a dynamically generated web page::
|
||||
explaining how this would work for a dynamically generated web page:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
given a URL, try finding that page in the cache
|
||||
if the page is in the cache:
|
||||
|
|
|
@ -150,7 +150,7 @@ this would lead to incorrect behavior.
|
|||
@etag(etag_func)
|
||||
@last_modified(last_modified_func)
|
||||
def my_view(request):
|
||||
# ...
|
||||
...
|
||||
|
||||
# End of bad code.
|
||||
|
||||
|
|
|
@ -74,9 +74,9 @@ p2 doesn't have an associated restaurant:
|
|||
|
||||
>>> from django.core.exceptions import ObjectDoesNotExist
|
||||
>>> try:
|
||||
>>> p2.restaurant
|
||||
>>> except ObjectDoesNotExist:
|
||||
>>> print("There is no restaurant here.")
|
||||
... p2.restaurant
|
||||
... except ObjectDoesNotExist:
|
||||
... print("There is no restaurant here.")
|
||||
There is no restaurant here.
|
||||
|
||||
You can also use ``hasattr`` to avoid the need for exception catching:
|
||||
|
|
|
@ -675,7 +675,9 @@ Field name restrictions
|
|||
Django places some restrictions on model field names:
|
||||
|
||||
#. A field name cannot be a Python reserved word, because that would result
|
||||
in a Python syntax error. For example::
|
||||
in a Python syntax error. For example:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
class Example(models.Model):
|
||||
pass = models.IntegerField() # 'pass' is a reserved word!
|
||||
|
@ -1221,7 +1223,9 @@ subclass with a :class:`~django.db.models.ManyToManyField`::
|
|||
class Supplier(Place):
|
||||
customers = models.ManyToManyField(Place)
|
||||
|
||||
This results in the error::
|
||||
This results in the error:
|
||||
|
||||
.. code-block:: pytb
|
||||
|
||||
Reverse query name for 'Supplier.customers' clashes with reverse query
|
||||
name for 'Supplier.place_ptr'.
|
||||
|
|
|
@ -1067,7 +1067,7 @@ query for SQL ``NULL``, use :lookup:`isnull`:
|
|||
<Dog: Archie>
|
||||
>>> Dog.objects.filter(data=None)
|
||||
<QuerySet [<Dog: Archie>]>
|
||||
>>> Dog.objects.filter(data=Value(None, JSONField())
|
||||
>>> Dog.objects.filter(data=Value(None, JSONField()))
|
||||
<QuerySet [<Dog: Archie>]>
|
||||
>>> Dog.objects.filter(data__isnull=True)
|
||||
<QuerySet [<Dog: Max>]>
|
||||
|
@ -1356,7 +1356,9 @@ For example, this statement yields a single ``Q`` object that represents the
|
|||
|
||||
Q(question__startswith='Who') | Q(question__startswith='What')
|
||||
|
||||
This is equivalent to the following SQL ``WHERE`` clause::
|
||||
This is equivalent to the following SQL ``WHERE`` clause:
|
||||
|
||||
.. code-block: sql
|
||||
|
||||
WHERE question LIKE 'Who%' OR question LIKE 'What%'
|
||||
|
||||
|
|
|
@ -309,7 +309,8 @@ alias::
|
|||
|
||||
from django.db import connections
|
||||
with connections['my_db_alias'].cursor() as cursor:
|
||||
# Your code here...
|
||||
# Your code here
|
||||
...
|
||||
|
||||
By default, the Python DB API will return results without their field names,
|
||||
which means you end up with a ``list`` of values, rather than a ``dict``. At a
|
||||
|
|
|
@ -111,7 +111,7 @@ requirements::
|
|||
css = {
|
||||
'screen': ['pretty.css'],
|
||||
'tv,projector': ['lo_res.css'],
|
||||
'print': ['newspaper.css],
|
||||
'print': ['newspaper.css'],
|
||||
}
|
||||
|
||||
If this last CSS definition were to be rendered, it would become the following HTML:
|
||||
|
@ -280,7 +280,7 @@ outputting the complete HTML ``<script>`` or ``<link>`` tag content:
|
|||
>>> from django.utils.html import html_safe
|
||||
>>>
|
||||
>>> @html_safe
|
||||
>>> class JSPath:
|
||||
... class JSPath:
|
||||
... def __str__(self):
|
||||
... return '<script src="https://example.org/asset.js" rel="stylesheet">'
|
||||
|
||||
|
|
|
@ -778,7 +778,9 @@ keyword arguments, or the corresponding attributes on the ``ModelForm`` inner
|
|||
``Meta`` class. Please see the ``ModelForm`` :ref:`modelforms-selecting-fields`
|
||||
documentation.
|
||||
|
||||
... or enable localization for specific fields::
|
||||
... or enable localization for specific fields:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> Form = modelform_factory(Author, form=AuthorForm, localized_fields=["birth_date"])
|
||||
|
||||
|
|
|
@ -127,13 +127,15 @@ You can use the :func:`redirect` function in a number of ways.
|
|||
...
|
||||
return redirect('some-view-name', foo='bar')
|
||||
|
||||
#. By passing a hardcoded URL to redirect to::
|
||||
#. By passing a hardcoded URL to redirect to:
|
||||
::
|
||||
|
||||
def my_view(request):
|
||||
...
|
||||
return redirect('/some/url/')
|
||||
|
||||
This also works with full URLs::
|
||||
This also works with full URLs:
|
||||
::
|
||||
|
||||
def my_view(request):
|
||||
...
|
||||
|
|
|
@ -865,7 +865,9 @@ Secondly, you can include an object that contains embedded namespace data. If
|
|||
you ``include()`` a list of :func:`~django.urls.path` or
|
||||
:func:`~django.urls.re_path` instances, the URLs contained in that object
|
||||
will be added to the global namespace. However, you can also ``include()`` a
|
||||
2-tuple containing::
|
||||
2-tuple containing:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
(<list of path()/re_path() instances>, <application namespace>)
|
||||
|
||||
|
|
|
@ -262,7 +262,9 @@ In a case like this, consider something like the following::
|
|||
}
|
||||
|
||||
You would get an error when running :djadmin:`django-admin
|
||||
compilemessages <compilemessages>`::
|
||||
compilemessages <compilemessages>`:
|
||||
|
||||
.. code-block: pytb
|
||||
|
||||
a format specification for argument 'name', as in 'msgstr[0]', doesn't exist in 'msgid'
|
||||
|
||||
|
@ -1094,7 +1096,9 @@ interface within your Python code::
|
|||
~~~~~~~~~~~~
|
||||
|
||||
The ``ngettext`` function provides an interface to pluralize words and
|
||||
phrases::
|
||||
phrases:
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
const objectCount = 1 // or 0, or 2, or 3, ...
|
||||
const string = ngettext(
|
||||
|
@ -1113,7 +1117,9 @@ function supports both positional and named interpolation:
|
|||
* Positional interpolation: ``obj`` contains a JavaScript Array object
|
||||
whose elements values are then sequentially interpolated in their
|
||||
corresponding ``fmt`` placeholders in the same order they appear.
|
||||
For example::
|
||||
For example:
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
const formats = ngettext(
|
||||
'There is %s object. Remaining: %s',
|
||||
|
@ -1125,7 +1131,9 @@ function supports both positional and named interpolation:
|
|||
|
||||
* Named interpolation: This mode is selected by passing the optional
|
||||
boolean ``named`` parameter as ``true``. ``obj`` contains a JavaScript
|
||||
object or associative array. For example::
|
||||
object or associative array. For example:
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
const data = {
|
||||
count: 10,
|
||||
|
@ -1149,7 +1157,9 @@ to produce proper pluralizations).
|
|||
~~~~~~~~~~~~~~
|
||||
|
||||
The ``get_format`` function has access to the configured i18n formatting
|
||||
settings and can retrieve the format string for a given setting name::
|
||||
settings and can retrieve the format string for a given setting name:
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
document.write(get_format('DATE_FORMAT'));
|
||||
// 'N j, Y'
|
||||
|
@ -1199,7 +1209,9 @@ translated word::
|
|||
|
||||
The ``npgettext`` function also behaves like the Python variant
|
||||
(:func:`~django.utils.translation.npgettext()`), providing a **pluralized**
|
||||
contextually translated word::
|
||||
contextually translated word:
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
document.write(npgettext('group', 'party', 1));
|
||||
// party
|
||||
|
@ -1211,7 +1223,9 @@ contextually translated word::
|
|||
|
||||
The ``pluralidx`` function works in a similar way to the :tfilter:`pluralize`
|
||||
template filter, determining if a given ``count`` should use a plural form of
|
||||
a word or not::
|
||||
a word or not:
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
document.write(pluralidx(0));
|
||||
// true
|
||||
|
|
|
@ -245,7 +245,7 @@ JSON in the following way::
|
|||
"model": "sessions.session",
|
||||
"fields": {
|
||||
"expire_date": "2013-01-16T08:16:59.844Z",
|
||||
...
|
||||
# ...
|
||||
}
|
||||
}
|
||||
]
|
||||
|
|
|
@ -125,6 +125,7 @@ In your Django apps, use settings by importing the object
|
|||
|
||||
if settings.DEBUG:
|
||||
# Do something
|
||||
...
|
||||
|
||||
Note that ``django.conf.settings`` isn't a module -- it's an object. So
|
||||
importing individual settings is not possible::
|
||||
|
|
|
@ -248,7 +248,9 @@ Use the ``django.test.Client`` class to make requests.
|
|||
>>> c = Client()
|
||||
>>> c.post('/login/', {'name': 'fred', 'passwd': 'secret'})
|
||||
|
||||
...will result in the evaluation of a POST request to this URL::
|
||||
...will result in the evaluation of a POST request to this URL:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
/login/
|
||||
|
||||
|
|
Loading…
Reference in New Issue