mirror of
https://github.com/django/django.git
synced 2025-09-03 02:45:09 +03:00
Compare commits
33 Commits
2cee3ad863
...
7732573126
Author | SHA1 | Date | |
---|---|---|---|
|
7732573126 | ||
|
a627194567 | ||
|
bb7a7701b1 | ||
|
2d453a2a68 | ||
|
183fcebf88 | ||
|
eaaf01c96a | ||
|
0be1c4575b | ||
|
550822bcee | ||
|
292b9e6fe8 | ||
|
dc4ee99152 | ||
|
41ff30f6f9 | ||
|
c93dddf659 | ||
|
56955636e6 | ||
|
ae03f81ffa | ||
|
a9fe98d5bd | ||
|
05bac8c420 | ||
|
3c0c54351b | ||
|
1285de557b | ||
|
d8426f64a7 | ||
|
4f07767106 | ||
|
1b0c4d5ea5 | ||
|
4c71e33440 | ||
|
d0e4dd5cdd | ||
|
c594574175 | ||
|
d454aefbd1 | ||
|
66082a7dac | ||
|
07f44c9e9a | ||
|
268c71f2d7 | ||
|
d3b92d0bbd | ||
|
a9830a403b | ||
|
c39c7133a0 | ||
|
54fa8b5693 | ||
|
76f4b0c0f3 |
14
.github/workflows/postgis.yml
vendored
14
.github/workflows/postgis.yml
vendored
|
@ -14,13 +14,17 @@ permissions:
|
|||
contents: read
|
||||
|
||||
jobs:
|
||||
postgis-latest:
|
||||
postgis:
|
||||
if: contains(github.event.pull_request.labels.*.name, 'geodjango')
|
||||
runs-on: ubuntu-latest
|
||||
name: Latest PostGIS
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
postgis-version: [latest, "17-3.5-alpine", "17-master"]
|
||||
name: PostGIS ${{ matrix.postgis-version }}
|
||||
services:
|
||||
postgres:
|
||||
image: postgis/postgis:latest
|
||||
image: postgis/postgis:${{ matrix.postgis-version }}
|
||||
env:
|
||||
POSTGRES_DB: geodjango
|
||||
POSTGRES_USER: user
|
||||
|
@ -41,8 +45,10 @@ jobs:
|
|||
python-version: '3.13'
|
||||
cache: 'pip'
|
||||
cache-dependency-path: 'tests/requirements/py3.txt'
|
||||
- name: Update apt repo
|
||||
run: sudo apt update
|
||||
- name: Install libmemcached-dev for pylibmc
|
||||
run: sudo apt install libmemcached-dev
|
||||
run: sudo apt install -y libmemcached-dev
|
||||
- name: Install geospatial dependencies
|
||||
run: sudo apt install -y binutils libproj-dev gdal-bin
|
||||
- name: Print PostGIS versions
|
||||
|
|
|
@ -10,6 +10,7 @@ from django.conf import settings
|
|||
from django.core.exceptions import ValidationError
|
||||
from django.core.validators import URLValidator
|
||||
from django.db.models import CASCADE, UUIDField
|
||||
from django.forms.widgets import Select
|
||||
from django.urls import reverse
|
||||
from django.urls.exceptions import NoReverseMatch
|
||||
from django.utils.html import smart_urlquote
|
||||
|
@ -284,16 +285,18 @@ class RelatedFieldWidgetWrapper(forms.Widget):
|
|||
if can_add_related is None:
|
||||
can_add_related = admin_site.is_registered(rel.model)
|
||||
self.can_add_related = can_add_related
|
||||
# XXX: The UX does not support multiple selected values.
|
||||
multiple = getattr(widget, "allow_multiple_selected", False)
|
||||
if not isinstance(widget, AutocompleteMixin):
|
||||
self.attrs["data-context"] = "available-source"
|
||||
self.can_change_related = not multiple and can_change_related
|
||||
# Only single-select Select widgets are supported.
|
||||
supported = not getattr(
|
||||
widget, "allow_multiple_selected", False
|
||||
) and isinstance(widget, Select)
|
||||
self.can_change_related = supported and can_change_related
|
||||
# XXX: The deletion UX can be confusing when dealing with cascading
|
||||
# deletion.
|
||||
cascade = getattr(rel, "on_delete", None) is CASCADE
|
||||
self.can_delete_related = not multiple and not cascade and can_delete_related
|
||||
self.can_view_related = not multiple and can_view_related
|
||||
self.can_delete_related = supported and not cascade and can_delete_related
|
||||
self.can_view_related = supported and can_view_related
|
||||
# To check if the related object is registered with this AdminSite.
|
||||
self.admin_site = admin_site
|
||||
self.use_fieldset = True
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import hmac
|
||||
import inspect
|
||||
import re
|
||||
import warnings
|
||||
|
@ -7,6 +6,7 @@ from django.apps import apps as django_apps
|
|||
from django.conf import settings
|
||||
from django.core.exceptions import ImproperlyConfigured, PermissionDenied
|
||||
from django.middleware.csrf import rotate_token
|
||||
from django.utils.crypto import constant_time_compare
|
||||
from django.utils.deprecation import RemovedInDjango61Warning
|
||||
from django.utils.module_loading import import_string
|
||||
from django.views.decorators.debug import sensitive_variables
|
||||
|
@ -175,7 +175,7 @@ def login(request, user, backend=None):
|
|||
if SESSION_KEY in request.session:
|
||||
if _get_user_session_key(request) != user.pk or (
|
||||
session_auth_hash
|
||||
and not hmac.compare_digest(
|
||||
and not constant_time_compare(
|
||||
request.session.get(HASH_SESSION_KEY, ""), session_auth_hash
|
||||
)
|
||||
):
|
||||
|
@ -217,7 +217,7 @@ async def alogin(request, user, backend=None):
|
|||
if await request.session.ahas_key(SESSION_KEY):
|
||||
if await _aget_user_session_key(request) != user.pk or (
|
||||
session_auth_hash
|
||||
and not hmac.compare_digest(
|
||||
and not constant_time_compare(
|
||||
await request.session.aget(HASH_SESSION_KEY, ""),
|
||||
session_auth_hash,
|
||||
)
|
||||
|
@ -323,7 +323,7 @@ def get_user(request):
|
|||
session_hash_verified = False
|
||||
else:
|
||||
session_auth_hash = user.get_session_auth_hash()
|
||||
session_hash_verified = hmac.compare_digest(
|
||||
session_hash_verified = constant_time_compare(
|
||||
session_hash, session_auth_hash
|
||||
)
|
||||
if not session_hash_verified:
|
||||
|
@ -331,7 +331,7 @@ def get_user(request):
|
|||
# with the fallback secrets and stop when a matching one is
|
||||
# found.
|
||||
if session_hash and any(
|
||||
hmac.compare_digest(session_hash, fallback_auth_hash)
|
||||
constant_time_compare(session_hash, fallback_auth_hash)
|
||||
for fallback_auth_hash in user.get_session_auth_fallback_hash()
|
||||
):
|
||||
request.session.cycle_key()
|
||||
|
@ -364,7 +364,7 @@ async def aget_user(request):
|
|||
session_hash_verified = False
|
||||
else:
|
||||
session_auth_hash = user.get_session_auth_hash()
|
||||
session_hash_verified = hmac.compare_digest(
|
||||
session_hash_verified = constant_time_compare(
|
||||
session_hash, session_auth_hash
|
||||
)
|
||||
if not session_hash_verified:
|
||||
|
@ -372,7 +372,7 @@ async def aget_user(request):
|
|||
# with the fallback secrets and stop when a matching one is
|
||||
# found.
|
||||
if session_hash and any(
|
||||
hmac.compare_digest(session_hash, fallback_auth_hash)
|
||||
constant_time_compare(session_hash, fallback_auth_hash)
|
||||
for fallback_auth_hash in user.get_session_auth_fallback_hash()
|
||||
):
|
||||
await request.session.acycle_key()
|
||||
|
|
|
@ -2,7 +2,6 @@ import base64
|
|||
import binascii
|
||||
import functools
|
||||
import hashlib
|
||||
import hmac
|
||||
import importlib
|
||||
import math
|
||||
import warnings
|
||||
|
@ -13,7 +12,12 @@ from django.conf import settings
|
|||
from django.core.exceptions import ImproperlyConfigured
|
||||
from django.core.signals import setting_changed
|
||||
from django.dispatch import receiver
|
||||
from django.utils.crypto import RANDOM_STRING_CHARS, get_random_string, pbkdf2
|
||||
from django.utils.crypto import (
|
||||
RANDOM_STRING_CHARS,
|
||||
constant_time_compare,
|
||||
get_random_string,
|
||||
pbkdf2,
|
||||
)
|
||||
from django.utils.encoding import force_bytes, force_str
|
||||
from django.utils.module_loading import import_string
|
||||
from django.utils.translation import gettext_noop as _
|
||||
|
@ -345,7 +349,7 @@ class PBKDF2PasswordHasher(BasePasswordHasher):
|
|||
def verify(self, password, encoded):
|
||||
decoded = self.decode(encoded)
|
||||
encoded_2 = self.encode(password, decoded["salt"], decoded["iterations"])
|
||||
return hmac.compare_digest(encoded, encoded_2)
|
||||
return constant_time_compare(encoded, encoded_2)
|
||||
|
||||
def safe_summary(self, encoded):
|
||||
decoded = self.decode(encoded)
|
||||
|
@ -529,7 +533,7 @@ class BCryptSHA256PasswordHasher(BasePasswordHasher):
|
|||
algorithm, data = encoded.split("$", 1)
|
||||
assert algorithm == self.algorithm
|
||||
encoded_2 = self.encode(password, data.encode("ascii"))
|
||||
return hmac.compare_digest(encoded, encoded_2)
|
||||
return constant_time_compare(encoded, encoded_2)
|
||||
|
||||
def safe_summary(self, encoded):
|
||||
decoded = self.decode(encoded)
|
||||
|
@ -624,7 +628,7 @@ class ScryptPasswordHasher(BasePasswordHasher):
|
|||
decoded["block_size"],
|
||||
decoded["parallelism"],
|
||||
)
|
||||
return hmac.compare_digest(encoded, encoded_2)
|
||||
return constant_time_compare(encoded, encoded_2)
|
||||
|
||||
def safe_summary(self, encoded):
|
||||
decoded = self.decode(encoded)
|
||||
|
@ -677,7 +681,7 @@ class MD5PasswordHasher(BasePasswordHasher):
|
|||
def verify(self, password, encoded):
|
||||
decoded = self.decode(encoded)
|
||||
encoded_2 = self.encode(password, decoded["salt"])
|
||||
return hmac.compare_digest(encoded, encoded_2)
|
||||
return constant_time_compare(encoded, encoded_2)
|
||||
|
||||
def safe_summary(self, encoded):
|
||||
decoded = self.decode(encoded)
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
import hmac
|
||||
from datetime import datetime
|
||||
|
||||
from django.conf import settings
|
||||
from django.utils.crypto import salted_hmac
|
||||
from django.utils.crypto import constant_time_compare, salted_hmac
|
||||
from django.utils.http import base36_to_int, int_to_base36
|
||||
|
||||
|
||||
|
@ -68,7 +67,7 @@ class PasswordResetTokenGenerator:
|
|||
|
||||
# Check that the timestamp/uid has not been tampered with
|
||||
for secret in [self.secret, *self.secret_fallbacks]:
|
||||
if hmac.compare_digest(
|
||||
if constant_time_compare(
|
||||
self._make_token_with_timestamp(user, ts, secret),
|
||||
token,
|
||||
):
|
||||
|
|
|
@ -2,24 +2,16 @@
|
|||
This module contains useful utilities for GeoDjango.
|
||||
"""
|
||||
|
||||
from django.contrib.gis.utils.layermapping import LayerMapError, LayerMapping
|
||||
from django.contrib.gis.utils.ogrinfo import ogrinfo
|
||||
from django.contrib.gis.utils.ogrinspect import mapping, ogrinspect
|
||||
from django.contrib.gis.utils.srs import add_srs_entry
|
||||
from django.core.exceptions import ImproperlyConfigured
|
||||
|
||||
__all__ = [
|
||||
"add_srs_entry",
|
||||
"mapping",
|
||||
"ogrinfo",
|
||||
"ogrinspect",
|
||||
"LayerMapError",
|
||||
"LayerMapping",
|
||||
]
|
||||
|
||||
try:
|
||||
# LayerMapping requires DJANGO_SETTINGS_MODULE to be set,
|
||||
# and ImproperlyConfigured is raised if that's not the case.
|
||||
from django.contrib.gis.utils.layermapping import LayerMapError, LayerMapping
|
||||
|
||||
__all__ += ["LayerMapError", "LayerMapping"]
|
||||
|
||||
except ImproperlyConfigured:
|
||||
pass
|
||||
|
|
|
@ -7,4 +7,3 @@ class RedirectAdmin(admin.ModelAdmin):
|
|||
list_display = ("old_path", "new_path")
|
||||
list_filter = ("site",)
|
||||
search_fields = ("old_path", "new_path")
|
||||
radio_fields = {"site": admin.VERTICAL}
|
||||
|
|
|
@ -36,13 +36,12 @@ These functions make use of all of them.
|
|||
|
||||
import base64
|
||||
import datetime
|
||||
import hmac
|
||||
import json
|
||||
import time
|
||||
import zlib
|
||||
|
||||
from django.conf import settings
|
||||
from django.utils.crypto import salted_hmac
|
||||
from django.utils.crypto import constant_time_compare, salted_hmac
|
||||
from django.utils.encoding import force_bytes
|
||||
from django.utils.module_loading import import_string
|
||||
from django.utils.regex_helper import _lazy_re_compile
|
||||
|
@ -210,7 +209,7 @@ class Signer:
|
|||
raise BadSignature('No "%s" found in value' % self.sep)
|
||||
value, sig = signed_value.rsplit(self.sep, 1)
|
||||
for key in [self.key, *self.fallback_keys]:
|
||||
if hmac.compare_digest(sig, self.signature(value, key)):
|
||||
if constant_time_compare(sig, self.signature(value, key)):
|
||||
return value
|
||||
raise BadSignature('Signature "%s" does not match' % sig)
|
||||
|
||||
|
|
|
@ -208,13 +208,6 @@ class BaseDatabaseOperations:
|
|||
else:
|
||||
return ["DISTINCT"], []
|
||||
|
||||
def fetch_returned_insert_columns(self, cursor, returning_params):
|
||||
"""
|
||||
Given a cursor object that has just performed an INSERT...RETURNING
|
||||
statement into a table, return the newly created data.
|
||||
"""
|
||||
return cursor.fetchone()
|
||||
|
||||
def force_group_by(self):
|
||||
"""
|
||||
Return a GROUP BY clause to use with a HAVING clause when no grouping
|
||||
|
@ -358,13 +351,31 @@ class BaseDatabaseOperations:
|
|||
"""
|
||||
return value
|
||||
|
||||
def return_insert_columns(self, fields):
|
||||
def returning_columns(self, fields):
|
||||
"""
|
||||
For backends that support returning columns as part of an insert query,
|
||||
return the SQL and params to append to the INSERT query. The returned
|
||||
fragment should contain a format string to hold the appropriate column.
|
||||
For backends that support returning columns as part of an insert or
|
||||
update query, return the SQL and params to append to the query.
|
||||
The returned fragment should contain a format string to hold the
|
||||
appropriate column.
|
||||
"""
|
||||
pass
|
||||
if not fields:
|
||||
return "", ()
|
||||
columns = [
|
||||
"%s.%s"
|
||||
% (
|
||||
self.quote_name(field.model._meta.db_table),
|
||||
self.quote_name(field.column),
|
||||
)
|
||||
for field in fields
|
||||
]
|
||||
return "RETURNING %s" % ", ".join(columns), ()
|
||||
|
||||
def fetch_returned_rows(self, cursor, returning_params):
|
||||
"""
|
||||
Given a cursor object for a DML query with a RETURNING statement,
|
||||
return the selected returning rows of tuples.
|
||||
"""
|
||||
return cursor.fetchall()
|
||||
|
||||
def compiler(self, compiler_name):
|
||||
"""
|
||||
|
|
|
@ -148,13 +148,6 @@ class DatabaseOperations(BaseDatabaseOperations):
|
|||
else:
|
||||
return f"TIME({sql})", params
|
||||
|
||||
def fetch_returned_insert_rows(self, cursor):
|
||||
"""
|
||||
Given a cursor object that has just performed an INSERT...RETURNING
|
||||
statement into a table, return the tuple of returned data.
|
||||
"""
|
||||
return cursor.fetchall()
|
||||
|
||||
def format_for_duration_arithmetic(self, sql):
|
||||
return "INTERVAL %s MICROSECOND" % sql
|
||||
|
||||
|
@ -182,20 +175,6 @@ class DatabaseOperations(BaseDatabaseOperations):
|
|||
return name # Quoting once is enough.
|
||||
return "`%s`" % name
|
||||
|
||||
def return_insert_columns(self, fields):
|
||||
# MySQL doesn't support an INSERT...RETURNING statement.
|
||||
if not fields:
|
||||
return "", ()
|
||||
columns = [
|
||||
"%s.%s"
|
||||
% (
|
||||
self.quote_name(field.model._meta.db_table),
|
||||
self.quote_name(field.column),
|
||||
)
|
||||
for field in fields
|
||||
]
|
||||
return "RETURNING %s" % ", ".join(columns), ()
|
||||
|
||||
def sql_flush(self, style, tables, *, reset_sequences=False, allow_cascade=False):
|
||||
if not tables:
|
||||
return []
|
||||
|
|
|
@ -22,7 +22,7 @@ from django.utils.functional import cached_property
|
|||
from django.utils.regex_helper import _lazy_re_compile
|
||||
|
||||
from .base import Database
|
||||
from .utils import BulkInsertMapper, InsertVar, Oracle_datetime
|
||||
from .utils import BoundVar, BulkInsertMapper, Oracle_datetime
|
||||
|
||||
|
||||
class DatabaseOperations(BaseDatabaseOperations):
|
||||
|
@ -298,12 +298,27 @@ END;
|
|||
def deferrable_sql(self):
|
||||
return " DEFERRABLE INITIALLY DEFERRED"
|
||||
|
||||
def fetch_returned_insert_columns(self, cursor, returning_params):
|
||||
columns = []
|
||||
for param in returning_params:
|
||||
value = param.get_value()
|
||||
columns.append(value[0])
|
||||
return tuple(columns)
|
||||
def returning_columns(self, fields):
|
||||
if not fields:
|
||||
return "", ()
|
||||
field_names = []
|
||||
params = []
|
||||
for field in fields:
|
||||
field_names.append(
|
||||
"%s.%s"
|
||||
% (
|
||||
self.quote_name(field.model._meta.db_table),
|
||||
self.quote_name(field.column),
|
||||
)
|
||||
)
|
||||
params.append(BoundVar(field))
|
||||
return "RETURNING %s INTO %s" % (
|
||||
", ".join(field_names),
|
||||
", ".join(["%s"] * len(params)),
|
||||
), tuple(params)
|
||||
|
||||
def fetch_returned_rows(self, cursor, returning_params):
|
||||
return list(zip(*(param.get_value() for param in returning_params)))
|
||||
|
||||
def no_limit_value(self):
|
||||
return None
|
||||
|
@ -391,25 +406,6 @@ END;
|
|||
match_option = "'i'"
|
||||
return "REGEXP_LIKE(%%s, %%s, %s)" % match_option
|
||||
|
||||
def return_insert_columns(self, fields):
|
||||
if not fields:
|
||||
return "", ()
|
||||
field_names = []
|
||||
params = []
|
||||
for field in fields:
|
||||
field_names.append(
|
||||
"%s.%s"
|
||||
% (
|
||||
self.quote_name(field.model._meta.db_table),
|
||||
self.quote_name(field.column),
|
||||
)
|
||||
)
|
||||
params.append(InsertVar(field))
|
||||
return "RETURNING %s INTO %s" % (
|
||||
", ".join(field_names),
|
||||
", ".join(["%s"] * len(params)),
|
||||
), tuple(params)
|
||||
|
||||
def __foreign_key_constraints(self, table_name, recursive):
|
||||
with self.connection.cursor() as cursor:
|
||||
if recursive:
|
||||
|
|
|
@ -4,7 +4,7 @@ import decimal
|
|||
from .base import Database
|
||||
|
||||
|
||||
class InsertVar:
|
||||
class BoundVar:
|
||||
"""
|
||||
A late-binding cursor variable that can be passed to Cursor.execute
|
||||
as a parameter, in order to receive the id of the row created by an
|
||||
|
|
|
@ -155,13 +155,6 @@ class DatabaseOperations(BaseDatabaseOperations):
|
|||
return f"SELECT * FROM {placeholder_rows}"
|
||||
return super().bulk_insert_sql(fields, placeholder_rows)
|
||||
|
||||
def fetch_returned_insert_rows(self, cursor):
|
||||
"""
|
||||
Given a cursor object that has just performed an INSERT...RETURNING
|
||||
statement into a table, return the tuple of returned data.
|
||||
"""
|
||||
return cursor.fetchall()
|
||||
|
||||
def lookup_cast(self, lookup_type, internal_type=None):
|
||||
lookup = "%s"
|
||||
# Cast text lookups to text to allow things like filter(x__contains=4)
|
||||
|
@ -324,19 +317,6 @@ class DatabaseOperations(BaseDatabaseOperations):
|
|||
return cursor.query.decode()
|
||||
return None
|
||||
|
||||
def return_insert_columns(self, fields):
|
||||
if not fields:
|
||||
return "", ()
|
||||
columns = [
|
||||
"%s.%s"
|
||||
% (
|
||||
self.quote_name(field.model._meta.db_table),
|
||||
self.quote_name(field.column),
|
||||
)
|
||||
for field in fields
|
||||
]
|
||||
return "RETURNING %s" % ", ".join(columns), ()
|
||||
|
||||
if is_psycopg3:
|
||||
|
||||
def adapt_integerfield_value(self, value, internal_type):
|
||||
|
|
|
@ -84,13 +84,6 @@ class DatabaseOperations(BaseDatabaseOperations):
|
|||
"""
|
||||
return f"django_date_extract(%s, {sql})", (lookup_type.lower(), *params)
|
||||
|
||||
def fetch_returned_insert_rows(self, cursor):
|
||||
"""
|
||||
Given a cursor object that has just performed an INSERT...RETURNING
|
||||
statement into a table, return the list of returned data.
|
||||
"""
|
||||
return cursor.fetchall()
|
||||
|
||||
def format_for_duration_arithmetic(self, sql):
|
||||
"""Do nothing since formatting is handled in the custom function."""
|
||||
return sql
|
||||
|
@ -399,20 +392,6 @@ class DatabaseOperations(BaseDatabaseOperations):
|
|||
return "INSERT OR IGNORE INTO"
|
||||
return super().insert_statement(on_conflict=on_conflict)
|
||||
|
||||
def return_insert_columns(self, fields):
|
||||
# SQLite < 3.35 doesn't support an INSERT...RETURNING statement.
|
||||
if not fields:
|
||||
return "", ()
|
||||
columns = [
|
||||
"%s.%s"
|
||||
% (
|
||||
self.quote_name(field.model._meta.db_table),
|
||||
self.quote_name(field.column),
|
||||
)
|
||||
for field in fields
|
||||
]
|
||||
return "RETURNING %s" % ", ".join(columns), ()
|
||||
|
||||
def on_conflict_suffix_sql(self, fields, on_conflict, update_fields, unique_fields):
|
||||
if (
|
||||
on_conflict == OnConflict.UPDATE
|
||||
|
|
|
@ -35,6 +35,7 @@ from django.db.models.utils import (
|
|||
resolve_callables,
|
||||
)
|
||||
from django.utils import timezone
|
||||
from django.utils.deprecation import RemovedInDjango70Warning
|
||||
from django.utils.functional import cached_property
|
||||
|
||||
# The maximum number of results to fetch in a get() query.
|
||||
|
@ -1394,7 +1395,12 @@ class QuerySet(AltersData):
|
|||
def _values(self, *fields, **expressions):
|
||||
clone = self._chain()
|
||||
if expressions:
|
||||
clone = clone.annotate(**expressions)
|
||||
# RemovedInDjango70Warning: When the deprecation ends, deindent as:
|
||||
# clone = clone.annotate(**expressions)
|
||||
with warnings.catch_warnings(
|
||||
action="ignore", category=RemovedInDjango70Warning
|
||||
):
|
||||
clone = clone.annotate(**expressions)
|
||||
clone._fields = fields
|
||||
clone.query.set_values(fields)
|
||||
return clone
|
||||
|
|
|
@ -1890,7 +1890,7 @@ class SQLInsertCompiler(SQLCompiler):
|
|||
result.append(on_conflict_suffix_sql)
|
||||
# Skip empty r_sql to allow subclasses to customize behavior for
|
||||
# 3rd party backends. Refs #19096.
|
||||
r_sql, self.returning_params = self.connection.ops.return_insert_columns(
|
||||
r_sql, self.returning_params = self.connection.ops.returning_columns(
|
||||
self.returning_fields
|
||||
)
|
||||
if r_sql:
|
||||
|
@ -1925,20 +1925,16 @@ class SQLInsertCompiler(SQLCompiler):
|
|||
cursor.execute(sql, params)
|
||||
if not self.returning_fields:
|
||||
return []
|
||||
obj_len = len(self.query.objs)
|
||||
if (
|
||||
self.connection.features.can_return_rows_from_bulk_insert
|
||||
and len(self.query.objs) > 1
|
||||
and obj_len > 1
|
||||
) or (
|
||||
self.connection.features.can_return_columns_from_insert and obj_len == 1
|
||||
):
|
||||
rows = self.connection.ops.fetch_returned_insert_rows(cursor)
|
||||
cols = [field.get_col(opts.db_table) for field in self.returning_fields]
|
||||
elif self.connection.features.can_return_columns_from_insert:
|
||||
assert len(self.query.objs) == 1
|
||||
rows = [
|
||||
self.connection.ops.fetch_returned_insert_columns(
|
||||
cursor,
|
||||
self.returning_params,
|
||||
)
|
||||
]
|
||||
rows = self.connection.ops.fetch_returned_rows(
|
||||
cursor, self.returning_params
|
||||
)
|
||||
cols = [field.get_col(opts.db_table) for field in self.returning_fields]
|
||||
elif returning_fields and isinstance(
|
||||
returning_field := returning_fields[0], AutoField
|
||||
|
|
|
@ -1219,7 +1219,7 @@ class Query(BaseExpression):
|
|||
if "aggregate" in {frame.function for frame in inspect.stack()}:
|
||||
stacklevel = 5
|
||||
else:
|
||||
# annotate() and alias().
|
||||
# annotate(), alias(), and values().
|
||||
stacklevel = 6
|
||||
warnings.warn(
|
||||
"Using percent signs in a column alias is deprecated.",
|
||||
|
@ -2269,8 +2269,21 @@ class Query(BaseExpression):
|
|||
join_info.joins,
|
||||
join_info.path,
|
||||
)
|
||||
for target in targets:
|
||||
cols.append(join_info.transform_function(target, final_alias))
|
||||
if len(targets) > 1:
|
||||
transformed_targets = [
|
||||
join_info.transform_function(target, final_alias)
|
||||
for target in targets
|
||||
]
|
||||
cols.append(
|
||||
ColPairs(
|
||||
final_alias if self.alias_cols else None,
|
||||
[col.target for col in transformed_targets],
|
||||
[col.output_field for col in transformed_targets],
|
||||
join_info.final_field,
|
||||
)
|
||||
)
|
||||
else:
|
||||
cols.append(join_info.transform_function(targets[0], final_alias))
|
||||
if cols:
|
||||
self.set_select(cols)
|
||||
except MultiJoin:
|
||||
|
|
|
@ -721,11 +721,10 @@ def parse_boundary_stream(stream, max_header_size):
|
|||
|
||||
# Eliminate blank lines
|
||||
for line in header.split(b"\r\n"):
|
||||
# This terminology ("main value" and "dictionary of
|
||||
# parameters") is from the Python docs.
|
||||
try:
|
||||
main_value_pair, params = parse_header_parameters(line.decode())
|
||||
name, value = main_value_pair.split(":", 1)
|
||||
header_name, value_and_params = line.decode().split(":", 1)
|
||||
name = header_name.lower().rstrip(" ")
|
||||
value, params = parse_header_parameters(value_and_params.lstrip(" "))
|
||||
params = {k: v.encode() for k, v in params.items()}
|
||||
except ValueError: # Invalid header.
|
||||
continue
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
from http import HTTPStatus
|
||||
|
||||
from django.conf import settings
|
||||
from django.utils.csp import CSP, LazyNonce, build_policy
|
||||
from django.utils.deprecation import MiddlewareMixin
|
||||
|
@ -14,22 +12,21 @@ class ContentSecurityPolicyMiddleware(MiddlewareMixin):
|
|||
request._csp_nonce = LazyNonce()
|
||||
|
||||
def process_response(self, request, response):
|
||||
# In DEBUG mode, exclude CSP headers for specific status codes that
|
||||
# trigger the debug view.
|
||||
exempted_status_codes = {
|
||||
HTTPStatus.NOT_FOUND,
|
||||
HTTPStatus.INTERNAL_SERVER_ERROR,
|
||||
}
|
||||
if settings.DEBUG and response.status_code in exempted_status_codes:
|
||||
return response
|
||||
|
||||
nonce = get_nonce(request)
|
||||
|
||||
sentinel = object()
|
||||
if (csp_config := getattr(response, "_csp_config", sentinel)) is sentinel:
|
||||
csp_config = settings.SECURE_CSP
|
||||
if (csp_ro_config := getattr(response, "_csp_ro_config", sentinel)) is sentinel:
|
||||
csp_ro_config = settings.SECURE_CSP_REPORT_ONLY
|
||||
|
||||
for header, config in [
|
||||
(CSP.HEADER_ENFORCE, settings.SECURE_CSP),
|
||||
(CSP.HEADER_REPORT_ONLY, settings.SECURE_CSP_REPORT_ONLY),
|
||||
(CSP.HEADER_ENFORCE, csp_config),
|
||||
(CSP.HEADER_REPORT_ONLY, csp_ro_config),
|
||||
]:
|
||||
# If headers are already set on the response, don't overwrite them.
|
||||
# This allows for views to set their own CSP headers as needed.
|
||||
# An empty config means CSP headers are not added to the response.
|
||||
if config and header not in response:
|
||||
response.headers[str(header)] = build_policy(config, nonce)
|
||||
|
||||
|
|
|
@ -5,7 +5,6 @@ This module provides a middleware that implements protection
|
|||
against request forgeries from other sites.
|
||||
"""
|
||||
|
||||
import hmac
|
||||
import logging
|
||||
import string
|
||||
from collections import defaultdict
|
||||
|
@ -16,7 +15,7 @@ from django.core.exceptions import DisallowedHost, ImproperlyConfigured
|
|||
from django.http import HttpHeaders, UnreadablePostError
|
||||
from django.urls import get_callable
|
||||
from django.utils.cache import patch_vary_headers
|
||||
from django.utils.crypto import get_random_string
|
||||
from django.utils.crypto import constant_time_compare, get_random_string
|
||||
from django.utils.deprecation import MiddlewareMixin
|
||||
from django.utils.functional import cached_property
|
||||
from django.utils.http import is_same_domain
|
||||
|
@ -155,7 +154,7 @@ def _does_token_match(request_csrf_token, csrf_secret):
|
|||
if len(request_csrf_token) == CSRF_TOKEN_LENGTH:
|
||||
request_csrf_token = _unmask_cipher_token(request_csrf_token)
|
||||
assert len(request_csrf_token) == CSRF_SECRET_LENGTH
|
||||
return hmac.compare_digest(request_csrf_token, csrf_secret)
|
||||
return constant_time_compare(request_csrf_token, csrf_secret)
|
||||
|
||||
|
||||
class RejectRequest(Exception):
|
||||
|
|
|
@ -5,10 +5,8 @@ Django's standard crypto functions and utilities.
|
|||
import hashlib
|
||||
import hmac
|
||||
import secrets
|
||||
import warnings
|
||||
|
||||
from django.conf import settings
|
||||
from django.utils.deprecation import RemovedInDjango70Warning
|
||||
from django.utils.encoding import force_bytes
|
||||
|
||||
|
||||
|
@ -66,12 +64,7 @@ def get_random_string(length, allowed_chars=RANDOM_STRING_CHARS):
|
|||
|
||||
def constant_time_compare(val1, val2):
|
||||
"""Return True if the two strings are equal, False otherwise."""
|
||||
warnings.warn(
|
||||
"constant_time_compare() is deprecated. Use hmac.compare_digest() instead.",
|
||||
RemovedInDjango70Warning,
|
||||
stacklevel=2,
|
||||
)
|
||||
return hmac.compare_digest(val1, val2)
|
||||
return secrets.compare_digest(force_bytes(val1), force_bytes(val2))
|
||||
|
||||
|
||||
def pbkdf2(password, salt, iterations, dklen=0, digest=None):
|
||||
|
|
|
@ -10,7 +10,7 @@ from urllib.parse import parse_qsl, quote, unquote, urlencode, urlsplit, urlunsp
|
|||
|
||||
from django.conf import settings
|
||||
from django.core.exceptions import SuspiciousOperation, ValidationError
|
||||
from django.core.validators import EmailValidator
|
||||
from django.core.validators import DomainNameValidator, EmailValidator
|
||||
from django.utils.deprecation import RemovedInDjango70Warning
|
||||
from django.utils.functional import Promise, cached_property, keep_lazy, keep_lazy_text
|
||||
from django.utils.http import MAX_URL_LENGTH, RFC3986_GENDELIMS, RFC3986_SUBDELIMS
|
||||
|
@ -296,7 +296,9 @@ class Urlizer:
|
|||
|
||||
simple_url_re = _lazy_re_compile(r"^https?://\[?\w", re.IGNORECASE)
|
||||
simple_url_2_re = _lazy_re_compile(
|
||||
r"^www\.|^(?!http)\w[^@]+\.(com|edu|gov|int|mil|net|org)($|/.*)$", re.IGNORECASE
|
||||
rf"^www\.|^(?!http)(?:{DomainNameValidator.hostname_re})"
|
||||
r"\.(com|edu|gov|int|mil|net|org)($|/.*)$",
|
||||
re.IGNORECASE,
|
||||
)
|
||||
word_split_re = _lazy_re_compile(r"""([\s<>"']+)""")
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@ from django.utils.encoding import force_str
|
|||
from django.utils.module_loading import import_string
|
||||
from django.utils.regex_helper import _lazy_re_compile
|
||||
from django.utils.version import get_docs_version
|
||||
from django.views.decorators.csp import csp_override, csp_report_only_override
|
||||
from django.views.decorators.debug import coroutine_functions_to_sensitive_variables
|
||||
|
||||
# Minimal Django templates engine to render the error templates
|
||||
|
@ -59,6 +60,8 @@ class CallableSettingWrapper:
|
|||
return repr(self._wrapped)
|
||||
|
||||
|
||||
@csp_override({})
|
||||
@csp_report_only_override({})
|
||||
def technical_500_response(request, exc_type, exc_value, tb, status_code=500):
|
||||
"""
|
||||
Create a technical server error response. The last three arguments are
|
||||
|
@ -606,6 +609,8 @@ class ExceptionReporter:
|
|||
tb = tb.tb_next
|
||||
|
||||
|
||||
@csp_override({})
|
||||
@csp_report_only_override({})
|
||||
def technical_404_response(request, exception):
|
||||
"""Create a technical 404 error response. `exception` is the Http404."""
|
||||
try:
|
||||
|
|
39
django/views/decorators/csp.py
Normal file
39
django/views/decorators/csp.py
Normal file
|
@ -0,0 +1,39 @@
|
|||
from functools import wraps
|
||||
|
||||
from asgiref.sync import iscoroutinefunction
|
||||
|
||||
|
||||
def _make_csp_decorator(config_attr_name, config_attr_value):
|
||||
"""General CSP override decorator factory."""
|
||||
|
||||
if not isinstance(config_attr_value, dict):
|
||||
raise TypeError("CSP config should be a mapping.")
|
||||
|
||||
def decorator(view_func):
|
||||
@wraps(view_func)
|
||||
async def _wrapped_async_view(request, *args, **kwargs):
|
||||
response = await view_func(request, *args, **kwargs)
|
||||
setattr(response, config_attr_name, config_attr_value)
|
||||
return response
|
||||
|
||||
@wraps(view_func)
|
||||
def _wrapped_sync_view(request, *args, **kwargs):
|
||||
response = view_func(request, *args, **kwargs)
|
||||
setattr(response, config_attr_name, config_attr_value)
|
||||
return response
|
||||
|
||||
if iscoroutinefunction(view_func):
|
||||
return _wrapped_async_view
|
||||
return _wrapped_sync_view
|
||||
|
||||
return decorator
|
||||
|
||||
|
||||
def csp_override(config):
|
||||
"""Override the Content-Security-Policy header for a view."""
|
||||
return _make_csp_decorator("_csp_config", config)
|
||||
|
||||
|
||||
def csp_report_only_override(config):
|
||||
"""Override the Content-Security-Policy-Report-Only header for a view."""
|
||||
return _make_csp_decorator("_csp_ro_config", config)
|
|
@ -27,22 +27,40 @@
|
|||
}
|
||||
{% endif %}
|
||||
|
||||
function getValueFromCatalog(msgid, index) {
|
||||
const value = django.catalog[msgid];
|
||||
|
||||
// if value in catalog is a string, return it
|
||||
if (typeof value === 'string' && value) {
|
||||
return value;
|
||||
}
|
||||
|
||||
// if value in catalog is an array and index is present, return the array index if exists
|
||||
if (value && value.constructor === Array && index !== undefined) {
|
||||
const text = value[index];
|
||||
|
||||
if (typeof text === 'string' && text) {
|
||||
return text;
|
||||
}
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (!django.jsi18n_initialized) {
|
||||
django.gettext = function(msgid) {
|
||||
const value = django.catalog[msgid];
|
||||
if (typeof value === 'undefined') {
|
||||
return msgid;
|
||||
} else {
|
||||
return (typeof value === 'string') ? value : value[0];
|
||||
}
|
||||
const value = getValueFromCatalog(msgid, 0);
|
||||
|
||||
return value !== undefined ? value : msgid;
|
||||
};
|
||||
|
||||
django.ngettext = function(singular, plural, count) {
|
||||
const value = django.catalog[singular];
|
||||
if (typeof value === 'undefined') {
|
||||
return (count == 1) ? singular : plural;
|
||||
const value = getValueFromCatalog(singular, django.pluralidx(count));
|
||||
|
||||
if (value !== undefined) {
|
||||
return value;
|
||||
} else {
|
||||
return value.constructor === Array ? value[django.pluralidx(count)] : value;
|
||||
return (count == 1) ? singular : plural;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -25,4 +25,4 @@ Indices, glossary and tables
|
|||
|
||||
* :ref:`genindex`
|
||||
* :ref:`modindex`
|
||||
* :doc:`glossary`
|
||||
* :doc:`/glossary`
|
||||
|
|
|
@ -120,7 +120,7 @@ this::
|
|||
# ...
|
||||
|
||||
The option (``delete`` in our example) is available in the options dict
|
||||
parameter of the handle method. See the :py:mod:`argparse` Python documentation
|
||||
parameter of the handle method. See the :mod:`argparse` Python documentation
|
||||
for more about ``add_argument`` usage.
|
||||
|
||||
In addition to being able to add custom command line options, all
|
||||
|
@ -208,7 +208,7 @@ All attributes can be set in your derived class and can be used in
|
|||
|
||||
If your command defines mandatory positional arguments, you can customize
|
||||
the message error returned in the case of missing arguments. The default is
|
||||
output by :py:mod:`argparse` ("too few arguments").
|
||||
output by :mod:`argparse` ("too few arguments").
|
||||
|
||||
.. attribute:: BaseCommand.output_transaction
|
||||
|
||||
|
|
|
@ -29,8 +29,8 @@ You should also consider how you will handle :doc:`static files
|
|||
:doc:`error reporting</howto/error-reporting>`.
|
||||
|
||||
Finally, before you deploy your application to production, you should run
|
||||
through our :doc:`deployment checklist<checklist>` to ensure that your
|
||||
configurations are suitable.
|
||||
through our :doc:`deployment checklist </howto/deployment/checklist>` to ensure
|
||||
that your configurations are suitable.
|
||||
|
||||
.. _WSGI: https://wsgi.readthedocs.io/en/latest/
|
||||
.. _ASGI: https://asgi.readthedocs.io/en/latest/
|
||||
|
|
|
@ -25,7 +25,7 @@ To send a log message from within your code, you place a logging call into it.
|
|||
logging, use a view function as suggested in the example below.
|
||||
|
||||
First, import the Python logging library, and then obtain a logger instance
|
||||
with :py:func:`logging.getLogger`. Provide the ``getLogger()`` method with a
|
||||
with :func:`logging.getLogger`. Provide the ``getLogger()`` method with a
|
||||
name to identify it and the records it emits. A good option is to use
|
||||
``__name__`` (see :ref:`naming-loggers` below for more on this) which will
|
||||
provide the name of the current Python module as a dotted path::
|
||||
|
@ -43,7 +43,7 @@ And then in a function, for example in a view, send a record to the logger::
|
|||
if some_risky_state:
|
||||
logger.warning("Platform is running at risk")
|
||||
|
||||
When this code is executed, a :py:class:`~logging.LogRecord` containing that
|
||||
When this code is executed, a :class:`~logging.LogRecord` containing that
|
||||
message will be sent to the logger. If you're using Django's default logging
|
||||
configuration, the message will appear in the console.
|
||||
|
||||
|
@ -129,7 +129,7 @@ file ``general.log`` (at the project root):
|
|||
Different handler classes take different configuration options. For more
|
||||
information on available handler classes, see the
|
||||
:class:`~django.utils.log.AdminEmailHandler` provided by Django and the various
|
||||
:py:mod:`handler classes <logging.handlers>` provided by Python.
|
||||
:mod:`handler classes <logging.handlers>` provided by Python.
|
||||
|
||||
Logging levels can also be set on the handlers (by default, they accept log
|
||||
messages of all levels). Using the example above, adding:
|
||||
|
@ -238,7 +238,7 @@ application. A named logging configuration will capture logs only from loggers
|
|||
with matching names.
|
||||
|
||||
The namespace of a logger instance is defined using
|
||||
:py:func:`~logging.getLogger`. For example in ``views.py`` of ``my_app``::
|
||||
:func:`~logging.getLogger`. For example in ``views.py`` of ``my_app``::
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
|
302
docs/index.txt
302
docs/index.txt
|
@ -12,34 +12,34 @@ First steps
|
|||
Are you new to Django or to programming? This is the place to start!
|
||||
|
||||
* **From scratch:**
|
||||
:doc:`Overview <intro/overview>` |
|
||||
:doc:`Installation <intro/install>`
|
||||
:doc:`Overview </intro/overview>` |
|
||||
:doc:`Installation </intro/install>`
|
||||
|
||||
* **Tutorial:**
|
||||
:doc:`Part 1: Requests and responses <intro/tutorial01>` |
|
||||
:doc:`Part 2: Models and the admin site <intro/tutorial02>` |
|
||||
:doc:`Part 3: Views and templates <intro/tutorial03>` |
|
||||
:doc:`Part 4: Forms and generic views <intro/tutorial04>` |
|
||||
:doc:`Part 5: Testing <intro/tutorial05>` |
|
||||
:doc:`Part 6: Static files <intro/tutorial06>` |
|
||||
:doc:`Part 7: Customizing the admin site <intro/tutorial07>` |
|
||||
:doc:`Part 8: Adding third-party packages <intro/tutorial08>`
|
||||
:doc:`Part 1: Requests and responses </intro/tutorial01>` |
|
||||
:doc:`Part 2: Models and the admin site </intro/tutorial02>` |
|
||||
:doc:`Part 3: Views and templates </intro/tutorial03>` |
|
||||
:doc:`Part 4: Forms and generic views </intro/tutorial04>` |
|
||||
:doc:`Part 5: Testing </intro/tutorial05>` |
|
||||
:doc:`Part 6: Static files </intro/tutorial06>` |
|
||||
:doc:`Part 7: Customizing the admin site </intro/tutorial07>` |
|
||||
:doc:`Part 8: Adding third-party packages </intro/tutorial08>`
|
||||
|
||||
* **Advanced Tutorials:**
|
||||
:doc:`How to write reusable apps <intro/reusable-apps>` |
|
||||
:doc:`Writing your first contribution to Django <intro/contributing>`
|
||||
:doc:`How to write reusable apps </intro/reusable-apps>` |
|
||||
:doc:`Writing your first contribution to Django </intro/contributing>`
|
||||
|
||||
Getting help
|
||||
============
|
||||
|
||||
Having trouble? We'd like to help!
|
||||
|
||||
* Try the :doc:`FAQ <faq/index>` -- it's got answers to many common questions.
|
||||
* Try the :doc:`FAQ </faq/index>` -- it's got answers to many common questions.
|
||||
|
||||
* Looking for specific information? Try the :ref:`genindex`, :ref:`modindex` or
|
||||
the :doc:`detailed table of contents <contents>`.
|
||||
the :doc:`detailed table of contents </contents>`.
|
||||
|
||||
* Not found anything? See :doc:`faq/help` for information on getting support
|
||||
* Not found anything? See :doc:`/faq/help` for information on getting support
|
||||
and asking questions to the community.
|
||||
|
||||
* Report bugs with Django in our `ticket tracker`_.
|
||||
|
@ -74,46 +74,46 @@ Django provides an abstraction layer (the "models") for structuring and
|
|||
manipulating the data of your web application. Learn more about it below:
|
||||
|
||||
* **Models:**
|
||||
:doc:`Introduction to models <topics/db/models>` |
|
||||
:doc:`Field types <ref/models/fields>` |
|
||||
:doc:`Indexes <ref/models/indexes>` |
|
||||
:doc:`Meta options <ref/models/options>` |
|
||||
:doc:`Model class <ref/models/class>`
|
||||
:doc:`Introduction to models </topics/db/models>` |
|
||||
:doc:`Field types </ref/models/fields>` |
|
||||
:doc:`Indexes </ref/models/indexes>` |
|
||||
:doc:`Meta options </ref/models/options>` |
|
||||
:doc:`Model class </ref/models/class>`
|
||||
|
||||
* **QuerySets:**
|
||||
:doc:`Making queries <topics/db/queries>` |
|
||||
:doc:`QuerySet method reference <ref/models/querysets>` |
|
||||
:doc:`Lookup expressions <ref/models/lookups>`
|
||||
:doc:`Making queries </topics/db/queries>` |
|
||||
:doc:`QuerySet method reference </ref/models/querysets>` |
|
||||
:doc:`Lookup expressions </ref/models/lookups>`
|
||||
|
||||
* **Model instances:**
|
||||
:doc:`Instance methods <ref/models/instances>` |
|
||||
:doc:`Accessing related objects <ref/models/relations>`
|
||||
:doc:`Instance methods </ref/models/instances>` |
|
||||
:doc:`Accessing related objects </ref/models/relations>`
|
||||
|
||||
* **Migrations:**
|
||||
:doc:`Introduction to Migrations<topics/migrations>` |
|
||||
:doc:`Operations reference <ref/migration-operations>` |
|
||||
:doc:`SchemaEditor <ref/schema-editor>` |
|
||||
:doc:`Writing migrations <howto/writing-migrations>`
|
||||
:doc:`Introduction to Migrations</topics/migrations>` |
|
||||
:doc:`Operations reference </ref/migration-operations>` |
|
||||
:doc:`SchemaEditor </ref/schema-editor>` |
|
||||
:doc:`Writing migrations </howto/writing-migrations>`
|
||||
|
||||
* **Advanced:**
|
||||
:doc:`Managers <topics/db/managers>` |
|
||||
:doc:`Raw SQL <topics/db/sql>` |
|
||||
:doc:`Transactions <topics/db/transactions>` |
|
||||
:doc:`Aggregation <topics/db/aggregation>` |
|
||||
:doc:`Search <topics/db/search>` |
|
||||
:doc:`Custom fields <howto/custom-model-fields>` |
|
||||
:doc:`Multiple databases <topics/db/multi-db>` |
|
||||
:doc:`Custom lookups <howto/custom-lookups>` |
|
||||
:doc:`Query Expressions <ref/models/expressions>` |
|
||||
:doc:`Conditional Expressions <ref/models/conditional-expressions>` |
|
||||
:doc:`Database Functions <ref/models/database-functions>`
|
||||
:doc:`Managers </topics/db/managers>` |
|
||||
:doc:`Raw SQL </topics/db/sql>` |
|
||||
:doc:`Transactions </topics/db/transactions>` |
|
||||
:doc:`Aggregation </topics/db/aggregation>` |
|
||||
:doc:`Search </topics/db/search>` |
|
||||
:doc:`Custom fields </howto/custom-model-fields>` |
|
||||
:doc:`Multiple databases </topics/db/multi-db>` |
|
||||
:doc:`Custom lookups </howto/custom-lookups>` |
|
||||
:doc:`Query Expressions </ref/models/expressions>` |
|
||||
:doc:`Conditional Expressions </ref/models/conditional-expressions>` |
|
||||
:doc:`Database Functions </ref/models/database-functions>`
|
||||
|
||||
* **Other:**
|
||||
:doc:`Supported databases <ref/databases>` |
|
||||
:doc:`Legacy databases <howto/legacy-databases>` |
|
||||
:doc:`Providing initial data <howto/initial-data>` |
|
||||
:doc:`Optimize database access <topics/db/optimization>` |
|
||||
:doc:`PostgreSQL specific features <ref/contrib/postgres/index>`
|
||||
:doc:`Supported databases </ref/databases>` |
|
||||
:doc:`Legacy databases </howto/legacy-databases>` |
|
||||
:doc:`Providing initial data </howto/initial-data>` |
|
||||
:doc:`Optimize database access </topics/db/optimization>` |
|
||||
:doc:`PostgreSQL specific features </ref/contrib/postgres/index>`
|
||||
|
||||
The view layer
|
||||
==============
|
||||
|
@ -123,39 +123,39 @@ processing a user's request and for returning the response. Find all you need
|
|||
to know about views via the links below:
|
||||
|
||||
* **The basics:**
|
||||
:doc:`URLconfs <topics/http/urls>` |
|
||||
:doc:`View functions <topics/http/views>` |
|
||||
:doc:`Shortcuts <topics/http/shortcuts>` |
|
||||
:doc:`Decorators <topics/http/decorators>` |
|
||||
:doc:`Asynchronous Support <topics/async>`
|
||||
:doc:`URLconfs </topics/http/urls>` |
|
||||
:doc:`View functions </topics/http/views>` |
|
||||
:doc:`Shortcuts </topics/http/shortcuts>` |
|
||||
:doc:`Decorators </topics/http/decorators>` |
|
||||
:doc:`Asynchronous Support </topics/async>`
|
||||
|
||||
* **Reference:**
|
||||
:doc:`Built-in Views <ref/views>` |
|
||||
:doc:`Request/response objects <ref/request-response>` |
|
||||
:doc:`TemplateResponse objects <ref/template-response>`
|
||||
:doc:`Built-in Views </ref/views>` |
|
||||
:doc:`Request/response objects </ref/request-response>` |
|
||||
:doc:`TemplateResponse objects </ref/template-response>`
|
||||
|
||||
* **File uploads:**
|
||||
:doc:`Overview <topics/http/file-uploads>` |
|
||||
:doc:`File objects <ref/files/file>` |
|
||||
:doc:`Storage API <ref/files/storage>` |
|
||||
:doc:`Managing files <topics/files>` |
|
||||
:doc:`Custom storage <howto/custom-file-storage>`
|
||||
:doc:`Overview </topics/http/file-uploads>` |
|
||||
:doc:`File objects </ref/files/file>` |
|
||||
:doc:`Storage API </ref/files/storage>` |
|
||||
:doc:`Managing files </topics/files>` |
|
||||
:doc:`Custom storage </howto/custom-file-storage>`
|
||||
|
||||
* **Class-based views:**
|
||||
:doc:`Overview <topics/class-based-views/index>` |
|
||||
:doc:`Built-in display views <topics/class-based-views/generic-display>` |
|
||||
:doc:`Built-in editing views <topics/class-based-views/generic-editing>` |
|
||||
:doc:`Using mixins <topics/class-based-views/mixins>` |
|
||||
:doc:`API reference <ref/class-based-views/index>` |
|
||||
:doc:`Flattened index<ref/class-based-views/flattened-index>`
|
||||
:doc:`Overview </topics/class-based-views/index>` |
|
||||
:doc:`Built-in display views </topics/class-based-views/generic-display>` |
|
||||
:doc:`Built-in editing views </topics/class-based-views/generic-editing>` |
|
||||
:doc:`Using mixins </topics/class-based-views/mixins>` |
|
||||
:doc:`API reference </ref/class-based-views/index>` |
|
||||
:doc:`Flattened index </ref/class-based-views/flattened-index>`
|
||||
|
||||
* **Advanced:**
|
||||
:doc:`Generating CSV <howto/outputting-csv>` |
|
||||
:doc:`Generating PDF <howto/outputting-pdf>`
|
||||
:doc:`Generating CSV </howto/outputting-csv>` |
|
||||
:doc:`Generating PDF </howto/outputting-pdf>`
|
||||
|
||||
* **Middleware:**
|
||||
:doc:`Overview <topics/http/middleware>` |
|
||||
:doc:`Built-in middleware classes <ref/middleware>`
|
||||
:doc:`Overview </topics/http/middleware>` |
|
||||
:doc:`Built-in middleware classes </ref/middleware>`
|
||||
|
||||
The template layer
|
||||
==================
|
||||
|
@ -165,17 +165,17 @@ information to be presented to the user. Learn how this syntax can be used by
|
|||
designers and how it can be extended by programmers:
|
||||
|
||||
* **The basics:**
|
||||
:doc:`Overview <topics/templates>`
|
||||
:doc:`Overview </topics/templates>`
|
||||
|
||||
* **For designers:**
|
||||
:doc:`Language overview <ref/templates/language>` |
|
||||
:doc:`Built-in tags and filters <ref/templates/builtins>` |
|
||||
:doc:`Humanization <ref/contrib/humanize>`
|
||||
:doc:`Language overview </ref/templates/language>` |
|
||||
:doc:`Built-in tags and filters </ref/templates/builtins>` |
|
||||
:doc:`Humanization </ref/contrib/humanize>`
|
||||
|
||||
* **For programmers:**
|
||||
:doc:`Template API <ref/templates/api>` |
|
||||
:doc:`Custom tags and filters <howto/custom-template-tags>` |
|
||||
:doc:`Custom template backend <howto/custom-template-backend>`
|
||||
:doc:`Template API </ref/templates/api>` |
|
||||
:doc:`Custom tags and filters </howto/custom-template-tags>` |
|
||||
:doc:`Custom template backend </howto/custom-template-backend>`
|
||||
|
||||
Forms
|
||||
=====
|
||||
|
@ -184,16 +184,16 @@ Django provides a rich framework to facilitate the creation of forms and the
|
|||
manipulation of form data.
|
||||
|
||||
* **The basics:**
|
||||
:doc:`Overview <topics/forms/index>` |
|
||||
:doc:`Form API <ref/forms/api>` |
|
||||
:doc:`Built-in fields <ref/forms/fields>` |
|
||||
:doc:`Built-in widgets <ref/forms/widgets>`
|
||||
:doc:`Overview </topics/forms/index>` |
|
||||
:doc:`Form API </ref/forms/api>` |
|
||||
:doc:`Built-in fields </ref/forms/fields>` |
|
||||
:doc:`Built-in widgets </ref/forms/widgets>`
|
||||
|
||||
* **Advanced:**
|
||||
:doc:`Forms for models <topics/forms/modelforms>` |
|
||||
:doc:`Integrating media <topics/forms/media>` |
|
||||
:doc:`Formsets <topics/forms/formsets>` |
|
||||
:doc:`Customizing validation <ref/forms/validation>`
|
||||
:doc:`Forms for models </topics/forms/modelforms>` |
|
||||
:doc:`Integrating media </topics/forms/media>` |
|
||||
:doc:`Formsets </topics/forms/formsets>` |
|
||||
:doc:`Customizing validation </ref/forms/validation>`
|
||||
|
||||
The development process
|
||||
=======================
|
||||
|
@ -202,32 +202,32 @@ Learn about the various components and tools to help you in the development and
|
|||
testing of Django applications:
|
||||
|
||||
* **Settings:**
|
||||
:doc:`Overview <topics/settings>` |
|
||||
:doc:`Full list of settings <ref/settings>`
|
||||
:doc:`Overview </topics/settings>` |
|
||||
:doc:`Full list of settings </ref/settings>`
|
||||
|
||||
* **Applications:**
|
||||
:doc:`Overview <ref/applications>`
|
||||
:doc:`Overview </ref/applications>`
|
||||
|
||||
* **Exceptions:**
|
||||
:doc:`Overview <ref/exceptions>`
|
||||
:doc:`Overview </ref/exceptions>`
|
||||
|
||||
* **django-admin and manage.py:**
|
||||
:doc:`Overview <ref/django-admin>` |
|
||||
:doc:`Adding custom commands <howto/custom-management-commands>`
|
||||
:doc:`Overview </ref/django-admin>` |
|
||||
:doc:`Adding custom commands </howto/custom-management-commands>`
|
||||
|
||||
* **Testing:**
|
||||
:doc:`Introduction <topics/testing/index>` |
|
||||
:doc:`Writing and running tests <topics/testing/overview>` |
|
||||
:doc:`Included testing tools <topics/testing/tools>` |
|
||||
:doc:`Advanced topics <topics/testing/advanced>`
|
||||
:doc:`Introduction </topics/testing/index>` |
|
||||
:doc:`Writing and running tests </topics/testing/overview>` |
|
||||
:doc:`Included testing tools </topics/testing/tools>` |
|
||||
:doc:`Advanced topics </topics/testing/advanced>`
|
||||
|
||||
* **Deployment:**
|
||||
:doc:`Overview <howto/deployment/index>` |
|
||||
:doc:`WSGI servers <howto/deployment/wsgi/index>` |
|
||||
:doc:`ASGI servers <howto/deployment/asgi/index>` |
|
||||
:doc:`Deploying static files <howto/static-files/deployment>` |
|
||||
:doc:`Tracking code errors by email <howto/error-reporting>` |
|
||||
:doc:`Deployment checklist <howto/deployment/checklist>`
|
||||
:doc:`Overview </howto/deployment/index>` |
|
||||
:doc:`WSGI servers </howto/deployment/wsgi/index>` |
|
||||
:doc:`ASGI servers </howto/deployment/asgi/index>` |
|
||||
:doc:`Deploying static files </howto/static-files/deployment>` |
|
||||
:doc:`Tracking code errors by email </howto/error-reporting>` |
|
||||
:doc:`Deployment checklist </howto/deployment/checklist>`
|
||||
|
||||
The admin
|
||||
=========
|
||||
|
@ -235,9 +235,9 @@ The admin
|
|||
Find all you need to know about the automated admin interface, one of Django's
|
||||
most popular features:
|
||||
|
||||
* :doc:`Admin site <ref/contrib/admin/index>`
|
||||
* :doc:`Admin actions <ref/contrib/admin/actions>`
|
||||
* :doc:`Admin documentation generator<ref/contrib/admin/admindocs>`
|
||||
* :doc:`Admin site </ref/contrib/admin/index>`
|
||||
* :doc:`Admin actions </ref/contrib/admin/actions>`
|
||||
* :doc:`Admin documentation generator </ref/contrib/admin/admindocs>`
|
||||
|
||||
Security
|
||||
========
|
||||
|
@ -245,13 +245,13 @@ Security
|
|||
Security is a topic of paramount importance in the development of web
|
||||
applications and Django provides multiple protection tools and mechanisms:
|
||||
|
||||
* :doc:`Security overview <topics/security>`
|
||||
* :doc:`Disclosed security issues in Django <releases/security>`
|
||||
* :doc:`Clickjacking protection <ref/clickjacking>`
|
||||
* :doc:`Cross Site Request Forgery protection <ref/csrf>`
|
||||
* :doc:`Cryptographic signing <topics/signing>`
|
||||
* :doc:`Security overview </topics/security>`
|
||||
* :doc:`Disclosed security issues in Django </releases/security>`
|
||||
* :doc:`Clickjacking protection </ref/clickjacking>`
|
||||
* :doc:`Cross Site Request Forgery protection </ref/csrf>`
|
||||
* :doc:`Cryptographic signing </topics/signing>`
|
||||
* :ref:`Security Middleware <security-middleware>`
|
||||
* :doc:`Content Security Policy <ref/csp>`
|
||||
* :doc:`Content Security Policy </ref/csp>`
|
||||
|
||||
Internationalization and localization
|
||||
=====================================
|
||||
|
@ -260,10 +260,10 @@ Django offers a robust internationalization and localization framework to
|
|||
assist you in the development of applications for multiple languages and world
|
||||
regions:
|
||||
|
||||
* :doc:`Overview <topics/i18n/index>` |
|
||||
:doc:`Internationalization <topics/i18n/translation>` |
|
||||
* :doc:`Overview </topics/i18n/index>` |
|
||||
:doc:`Internationalization </topics/i18n/translation>` |
|
||||
:ref:`Localization <how-to-create-language-files>` |
|
||||
:doc:`Localized web UI formatting and form input <topics/i18n/formatting>`
|
||||
:doc:`Localized web UI formatting and form input </topics/i18n/formatting>`
|
||||
* :doc:`Time zones </topics/i18n/timezones>`
|
||||
|
||||
Performance and optimization
|
||||
|
@ -272,14 +272,14 @@ Performance and optimization
|
|||
There are a variety of techniques and tools that can help get your code running
|
||||
more efficiently - faster, and using fewer system resources.
|
||||
|
||||
* :doc:`Performance and optimization overview <topics/performance>`
|
||||
* :doc:`Performance and optimization overview </topics/performance>`
|
||||
|
||||
Geographic framework
|
||||
====================
|
||||
|
||||
:doc:`GeoDjango <ref/contrib/gis/index>` intends to be a world-class geographic
|
||||
web framework. Its goal is to make it as easy as possible to build GIS web
|
||||
applications and harness the power of spatially enabled data.
|
||||
:doc:`GeoDjango </ref/contrib/gis/index>` intends to be a world-class
|
||||
geographic web framework. Its goal is to make it as easy as possible to build
|
||||
GIS web applications and harness the power of spatially enabled data.
|
||||
|
||||
Common web application tools
|
||||
============================
|
||||
|
@ -288,36 +288,36 @@ Django offers multiple tools commonly needed in the development of web
|
|||
applications:
|
||||
|
||||
* **Authentication:**
|
||||
:doc:`Overview <topics/auth/index>` |
|
||||
:doc:`Using the authentication system <topics/auth/default>` |
|
||||
:doc:`Password management <topics/auth/passwords>` |
|
||||
:doc:`Customizing authentication <topics/auth/customizing>` |
|
||||
:doc:`API Reference <ref/contrib/auth>`
|
||||
* :doc:`Caching <topics/cache>`
|
||||
* :doc:`Logging <topics/logging>`
|
||||
* :doc:`Sending emails <topics/email>`
|
||||
* :doc:`Syndication feeds (RSS/Atom) <ref/contrib/syndication>`
|
||||
* :doc:`Pagination <topics/pagination>`
|
||||
* :doc:`Messages framework <ref/contrib/messages>`
|
||||
* :doc:`Serialization <topics/serialization>`
|
||||
* :doc:`Sessions <topics/http/sessions>`
|
||||
* :doc:`Sitemaps <ref/contrib/sitemaps>`
|
||||
* :doc:`Static files management <ref/contrib/staticfiles>`
|
||||
* :doc:`Data validation <ref/validators>`
|
||||
:doc:`Overview </topics/auth/index>` |
|
||||
:doc:`Using the authentication system </topics/auth/default>` |
|
||||
:doc:`Password management </topics/auth/passwords>` |
|
||||
:doc:`Customizing authentication </topics/auth/customizing>` |
|
||||
:doc:`API Reference </ref/contrib/auth>`
|
||||
* :doc:`Caching </topics/cache>`
|
||||
* :doc:`Logging </topics/logging>`
|
||||
* :doc:`Sending emails </topics/email>`
|
||||
* :doc:`Syndication feeds (RSS/Atom) </ref/contrib/syndication>`
|
||||
* :doc:`Pagination </topics/pagination>`
|
||||
* :doc:`Messages framework </ref/contrib/messages>`
|
||||
* :doc:`Serialization </topics/serialization>`
|
||||
* :doc:`Sessions </topics/http/sessions>`
|
||||
* :doc:`Sitemaps </ref/contrib/sitemaps>`
|
||||
* :doc:`Static files management </ref/contrib/staticfiles>`
|
||||
* :doc:`Data validation </ref/validators>`
|
||||
|
||||
Other core functionalities
|
||||
==========================
|
||||
|
||||
Learn about some other core functionalities of the Django framework:
|
||||
|
||||
* :doc:`Conditional content processing <topics/conditional-view-processing>`
|
||||
* :doc:`Content types and generic relations <ref/contrib/contenttypes>`
|
||||
* :doc:`Flatpages <ref/contrib/flatpages>`
|
||||
* :doc:`Redirects <ref/contrib/redirects>`
|
||||
* :doc:`Signals <topics/signals>`
|
||||
* :doc:`System check framework <topics/checks>`
|
||||
* :doc:`The sites framework <ref/contrib/sites>`
|
||||
* :doc:`Unicode in Django <ref/unicode>`
|
||||
* :doc:`Conditional content processing </topics/conditional-view-processing>`
|
||||
* :doc:`Content types and generic relations </ref/contrib/contenttypes>`
|
||||
* :doc:`Flatpages </ref/contrib/flatpages>`
|
||||
* :doc:`Redirects </ref/contrib/redirects>`
|
||||
* :doc:`Signals </topics/signals>`
|
||||
* :doc:`System check framework </topics/checks>`
|
||||
* :doc:`The sites framework </ref/contrib/sites>`
|
||||
* :doc:`Unicode in Django </ref/unicode>`
|
||||
|
||||
The Django open-source project
|
||||
==============================
|
||||
|
@ -326,23 +326,23 @@ Learn about the development process for the Django project itself and about how
|
|||
you can contribute:
|
||||
|
||||
* **Community:**
|
||||
:doc:`Contributing to Django <internals/contributing/index>` |
|
||||
:doc:`The release process <internals/release-process>` |
|
||||
:doc:`Team organization <internals/organization>` |
|
||||
:doc:`The Django source code repository <internals/git>` |
|
||||
:doc:`Security policies <internals/security>` |
|
||||
:doc:`Mailing lists and Forum<internals/mailing-lists>`
|
||||
:doc:`Contributing to Django </internals/contributing/index>` |
|
||||
:doc:`The release process </internals/release-process>` |
|
||||
:doc:`Team organization </internals/organization>` |
|
||||
:doc:`The Django source code repository </internals/git>` |
|
||||
:doc:`Security policies </internals/security>` |
|
||||
:doc:`Mailing lists and Forum </internals/mailing-lists>`
|
||||
|
||||
* **Design philosophies:**
|
||||
:doc:`Overview <misc/design-philosophies>`
|
||||
:doc:`Overview </misc/design-philosophies>`
|
||||
|
||||
* **Documentation:**
|
||||
:doc:`About this documentation <internals/contributing/writing-documentation>`
|
||||
:doc:`About this documentation </internals/contributing/writing-documentation>`
|
||||
|
||||
* **Third-party distributions:**
|
||||
:doc:`Overview <misc/distributions>`
|
||||
:doc:`Overview </misc/distributions>`
|
||||
|
||||
* **Django over time:**
|
||||
:doc:`API stability <misc/api-stability>` |
|
||||
:doc:`Release notes and upgrading instructions <releases/index>` |
|
||||
:doc:`Deprecation Timeline <internals/deprecation>`
|
||||
:doc:`API stability </misc/api-stability>` |
|
||||
:doc:`Release notes and upgrading instructions </releases/index>` |
|
||||
:doc:`Deprecation Timeline </internals/deprecation>`
|
||||
|
|
|
@ -55,7 +55,7 @@ particular:
|
|||
as they are filed.
|
||||
|
||||
To understand the lifecycle of your ticket once you have created it, refer to
|
||||
:doc:`triaging-tickets`.
|
||||
:ref:`triage-workflow`.
|
||||
|
||||
Reporting user interface bugs
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
|
|
@ -4,8 +4,8 @@ Committing code
|
|||
|
||||
This section is addressed to the mergers and to anyone interested in knowing
|
||||
how code gets committed into Django. If you're a community member who wants to
|
||||
contribute code to Django, look at :doc:`writing-code/working-with-git`
|
||||
instead.
|
||||
contribute code to Django, look at
|
||||
:doc:`/internals/contributing/writing-code/working-with-git` instead.
|
||||
|
||||
.. _handling-pull-requests:
|
||||
|
||||
|
|
|
@ -61,8 +61,8 @@ the date, time and numbers formatting particularities of your locale. See
|
|||
The format files aren't managed by the use of Transifex. To change them, you
|
||||
must:
|
||||
|
||||
* :doc:`Create a pull request<writing-code/submitting-patches>` against the
|
||||
Django Git ``main`` branch, as for any code change.
|
||||
* :ref:`Create a pull request <patch-review-checklist>` against the Django Git
|
||||
``main`` branch, as for any code change.
|
||||
|
||||
* Open a ticket in Django's ticket system, set its ``Component`` field to
|
||||
``Translations``, set the "has patch" flag, and include the link to the pull
|
||||
|
|
|
@ -47,14 +47,15 @@ Keep old patches up-to-date
|
|||
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
|
||||
expected. Updating a patch is both useful and important! See more on
|
||||
:doc:`writing-code/submitting-patches`.
|
||||
:ref:`patch-review-checklist`.
|
||||
|
||||
Write some documentation
|
||||
------------------------
|
||||
|
||||
Django's documentation is great but it can always be improved. Did you find a
|
||||
typo? Do you think that something should be clarified? Go ahead and suggest a
|
||||
documentation patch! See also the guide on :doc:`writing-documentation`.
|
||||
documentation patch! See also the guide on
|
||||
:doc:`/internals/contributing/writing-documentation`.
|
||||
|
||||
.. note::
|
||||
|
||||
|
|
|
@ -29,11 +29,13 @@ confusion or disagreement.
|
|||
Django is a community project, and every contribution helps. We can't do this
|
||||
without **you**!
|
||||
|
||||
.. _triage-workflow:
|
||||
|
||||
Triage workflow
|
||||
===============
|
||||
|
||||
Unfortunately, not all reports in the ticket tracker provide all the
|
||||
:doc:`required details<bugs-and-features>`. A number of tickets have proposed
|
||||
:ref:`required details <reporting-bugs>`. A number of tickets have proposed
|
||||
solutions, but those don't necessarily meet all the requirements :ref:`adhering
|
||||
to the guidelines for contributing <patch-style>`.
|
||||
|
||||
|
@ -168,8 +170,8 @@ Has patch
|
|||
---------
|
||||
|
||||
This means the ticket has an associated solution. These will be reviewed to
|
||||
ensure they adhere to the :doc:`documented guidelines
|
||||
<writing-code/submitting-patches>`.
|
||||
ensure they adhere to the :ref:`documented guidelines
|
||||
<patch-review-checklist>`.
|
||||
|
||||
The following three fields (Needs documentation, Needs tests,
|
||||
Patch needs improvement) apply only if a patch has been supplied.
|
||||
|
@ -234,8 +236,11 @@ majority of tickets have a severity of "Normal".
|
|||
Version
|
||||
-------
|
||||
|
||||
It is possible to use the *version* attribute to indicate in which
|
||||
version the reported bug was identified.
|
||||
The *version* attribute indicates the earliest version in which the bug was
|
||||
reproduced. During triage, this field can be updated, but there is no need to
|
||||
make further updates when that version goes out of support. The field should
|
||||
not be reset to "dev" to show the issue still exists: instead, the tested
|
||||
commit hash can be noted in a comment.
|
||||
|
||||
UI/UX
|
||||
-----
|
||||
|
@ -350,8 +355,7 @@ Then, you can help out by:
|
|||
"wontfix".
|
||||
|
||||
* Closing "Unreviewed" tickets as "needsinfo" when the description is too
|
||||
sparse to be actionable, or when they're feature requests requiring a
|
||||
discussion on the `Django Forum`_.
|
||||
sparse to be actionable.
|
||||
|
||||
* Correcting the "Needs tests", "Needs documentation", or "Has patch"
|
||||
flags for tickets where they are incorrectly set.
|
||||
|
@ -383,7 +387,7 @@ Then, you can help out by:
|
|||
several that are useful for triaging tickets and reviewing proposals as
|
||||
suggested above.
|
||||
|
||||
You can also find more :doc:`new-contributors`.
|
||||
You can also find more :doc:`/internals/contributing/new-contributors`.
|
||||
|
||||
.. _Reports page: https://code.djangoproject.com/wiki/Reports
|
||||
|
||||
|
|
|
@ -56,8 +56,8 @@ Python style
|
|||
These limits are checked when ``flake8`` is run.
|
||||
|
||||
* String variable interpolation may use
|
||||
:py:ref:`%-formatting <old-string-formatting>`, :py:ref:`f-strings
|
||||
<f-strings>`, or :py:meth:`str.format` as appropriate, with the goal of
|
||||
:ref:`%-formatting <old-string-formatting>`, :ref:`f-strings
|
||||
<f-strings>`, or :meth:`str.format` as appropriate, with the goal of
|
||||
maximizing code readability.
|
||||
|
||||
Final judgments of readability are left to the Merger's discretion. As a
|
||||
|
@ -504,6 +504,6 @@ JavaScript style
|
|||
================
|
||||
|
||||
For details about the JavaScript code style used by Django, see
|
||||
:doc:`javascript`.
|
||||
:doc:`/internals/contributing/writing-code/javascript`.
|
||||
|
||||
.. _editorconfig: https://editorconfig.org/
|
||||
|
|
|
@ -15,7 +15,8 @@ If you are fixing a really trivial issue, for example changing a word in the
|
|||
documentation, the preferred way to provide the patch is using GitHub pull
|
||||
requests without a Trac ticket.
|
||||
|
||||
See the :doc:`working-with-git` for more details on how to use pull requests.
|
||||
See the :doc:`/internals/contributing/writing-code/working-with-git` for more
|
||||
details on how to use pull requests.
|
||||
|
||||
"Claiming" tickets
|
||||
==================
|
||||
|
@ -109,19 +110,20 @@ requirements:
|
|||
|
||||
* The code required to fix a problem or add a feature is an essential part
|
||||
of a solution, but it is not the only part. A good fix should also include a
|
||||
:doc:`regression test <unit-tests>` to validate the behavior that has been
|
||||
fixed and to prevent the problem from arising again. Also, if some tickets
|
||||
are relevant to the code that you've written, mention the ticket numbers in
|
||||
some comments in the test so that one can easily trace back the relevant
|
||||
discussions after your patch gets committed, and the tickets get closed.
|
||||
:doc:`regression test </internals/contributing/writing-code/unit-tests>` to
|
||||
validate the behavior that has been fixed and to prevent the problem from
|
||||
arising again. Also, if some tickets are relevant to the code that you've
|
||||
written, mention the ticket numbers in some comments in the test so that one
|
||||
can easily trace back the relevant discussions after your patch gets
|
||||
committed, and the tickets get closed.
|
||||
|
||||
* If the code adds a new feature, or modifies the behavior of an existing
|
||||
feature, the change should also contain documentation.
|
||||
|
||||
When you think your work is ready to be reviewed, send :doc:`a GitHub pull
|
||||
request <working-with-git>`.
|
||||
If you can't send a pull request for some reason, you can also use patches in
|
||||
Trac. When using this style, follow these guidelines.
|
||||
request </internals/contributing/writing-code/working-with-git>`. If you can't
|
||||
send a pull request for some reason, you can also use patches in Trac. When
|
||||
using this style, follow these guidelines.
|
||||
|
||||
* Submit patches in the format returned by the ``git diff`` command.
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ Working with Git and GitHub
|
|||
|
||||
This section explains how the community can contribute code to Django via pull
|
||||
requests. If you're interested in how :ref:`mergers <mergers-team>` handle
|
||||
them, see :doc:`../committing-code`.
|
||||
them, see :ref:`handling-pull-requests`.
|
||||
|
||||
Below, we are going to show how to create a GitHub pull request containing the
|
||||
changes for Trac ticket #xxxxx. By creating a fully-ready pull request, you
|
||||
|
@ -142,7 +142,7 @@ When you think your work is ready to be pulled into Django, you should create
|
|||
a pull request at GitHub. A good pull request means:
|
||||
|
||||
* commits with one logical change in each, following the
|
||||
:doc:`coding style <coding-style>`,
|
||||
:doc:`coding style </internals/contributing/writing-code/coding-style>`,
|
||||
|
||||
* well-formed messages for each commit: a summary line and then paragraphs
|
||||
wrapped at 72 characters thereafter -- see the :ref:`committing guidelines
|
||||
|
|
|
@ -53,8 +53,6 @@ details on these changes.
|
|||
* The ``django.core.mail.forbid_multi_line_headers()`` and
|
||||
``django.core.mail.message.sanitize_address()`` functions will be removed.
|
||||
|
||||
* The ``django.utils.crypto.constant_time_compare()`` function will be removed.
|
||||
|
||||
.. _deprecation-removed-in-6.1:
|
||||
|
||||
6.1
|
||||
|
@ -744,8 +742,8 @@ details on these changes.
|
|||
* The ability to use a dotted Python path for the ``LOGIN_URL`` and
|
||||
``LOGIN_REDIRECT_URL`` settings will be removed.
|
||||
|
||||
* Support for :py:mod:`optparse` will be dropped for custom management commands
|
||||
(replaced by :py:mod:`argparse`).
|
||||
* Support for :mod:`optparse` will be dropped for custom management commands
|
||||
(replaced by :mod:`argparse`).
|
||||
|
||||
* The class ``django.core.management.NoArgsCommand`` will be removed. Use
|
||||
:class:`~django.core.management.BaseCommand` instead, which takes no
|
||||
|
|
|
@ -31,7 +31,8 @@ own branch, called ``stable/A.B.x``, and bugfix/security releases will be
|
|||
issued from those branches.
|
||||
|
||||
For more information about how the Django project issues new releases for
|
||||
security purposes, please see :doc:`our security policies <security>`.
|
||||
security purposes, please see :doc:`our security policies
|
||||
</internals/security>`.
|
||||
|
||||
.. glossary::
|
||||
|
||||
|
|
40
docs/lint.py
40
docs/lint.py
|
@ -5,14 +5,16 @@ from os.path import abspath, dirname, splitext
|
|||
from unittest import mock
|
||||
|
||||
from sphinxlint.checkers import (
|
||||
_ROLE_BODY,
|
||||
_is_long_interpreted_text,
|
||||
_is_very_long_string_literal,
|
||||
_starts_with_anonymous_hyperlink,
|
||||
_starts_with_directive_or_hyperlink,
|
||||
)
|
||||
from sphinxlint.checkers import checker as sphinxlint_checker
|
||||
from sphinxlint.rst import SIMPLENAME
|
||||
from sphinxlint.sphinxlint import check_text
|
||||
from sphinxlint.utils import PER_FILE_CACHES, hide_non_rst_blocks
|
||||
from sphinxlint.utils import PER_FILE_CACHES, hide_non_rst_blocks, paragraphs
|
||||
|
||||
|
||||
def django_check_file(filename, checkers, options=None):
|
||||
|
@ -94,7 +96,7 @@ def check_line_too_long_django(file, lines, options=None):
|
|||
continue
|
||||
except IndexError:
|
||||
# End of file
|
||||
continue
|
||||
pass
|
||||
if len(set(line.strip())) == 1 and len(line) == len(lines[lno - 1]):
|
||||
continue # Ignore heading underline
|
||||
if lno in table_rows:
|
||||
|
@ -116,6 +118,40 @@ def check_line_too_long_django(file, lines, options=None):
|
|||
yield lno + 1, f"Line too long ({len(line) - 1}/{options.max_line_length})"
|
||||
|
||||
|
||||
_PYTHON_DOMAIN = re.compile(f":py:{SIMPLENAME}:`{_ROLE_BODY}`")
|
||||
|
||||
|
||||
@sphinxlint_checker(".rst", enabled=False, rst_only=True)
|
||||
def check_python_domain_in_roles(file, lines, options=None):
|
||||
"""
|
||||
:py: indicates the Python language domain. This means code writen in
|
||||
Python, not Python built-ins in particular.
|
||||
|
||||
Bad: :py:class:`email.message.EmailMessage`
|
||||
Good: :class:`email.message.EmailMessage`
|
||||
"""
|
||||
for lno, line in enumerate(lines, start=1):
|
||||
role = _PYTHON_DOMAIN.search(line)
|
||||
if role:
|
||||
yield lno, f":py domain is the default and can be omitted {role.group(0)!r}"
|
||||
|
||||
|
||||
_DOC_CAPTURE_TARGET_RE = re.compile(r":doc:`(?:[^<`]+<)?([^>`]+)>?`")
|
||||
|
||||
|
||||
@sphinxlint_checker(".rst", rst_only=True)
|
||||
def check_absolute_targets_doc_role(file, lines, options=None):
|
||||
for paragraph_lno, paragraph in paragraphs(lines):
|
||||
for error in _DOC_CAPTURE_TARGET_RE.finditer(paragraph):
|
||||
target = error.group(1)
|
||||
# Skip absolute or intersphinx refs like "python:using/windows".
|
||||
if target.startswith("/") or ":" in target.split("/", 1)[0]:
|
||||
continue
|
||||
# Relative target, report as a violation.
|
||||
error_offset = paragraph[: error.start()].count("\n")
|
||||
yield (paragraph_lno + error_offset, target)
|
||||
|
||||
|
||||
import sphinxlint # noqa: E402
|
||||
|
||||
sphinxlint.check_file = django_check_file
|
||||
|
|
|
@ -1436,7 +1436,7 @@ default templates used by the :class:`ModelAdmin` views:
|
|||
The ``delete_queryset()`` method is given the ``HttpRequest`` and a
|
||||
``QuerySet`` of objects to be deleted. Override this method to customize
|
||||
the deletion process for the "delete selected objects" :doc:`action
|
||||
<actions>`.
|
||||
</ref/contrib/admin/actions>`.
|
||||
|
||||
.. method:: ModelAdmin.save_formset(request, form, formset, change)
|
||||
|
||||
|
@ -2055,7 +2055,7 @@ default templates used by the :class:`ModelAdmin` views:
|
|||
.. method:: ModelAdmin.get_deleted_objects(objs, request)
|
||||
|
||||
A hook for customizing the deletion process of the :meth:`delete_view` and
|
||||
the "delete selected" :doc:`action <actions>`.
|
||||
the "delete selected" :doc:`action </ref/contrib/admin/actions>`.
|
||||
|
||||
The ``objs`` argument is a homogeneous iterable of objects (a ``QuerySet``
|
||||
or a list of model instances) to be deleted, and ``request`` is the
|
||||
|
|
|
@ -156,7 +156,7 @@ Geometry Lookups
|
|||
----------------
|
||||
|
||||
Geographic queries with geometries take the following general form (assuming
|
||||
the ``Zipcode`` model used in the :doc:`model-api`):
|
||||
the ``Zipcode`` model used in the :doc:`/ref/contrib/gis/model-api`):
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
|
@ -192,7 +192,8 @@ used to pass a band index. On the right hand side, a tuple of the raster and
|
|||
band index can be specified.
|
||||
|
||||
This results in the following general form for lookups involving rasters
|
||||
(assuming the ``Elevation`` model used in the :doc:`model-api`):
|
||||
(assuming the ``Elevation`` model used in the
|
||||
:doc:`/ref/contrib/gis/model-api`):
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
|
@ -234,11 +235,10 @@ Distance Queries
|
|||
Introduction
|
||||
------------
|
||||
|
||||
Distance calculations with spatial data is tricky because, unfortunately,
|
||||
the Earth is not flat. Some distance queries with fields in a geographic
|
||||
coordinate system may have to be expressed differently because of
|
||||
limitations in PostGIS. Please see the :ref:`selecting-an-srid` section
|
||||
in the :doc:`model-api` documentation for more details.
|
||||
Distance calculations with spatial data is tricky because, unfortunately, the
|
||||
Earth is not flat. Some distance queries with fields in a geographic coordinate
|
||||
system may have to be expressed differently because of limitations in PostGIS.
|
||||
Please see the :ref:`selecting-an-srid` section for more details.
|
||||
|
||||
.. _distance-lookups-intro:
|
||||
|
||||
|
|
|
@ -85,7 +85,8 @@ queryset is calculated:
|
|||
express the value in the units of your choice. For example,
|
||||
``city.distance.mi`` is the distance value in miles and
|
||||
``city.distance.km`` is the distance value in kilometers. See
|
||||
:doc:`measure` for usage details and the list of :ref:`supported_units`.
|
||||
:doc:`/ref/contrib/gis/measure` for usage details and the list of
|
||||
:ref:`supported_units`.
|
||||
|
||||
``GeometryDistance``
|
||||
--------------------
|
||||
|
|
|
@ -5,6 +5,11 @@ GDAL API
|
|||
.. module:: django.contrib.gis.gdal
|
||||
:synopsis: GeoDjango's high-level interface to the GDAL library.
|
||||
|
||||
.. _gdal-overview:
|
||||
|
||||
Overview
|
||||
========
|
||||
|
||||
`GDAL`__ stands for **Geospatial Data Abstraction Library**,
|
||||
and is a veritable "Swiss army knife" of GIS data functionality. A subset
|
||||
of GDAL is the `OGR`__ Simple Features Library, which specializes
|
||||
|
@ -24,9 +29,6 @@ to raster (image) data.
|
|||
__ https://gdal.org/
|
||||
__ https://gdal.org/user/vector_data_model.html
|
||||
|
||||
Overview
|
||||
========
|
||||
|
||||
.. _gdal_sample_data:
|
||||
|
||||
Sample Data
|
||||
|
@ -43,6 +45,8 @@ data sets that you can use for testing. You can download them here:
|
|||
$ wget https://raw.githubusercontent.com/django/django/main/tests/gis_tests/data/cities/cities.{shp,prj,shx,dbf}
|
||||
$ wget https://raw.githubusercontent.com/django/django/main/tests/gis_tests/data/rasters/raster.tif
|
||||
|
||||
.. _gdal_vector_data:
|
||||
|
||||
Vector Data Source Objects
|
||||
==========================
|
||||
|
||||
|
|
|
@ -5,6 +5,11 @@ Geolocation with GeoIP2
|
|||
.. module:: django.contrib.gis.geoip2
|
||||
:synopsis: Python interface for MaxMind's GeoIP2 databases.
|
||||
|
||||
.. _geoip2-overview:
|
||||
|
||||
Overview
|
||||
========
|
||||
|
||||
The :class:`GeoIP2` object is a wrapper for the :pypi:`MaxMind geoip2 Python
|
||||
library <geoip2>`. [#]_
|
||||
|
||||
|
|
|
@ -5,6 +5,8 @@ GEOS API
|
|||
.. module:: django.contrib.gis.geos
|
||||
:synopsis: GeoDjango's high-level interface to the GEOS library.
|
||||
|
||||
.. _geos-overview:
|
||||
|
||||
Background
|
||||
==========
|
||||
|
||||
|
|
|
@ -2,19 +2,24 @@
|
|||
Installing Geospatial libraries
|
||||
===============================
|
||||
|
||||
.. _geolibs-list:
|
||||
|
||||
Geospatial libraries
|
||||
====================
|
||||
|
||||
GeoDjango uses and/or provides interfaces for the following open source
|
||||
geospatial libraries:
|
||||
|
||||
======================== ==================================== ================================ =======================================================
|
||||
Program Description Required Supported Versions
|
||||
======================== ==================================== ================================ =======================================================
|
||||
:doc:`GEOS <../geos>` Geometry Engine Open Source Yes 3.13, 3.12, 3.11, 3.10, 3.9, 3.8
|
||||
`PROJ`_ Cartographic Projections library Yes (PostgreSQL and SQLite only) 9.x, 8.x, 7.x, 6.x
|
||||
:doc:`GDAL <../gdal>` Geospatial Data Abstraction Library Yes 3.11, 3.10, 3.9, 3.8, 3.7, 3.6, 3.5, 3.4, 3.3, 3.2, 3.1
|
||||
:doc:`GeoIP <../geoip2>` IP-based geolocation library No 2
|
||||
`PostGIS`__ Spatial extensions for PostgreSQL Yes (PostgreSQL only) 3.5, 3.4, 3.3, 3.2, 3.1
|
||||
`SpatiaLite`__ Spatial extensions for SQLite Yes (SQLite only) 5.1, 5.0, 4.3
|
||||
======================== ==================================== ================================ =======================================================
|
||||
============================== ==================================== ================================ =======================================================
|
||||
Program Description Required Supported Versions
|
||||
============================== ==================================== ================================ =======================================================
|
||||
:ref:`GEOS <geos-overview>` Geometry Engine Open Source Yes 3.14, 3.13, 3.12, 3.11, 3.10, 3.9, 3.8
|
||||
`PROJ`_ Cartographic Projections library Yes (PostgreSQL and SQLite only) 9.x, 8.x, 7.x, 6.x
|
||||
:ref:`GDAL <gdal-overview>` Geospatial Data Abstraction Library Yes 3.11, 3.10, 3.9, 3.8, 3.7, 3.6, 3.5, 3.4, 3.3, 3.2, 3.1
|
||||
:ref:`GeoIP <geoip2-overview>` IP-based geolocation library No 2
|
||||
`PostGIS`__ Spatial extensions for PostgreSQL Yes (PostgreSQL only) 3.5, 3.4, 3.3, 3.2, 3.1
|
||||
`SpatiaLite`__ Spatial extensions for SQLite Yes (SQLite only) 5.1, 5.0, 4.3
|
||||
============================== ==================================== ================================ =======================================================
|
||||
|
||||
Note that older or more recent versions of these libraries *may* also work
|
||||
totally fine with GeoDjango. Your mileage may vary.
|
||||
|
@ -27,6 +32,7 @@ totally fine with GeoDjango. Your mileage may vary.
|
|||
GEOS 3.11.0 2022-07-01
|
||||
GEOS 3.12.0 2023-06-27
|
||||
GEOS 3.13.0 2024-09-06
|
||||
GEOS 3.14.0 2025-08-21
|
||||
GDAL 3.1.0 2020-05-07
|
||||
GDAL 3.2.0 2020-11-02
|
||||
GDAL 3.3.0 2021-05-03
|
||||
|
@ -234,7 +240,7 @@ GDAL
|
|||
|
||||
`GDAL`__ is an excellent open source geospatial library that has support for
|
||||
reading most vector and raster spatial data formats. Currently, GeoDjango only
|
||||
supports :doc:`GDAL's vector data <../gdal>` capabilities [#]_.
|
||||
supports :ref:`GDAL's vector data <gdal_vector_data>` capabilities [#]_.
|
||||
:ref:`geosbuild` and :ref:`proj4` should be installed prior to building GDAL.
|
||||
|
||||
First download the latest GDAL release version and untar the archive:
|
||||
|
|
|
@ -8,7 +8,7 @@ In general, GeoDjango installation requires:
|
|||
|
||||
#. :ref:`Python and Django <django>`
|
||||
#. :ref:`spatial_database`
|
||||
#. :doc:`geolibs`
|
||||
#. :ref:`geolibs-list`
|
||||
|
||||
Details for each of the requirements and installation instructions
|
||||
are provided in the sections below. In addition, platform-specific
|
||||
|
|
|
@ -22,9 +22,9 @@ familiarize yourself with Django first.
|
|||
|
||||
.. note::
|
||||
|
||||
GeoDjango has additional requirements beyond what Django requires --
|
||||
please consult the :doc:`installation documentation <install/index>`
|
||||
for more details.
|
||||
GeoDjango has additional requirements beyond what Django requires -- please
|
||||
consult the :doc:`installation documentation
|
||||
</ref/contrib/gis/install/index>` for more details.
|
||||
|
||||
This tutorial will guide you through the creation of a geographic web
|
||||
application for viewing the `world borders`_. [#]_ Some of the code
|
||||
|
@ -49,8 +49,8 @@ Create a Spatial Database
|
|||
Typically no special setup is required, so you can create a database as you
|
||||
would for any other project. We provide some tips for selected databases:
|
||||
|
||||
* :doc:`install/postgis`
|
||||
* :doc:`install/spatialite`
|
||||
* :doc:`/ref/contrib/gis/install/postgis`
|
||||
* :doc:`/ref/contrib/gis/install/spatialite`
|
||||
|
||||
Create a New Project
|
||||
--------------------
|
||||
|
@ -305,7 +305,7 @@ Importing Spatial Data
|
|||
======================
|
||||
|
||||
This section will show you how to import the world borders shapefile into the
|
||||
database via GeoDjango models using the :doc:`layermapping`.
|
||||
database via GeoDjango models using the :doc:`/ref/contrib/gis/layermapping`.
|
||||
|
||||
There are many different ways to import data into a spatial database --
|
||||
besides the tools included within GeoDjango, you may also use the following:
|
||||
|
@ -531,11 +531,13 @@ Next, import the ``load`` module, call the ``run`` routine, and watch
|
|||
|
||||
Try ``ogrinspect``
|
||||
------------------
|
||||
|
||||
Now that you've seen how to define geographic models and import data with the
|
||||
:doc:`layermapping`, it's possible to further automate this process with
|
||||
use of the :djadmin:`ogrinspect` management command. The :djadmin:`ogrinspect`
|
||||
command introspects a GDAL-supported vector data source (e.g., a shapefile)
|
||||
and generates a model definition and ``LayerMapping`` dictionary automatically.
|
||||
:doc:`/ref/contrib/gis/layermapping`, it's possible to further automate this
|
||||
process with use of the :djadmin:`ogrinspect` management command. The
|
||||
:djadmin:`ogrinspect` command introspects a GDAL-supported vector data source
|
||||
(e.g., a shapefile) and generates a model definition and ``LayerMapping``
|
||||
dictionary automatically.
|
||||
|
||||
The general usage of the command goes as follows:
|
||||
|
||||
|
@ -637,10 +639,10 @@ a ``contains`` lookup using the ``pnt_wkt`` as the parameter:
|
|||
Here, you retrieved a ``QuerySet`` with only one model: the border of the
|
||||
United States (exactly what you would expect).
|
||||
|
||||
Similarly, you may also use a :doc:`GEOS geometry object <geos>`.
|
||||
Here, you can combine the ``intersects`` spatial lookup with the ``get``
|
||||
method to retrieve only the ``WorldBorder`` instance for San Marino instead
|
||||
of a queryset:
|
||||
Similarly, you may also use a :doc:`GEOS geometry object
|
||||
</ref/contrib/gis/geos>`. Here, you can combine the ``intersects`` spatial
|
||||
lookup with the ``get`` method to retrieve only the ``WorldBorder`` instance
|
||||
for San Marino instead of a queryset:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
|
@ -649,8 +651,8 @@ of a queryset:
|
|||
>>> WorldBorder.objects.get(mpoly__intersects=pnt)
|
||||
<WorldBorder: San Marino>
|
||||
|
||||
The ``contains`` and ``intersects`` lookups are just a subset of the
|
||||
available queries -- the :doc:`db-api` documentation has more.
|
||||
The ``contains`` and ``intersects`` lookups are just a subset of the available
|
||||
queries -- the :doc:`/ref/contrib/gis/db-api` documentation has more.
|
||||
|
||||
.. _automatic-spatial-transformations:
|
||||
|
||||
|
@ -748,7 +750,7 @@ Geographic annotations
|
|||
|
||||
GeoDjango also offers a set of geographic annotations to compute distances and
|
||||
several other operations (intersection, difference, etc.). See the
|
||||
:doc:`functions` documentation.
|
||||
:doc:`/ref/contrib/gis/functions` documentation.
|
||||
|
||||
Putting your data on the map
|
||||
============================
|
||||
|
|
|
@ -492,7 +492,7 @@ This view function serves static files in development.
|
|||
.. note::
|
||||
|
||||
To guess the served files' content types, this view relies on the
|
||||
:py:mod:`mimetypes` module from the Python standard library, which itself
|
||||
:mod:`mimetypes` module from the Python standard library, which itself
|
||||
relies on the underlying platform's map files. If you find that this view
|
||||
doesn't return proper content types for certain files, it is most likely
|
||||
that the platform's map files are incorrect or need to be updated. This can
|
||||
|
|
|
@ -154,6 +154,92 @@ with the CSP specification.
|
|||
secure, random nonce that is generated for each request. See detailed
|
||||
explanation in :ref:`csp-nonce`.
|
||||
|
||||
Decorators
|
||||
==========
|
||||
|
||||
.. module:: django.views.decorators.csp
|
||||
|
||||
Django provides decorators to control the Content Security Policy headers on a
|
||||
per-view basis. These allow overriding or disabling the enforced or report-only
|
||||
policy for specific views, providing fine-grained control when the global
|
||||
settings are not sufficient. Applying these overrides fully replaces the base
|
||||
CSP: they do not merge with existing rules. They can be used alongside the
|
||||
constants defined in :class:`~django.utils.csp.CSP`.
|
||||
|
||||
.. warning::
|
||||
|
||||
Weakening or disabling a CSP policy on any page can compromise the security
|
||||
of the entire site. Because of the "same origin" policy, an attacker could
|
||||
exploit a vulnerability on one page to access other parts of the site.
|
||||
|
||||
.. function:: csp_override(config)(view)
|
||||
|
||||
Overrides the ``Content-Security-Policy`` header for the decorated view
|
||||
using directives in the same format as the :setting:`SECURE_CSP` setting.
|
||||
|
||||
The ``config`` argument must be a mapping with the desired CSP directives.
|
||||
If ``config`` is an empty mapping (``{}``), no CSP enforcement header will
|
||||
be added to the response returned by that view, effectively disabling CSP
|
||||
for that view.
|
||||
|
||||
Examples::
|
||||
|
||||
from django.http import HttpResponse
|
||||
from django.utils.csp import CSP
|
||||
from django.views.decorators.csp import csp_override
|
||||
|
||||
|
||||
@csp_override(
|
||||
{
|
||||
"default-src": [CSP.SELF],
|
||||
"img-src": [CSP.SELF, "data:"],
|
||||
}
|
||||
)
|
||||
def my_view(request):
|
||||
return HttpResponse("Custom Content-Security-Policy header applied")
|
||||
|
||||
|
||||
@csp_override({})
|
||||
def my_other_view(request):
|
||||
return HttpResponse("No Content-Security-Policy header added")
|
||||
|
||||
|
||||
.. function:: csp_report_only_override(config)(view)
|
||||
|
||||
Overrides the ``Content-Security-Policy-Report-Only`` header for the
|
||||
decorated view using directives in the same format as the
|
||||
:setting:`SECURE_CSP_REPORT_ONLY` setting.
|
||||
|
||||
Like :func:`csp_override`, the ``config`` argument must be a mapping with
|
||||
the desired CSP directives. If ``config`` is an empty mapping (``{}``), no
|
||||
CSP report-only header will be added to the response returned by that view,
|
||||
effectively disabling report-only CSP for that view.
|
||||
|
||||
Examples::
|
||||
|
||||
from django.http import HttpResponse
|
||||
from django.utils.csp import CSP
|
||||
from django.views.decorators.csp import csp_report_only_override
|
||||
|
||||
|
||||
@csp_report_only_override(
|
||||
{
|
||||
"default-src": [CSP.SELF],
|
||||
"img-src": [CSP.SELF, "data:"],
|
||||
"report-uri": "https://mysite.com/csp-report/",
|
||||
}
|
||||
)
|
||||
def my_view(request):
|
||||
return HttpResponse("Custom Content-Security-Policy-Report-Only header applied")
|
||||
|
||||
|
||||
@csp_report_only_override({})
|
||||
def my_other_view(request):
|
||||
return HttpResponse("No Content-Security-Policy-Report-Only header added")
|
||||
|
||||
The examples above assume function-based views. For class-based views, see the
|
||||
:ref:`guide for decorating class-based views <decorating-class-based-views>`.
|
||||
|
||||
.. _csp-nonce:
|
||||
|
||||
Nonce usage
|
||||
|
|
|
@ -951,7 +951,7 @@ Enabling JSON1 extension on SQLite
|
|||
----------------------------------
|
||||
|
||||
To use :class:`~django.db.models.JSONField` on SQLite, you need to enable the
|
||||
`JSON1 extension`_ on Python's :py:mod:`sqlite3` library. If the extension is
|
||||
`JSON1 extension`_ on Python's :mod:`sqlite3` library. If the extension is
|
||||
not enabled on your installation, a system error (``fields.E180``) will be
|
||||
raised.
|
||||
|
||||
|
|
|
@ -1845,7 +1845,7 @@ allows for the following options by default:
|
|||
|
||||
.. django-admin-option:: --pythonpath PYTHONPATH
|
||||
|
||||
Adds the given filesystem path to the Python :py:data:`sys.path` module
|
||||
Adds the given filesystem path to the Python :data:`sys.path` module
|
||||
attribute. If this isn't provided, ``django-admin`` will use the
|
||||
:envvar:`PYTHONPATH` environment variable.
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ The ``File`` class
|
|||
.. class:: File(file_object, name=None)
|
||||
|
||||
The :class:`File` class is a thin wrapper around a Python
|
||||
:py:term:`file object` with some Django-specific additions.
|
||||
:term:`file object` with some Django-specific additions.
|
||||
Internally, Django uses this class when it needs to represent a file.
|
||||
|
||||
:class:`File` objects have the following attributes and methods:
|
||||
|
@ -29,14 +29,14 @@ The ``File`` class
|
|||
|
||||
.. attribute:: file
|
||||
|
||||
The underlying :py:term:`file object` that this class wraps.
|
||||
The underlying :term:`file object` that this class wraps.
|
||||
|
||||
.. admonition:: Be careful with this attribute in subclasses.
|
||||
|
||||
Some subclasses of :class:`File`, including
|
||||
:class:`~django.core.files.base.ContentFile` and
|
||||
:class:`~django.db.models.fields.files.FieldFile`, may replace this
|
||||
attribute with an object other than a Python :py:term:`file
|
||||
attribute with an object other than a Python :term:`file
|
||||
object`. In these cases, this attribute may itself be a
|
||||
:class:`File` subclass (and not necessarily the same subclass).
|
||||
Whenever possible, use the attributes and methods of the subclass
|
||||
|
|
|
@ -942,8 +942,8 @@ Configuring the rendering of a form's widgets
|
|||
|
||||
.. attribute:: Form.default_renderer
|
||||
|
||||
Specifies the :doc:`renderer <renderers>` to use for the form. Defaults to
|
||||
``None`` which means to use the default renderer specified by the
|
||||
Specifies the :doc:`renderer </ref/forms/renderers>` to use for the form.
|
||||
Defaults to ``None`` which means to use the default renderer specified by the
|
||||
:setting:`FORM_RENDERER` setting.
|
||||
|
||||
You can set this as a class attribute when declaring your form or use the
|
||||
|
@ -1070,9 +1070,9 @@ Customizing the error list format
|
|||
|
||||
.. attribute:: renderer
|
||||
|
||||
Specifies the :doc:`renderer <renderers>` to use for ``ErrorList``.
|
||||
Defaults to ``None`` which means to use the default renderer
|
||||
specified by the :setting:`FORM_RENDERER` setting.
|
||||
Specifies the :doc:`renderer </ref/forms/renderers>` to use for
|
||||
``ErrorList``. Defaults to ``None`` which means to use the default
|
||||
renderer specified by the :setting:`FORM_RENDERER` setting.
|
||||
|
||||
.. attribute:: field_id
|
||||
|
||||
|
|
|
@ -919,7 +919,7 @@ For each field, we describe the default widget used if you don't specify
|
|||
|
||||
.. attribute:: encoder
|
||||
|
||||
A :py:class:`json.JSONEncoder` subclass to serialize data types not
|
||||
A :class:`json.JSONEncoder` subclass to serialize data types not
|
||||
supported by the standard JSON serializer (e.g. ``datetime.datetime``
|
||||
or :class:`~python:uuid.UUID`). For example, you can use the
|
||||
:class:`~django.core.serializers.json.DjangoJSONEncoder` class.
|
||||
|
@ -928,14 +928,14 @@ For each field, we describe the default widget used if you don't specify
|
|||
|
||||
.. attribute:: decoder
|
||||
|
||||
A :py:class:`json.JSONDecoder` subclass to deserialize the input. Your
|
||||
A :class:`json.JSONDecoder` subclass to deserialize the input. Your
|
||||
deserialization may need to account for the fact that you can't be
|
||||
certain of the input type. For example, you run the risk of returning a
|
||||
``datetime`` that was actually a string that just happened to be in the
|
||||
same format chosen for ``datetime``\s.
|
||||
|
||||
The ``decoder`` can be used to validate the input. If
|
||||
:py:class:`json.JSONDecodeError` is raised during the deserialization,
|
||||
:class:`json.JSONDecodeError` is raised during the deserialization,
|
||||
a ``ValidationError`` will be raised.
|
||||
|
||||
Defaults to ``json.JSONDecoder``.
|
||||
|
|
|
@ -1,15 +1,188 @@
|
|||
====================
|
||||
Model Form Functions
|
||||
====================
|
||||
|
||||
Model Form API reference. For introductory material about model forms, see the
|
||||
:doc:`/topics/forms/modelforms` topic guide.
|
||||
===========
|
||||
Model forms
|
||||
===========
|
||||
|
||||
.. module:: django.forms.models
|
||||
:synopsis: Django's functions for building model forms and formsets.
|
||||
:synopsis: ModelForm API reference for inner ``Meta`` class and factory
|
||||
functions
|
||||
|
||||
.. currentmodule:: django.forms
|
||||
|
||||
``ModelForm`` API reference. For introductory material about using a
|
||||
``ModelForm``, see the :doc:`/topics/forms/modelforms` topic guide.
|
||||
|
||||
Model form ``Meta`` API
|
||||
=======================
|
||||
|
||||
.. class:: ModelFormOptions
|
||||
|
||||
The ``_meta`` API is used to build forms that reflect a Django model. It is
|
||||
accessible through the ``_meta`` attribute of each model form, and is an
|
||||
``django.forms.models.ModelFormOptions`` instance.
|
||||
|
||||
The structure of the generated form can be customized by defining metadata
|
||||
options as attributes of an inner ``Meta`` class. For example::
|
||||
|
||||
from django.forms import ModelForm
|
||||
from myapp.models import Book
|
||||
|
||||
|
||||
class BookForm(ModelForm):
|
||||
class Meta:
|
||||
model = Book
|
||||
fields = ["title", "author"]
|
||||
help_texts = {
|
||||
"title": "The title of the book",
|
||||
"author": "The author of the book",
|
||||
}
|
||||
# ... other attributes
|
||||
|
||||
Required attributes are :attr:`~ModelFormOptions.model`, and either
|
||||
:attr:`~ModelFormOptions.fields` or :attr:`~ModelFormOptions.exclude`. All
|
||||
other ``Meta`` attributes are optional.
|
||||
|
||||
Optional attributes, other than :attr:`~ModelFormOptions.localized_fields` and
|
||||
:attr:`~ModelFormOptions.formfield_callback`, expect a dictionary that maps a
|
||||
model field name to a value. Any field that is not defined in the dictionary
|
||||
falls back to the field's default value.
|
||||
|
||||
.. admonition:: Invalid field names
|
||||
|
||||
Invalid or excluded field names in an optional dictionary attribute have no
|
||||
effect, since fields that are not included are not accessed.
|
||||
|
||||
.. admonition:: Invalid Meta class attributes
|
||||
|
||||
You may define any attribute on a ``Meta`` class. Typos or incorrect
|
||||
attribute names do not raise an error.
|
||||
|
||||
``error_messages``
|
||||
------------------
|
||||
|
||||
.. attribute:: ModelFormOptions.error_messages
|
||||
|
||||
A dictionary that maps a model field name to a dictionary of error message
|
||||
keys (``null``, ``blank``, ``invalid``, ``unique``, etc.) mapped to custom
|
||||
error messages.
|
||||
|
||||
When a field is not specified, Django will fall back on the error messages
|
||||
defined in that model field's :attr:`django.db.models.Field.error_messages`
|
||||
and then finally on the default error messages for that field type.
|
||||
|
||||
``exclude``
|
||||
-----------
|
||||
|
||||
.. attribute:: ModelFormOptions.exclude
|
||||
|
||||
A tuple or list of :attr:`~ModelFormOptions.model` field names to be
|
||||
excluded from the form.
|
||||
|
||||
Either :attr:`~ModelFormOptions.fields` or
|
||||
:attr:`~ModelFormOptions.exclude` must be set. If neither are set, an
|
||||
:class:`~django.core.exceptions.ImproperlyConfigured` exception will be
|
||||
raised. If :attr:`~ModelFormOptions.exclude` is set and
|
||||
:attr:`~ModelFormOptions.fields` is unset, all model fields, except for
|
||||
those specified in :attr:`~ModelFormOptions.exclude`, are included in the
|
||||
form.
|
||||
|
||||
``field_classes``
|
||||
-----------------
|
||||
|
||||
.. attribute:: ModelFormOptions.field_classes
|
||||
|
||||
A dictionary that maps a model field name to a :class:`~django.forms.Field`
|
||||
class, which overrides the ``form_class`` used in the model field's
|
||||
:meth:`.Field.formfield` method.
|
||||
|
||||
When a field is not specified, Django will fall back on the model field's
|
||||
:ref:`default field class <model-form-field-types>`.
|
||||
|
||||
``fields``
|
||||
----------
|
||||
|
||||
.. attribute:: ModelFormOptions.fields
|
||||
|
||||
A tuple or list of :attr:`~ModelFormOptions.model` field names to be
|
||||
included in the form. The value ``'__all__'`` can be used to specify that
|
||||
all fields should be included.
|
||||
|
||||
If any field is specified in :attr:`~ModelFormOptions.exclude`, this will
|
||||
not be included in the form despite being specified in
|
||||
:attr:`~ModelFormOptions.fields`.
|
||||
|
||||
Either :attr:`~ModelFormOptions.fields` or
|
||||
:attr:`~ModelFormOptions.exclude` must be set. If neither are set, an
|
||||
:class:`~django.core.exceptions.ImproperlyConfigured` exception will be
|
||||
raised.
|
||||
|
||||
``formfield_callback``
|
||||
----------------------
|
||||
|
||||
.. attribute:: ModelFormOptions.formfield_callback
|
||||
|
||||
A function or callable that takes a model field and returns a
|
||||
:class:`django.forms.Field` object.
|
||||
|
||||
``help_texts``
|
||||
--------------
|
||||
|
||||
.. attribute:: ModelFormOptions.help_texts
|
||||
|
||||
A dictionary that maps a model field name to a help text string.
|
||||
|
||||
When a field is not specified, Django will fall back on that model field's
|
||||
:attr:`~django.db.models.Field.help_text`.
|
||||
|
||||
``labels``
|
||||
----------
|
||||
|
||||
.. attribute:: ModelFormOptions.labels
|
||||
|
||||
A dictionary that maps a model field names to a label string.
|
||||
|
||||
When a field is not specified, Django will fall back on that model field's
|
||||
:attr:`~django.db.models.Field.verbose_name` and then the field's attribute
|
||||
name.
|
||||
|
||||
``localized_fields``
|
||||
--------------------
|
||||
|
||||
.. attribute:: ModelFormOptions.localized_fields
|
||||
|
||||
A tuple or list of :attr:`~ModelFormOptions.model` field names to be
|
||||
localized. The value ``'__all__'`` can be used to specify that all fields
|
||||
should be localized.
|
||||
|
||||
By default, form fields are not localized, see
|
||||
:ref:`enabling localization of fields
|
||||
<modelforms-enabling-localization-of-fields>` for more details.
|
||||
|
||||
``model``
|
||||
---------
|
||||
|
||||
.. attribute:: ModelFormOptions.model
|
||||
|
||||
Required. The :class:`django.db.models.Model` to be used for the
|
||||
:class:`~django.forms.ModelForm`.
|
||||
|
||||
``widgets``
|
||||
-----------
|
||||
|
||||
.. attribute:: ModelFormOptions.widgets
|
||||
|
||||
A dictionary that maps a model field name to a
|
||||
:class:`django.forms.Widget`.
|
||||
|
||||
When a field is not specified, Django will fall back on the default widget
|
||||
for that particular type of :class:`django.db.models.Field`.
|
||||
|
||||
Model form factory functions
|
||||
============================
|
||||
|
||||
.. currentmodule:: django.forms.models
|
||||
|
||||
``modelform_factory``
|
||||
=====================
|
||||
---------------------
|
||||
|
||||
.. function:: modelform_factory(model, form=ModelForm, fields=None, exclude=None, formfield_callback=None, widgets=None, localized_fields=None, labels=None, help_texts=None, error_messages=None, field_classes=None)
|
||||
|
||||
|
@ -51,7 +224,7 @@ Model Form API reference. For introductory material about model forms, see the
|
|||
in an :exc:`~django.core.exceptions.ImproperlyConfigured` exception.
|
||||
|
||||
``modelformset_factory``
|
||||
========================
|
||||
------------------------
|
||||
|
||||
.. function:: modelformset_factory(model, form=ModelForm, formfield_callback=None, formset=BaseModelFormSet, extra=1, can_delete=False, can_order=False, max_num=None, fields=None, exclude=None, widgets=None, validate_max=False, localized_fields=None, labels=None, help_texts=None, error_messages=None, min_num=None, validate_min=False, field_classes=None, absolute_max=None, can_delete_extra=True, renderer=None, edit_only=False)
|
||||
|
||||
|
@ -74,7 +247,7 @@ Model Form API reference. For introductory material about model forms, see the
|
|||
See :ref:`model-formsets` for example usage.
|
||||
|
||||
``inlineformset_factory``
|
||||
=========================
|
||||
-------------------------
|
||||
|
||||
.. function:: inlineformset_factory(parent_model, model, form=ModelForm, formset=BaseInlineFormSet, fk_name=None, fields=None, exclude=None, extra=3, can_order=False, can_delete=True, max_num=None, formfield_callback=None, widgets=None, validate_max=False, localized_fields=None, labels=None, help_texts=None, error_messages=None, min_num=None, validate_min=False, field_classes=None, absolute_max=None, can_delete_extra=True, renderer=None, edit_only=False)
|
||||
|
||||
|
|
|
@ -164,7 +164,7 @@ Messages to this logger have the following extra context:
|
|||
|
||||
* ``status_code``: The HTTP response code associated with the request.
|
||||
|
||||
* ``request``: The request object (a :py:class:`socket.socket`) that generated
|
||||
* ``request``: The request object (a :class:`socket.socket`) that generated
|
||||
the logging message.
|
||||
|
||||
.. _django-template-logger:
|
||||
|
@ -215,27 +215,28 @@ messages during filesystem inspection and event subscription processes.
|
|||
``django.contrib.auth``
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Log messages related to :doc:`contrib/auth`, particularly ``ERROR`` messages
|
||||
are generated when a :class:`~django.contrib.auth.forms.PasswordResetForm` is
|
||||
successfully submitted but the password reset email cannot be delivered due to
|
||||
a mail sending exception.
|
||||
Log messages related to :doc:`/ref/contrib/auth`, particularly ``ERROR``
|
||||
messages are generated when a
|
||||
:class:`~django.contrib.auth.forms.PasswordResetForm` is successfully submitted
|
||||
but the password reset email cannot be delivered due to a mail sending
|
||||
exception.
|
||||
|
||||
.. _django-contrib-gis-logger:
|
||||
|
||||
``django.contrib.gis``
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Log messages related to :doc:`contrib/gis/index` at various points: during the
|
||||
loading of external GeoSpatial libraries (GEOS, GDAL, etc.) and when reporting
|
||||
errors. Each ``ERROR`` log record includes the caught exception and relevant
|
||||
contextual data.
|
||||
Log messages related to :doc:`/ref/contrib/gis/index` at various points: during
|
||||
the loading of external GeoSpatial libraries (GEOS, GDAL, etc.) and when
|
||||
reporting errors. Each ``ERROR`` log record includes the caught exception and
|
||||
relevant contextual data.
|
||||
|
||||
.. _django-dispatch-logger:
|
||||
|
||||
``django.dispatch``
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
This logger is used in :doc:`signals`, specifically within the
|
||||
This logger is used in :doc:`/ref/signals`, specifically within the
|
||||
:mod:`~django.dispatch.Signal` class, to report issues when dispatching a
|
||||
signal to a connected receiver. The ``ERROR`` log record includes the caught
|
||||
exception as ``exc_info`` and adds the following extra context:
|
||||
|
|
|
@ -6,9 +6,9 @@ Conditional Expressions
|
|||
|
||||
Conditional expressions let you use :keyword:`if` ... :keyword:`elif` ...
|
||||
:keyword:`else` logic within filters, annotations, aggregations, and updates. A
|
||||
conditional expression evaluates a series of conditions for each row of a
|
||||
table and returns the matching result expression. Conditional expressions can
|
||||
also be combined and nested like other :doc:`expressions <expressions>`.
|
||||
conditional expression evaluates a series of conditions for each row of a table
|
||||
and returns the matching result expression. Conditional expressions can also be
|
||||
combined and nested like other :doc:`expressions </ref/models/expressions>`.
|
||||
|
||||
The conditional expression classes
|
||||
==================================
|
||||
|
|
|
@ -7,8 +7,8 @@ Database Functions
|
|||
|
||||
The classes documented below provide a way for users to use functions provided
|
||||
by the underlying database as annotations, aggregations, or filters in Django.
|
||||
Functions are also :doc:`expressions <expressions>`, so they can be used and
|
||||
combined with other expressions like :ref:`aggregate functions
|
||||
Functions are also :doc:`expressions </ref/models/expressions>`, so they can be
|
||||
used and combined with other expressions like :ref:`aggregate functions
|
||||
<aggregation-functions>`.
|
||||
|
||||
We'll be using the following model in examples of each function::
|
||||
|
|
|
@ -340,7 +340,8 @@ extra attribute ``field_lower`` produced, roughly, from the following SQL:
|
|||
...
|
||||
LOWER("db_table"."field") as "field_lower"
|
||||
|
||||
See :doc:`database-functions` for a list of built-in database functions.
|
||||
See :doc:`/ref/models/database-functions` for a list of built-in database
|
||||
functions.
|
||||
|
||||
The ``Func`` API is as follows:
|
||||
|
||||
|
@ -563,7 +564,7 @@ values into their corresponding database type.
|
|||
|
||||
If no :ref:`output_field<output-field>` is specified, it will be inferred from
|
||||
the type of the provided ``value`` for many common types. For example, passing
|
||||
an instance of :py:class:`datetime.datetime` as ``value`` defaults
|
||||
an instance of :class:`datetime.datetime` as ``value`` defaults
|
||||
``output_field`` to :class:`~django.db.models.DateTimeField`.
|
||||
|
||||
``ExpressionWrapper()`` expressions
|
||||
|
@ -582,7 +583,7 @@ Conditional expressions
|
|||
|
||||
Conditional expressions allow you to use :keyword:`if` ... :keyword:`elif` ...
|
||||
:keyword:`else` logic in queries. Django natively supports SQL ``CASE``
|
||||
expressions. For more details see :doc:`conditional-expressions`.
|
||||
expressions. For more details see :doc:`/ref/models/conditional-expressions`.
|
||||
|
||||
``Subquery()`` expressions
|
||||
--------------------------
|
||||
|
@ -1094,7 +1095,7 @@ calling the appropriate methods on the wrapped expression.
|
|||
|
||||
Tells Django which value should be returned when the expression is used
|
||||
to apply a function over an empty result set. Defaults to
|
||||
:py:data:`NotImplemented` which forces the expression to be computed on
|
||||
:data:`NotImplemented` which forces the expression to be computed on
|
||||
the database.
|
||||
|
||||
.. attribute:: set_returning
|
||||
|
|
|
@ -1434,7 +1434,7 @@ Python native format: dictionaries, lists, strings, numbers, booleans and
|
|||
|
||||
.. attribute:: JSONField.encoder
|
||||
|
||||
An optional :py:class:`json.JSONEncoder` subclass to serialize data types
|
||||
An optional :class:`json.JSONEncoder` subclass to serialize data types
|
||||
not supported by the standard JSON serializer (e.g. ``datetime.datetime``
|
||||
or :class:`~python:uuid.UUID`). For example, you can use the
|
||||
:class:`~django.core.serializers.json.DjangoJSONEncoder` class.
|
||||
|
@ -1443,7 +1443,7 @@ Python native format: dictionaries, lists, strings, numbers, booleans and
|
|||
|
||||
.. attribute:: JSONField.decoder
|
||||
|
||||
An optional :py:class:`json.JSONDecoder` subclass to deserialize the value
|
||||
An optional :class:`json.JSONDecoder` subclass to deserialize the value
|
||||
retrieved from the database. The value will be in the format chosen by the
|
||||
custom encoder (most often a string). Your deserialization may need to
|
||||
account for the fact that you can't be certain of the input type. For
|
||||
|
@ -1458,7 +1458,7 @@ To query ``JSONField`` in the database, see :ref:`querying-jsonfield`.
|
|||
.. admonition:: Default value
|
||||
|
||||
If you give the field a :attr:`~django.db.models.Field.default`, ensure
|
||||
it's a callable such as the :py:class:`dict` class or a function that
|
||||
it's a callable such as the :class:`dict` class or a function that
|
||||
returns a fresh object each time. Incorrectly using a mutable object like
|
||||
``default={}`` or ``default=[]`` creates a mutable default that is shared
|
||||
between all instances.
|
||||
|
@ -1483,8 +1483,8 @@ To query ``JSONField`` in the database, see :ref:`querying-jsonfield`.
|
|||
.. admonition:: Oracle users
|
||||
|
||||
Oracle Database does not support storing JSON scalar values. Only JSON
|
||||
objects and arrays (represented in Python using :py:class:`dict` and
|
||||
:py:class:`list`) are supported.
|
||||
objects and arrays (represented in Python using :class:`dict` and
|
||||
:class:`list`) are supported.
|
||||
|
||||
``PositiveBigIntegerField``
|
||||
---------------------------
|
||||
|
@ -2440,7 +2440,7 @@ Field API reference
|
|||
|
||||
.. attribute:: descriptor_class
|
||||
|
||||
A class implementing the :py:ref:`descriptor protocol <descriptors>`
|
||||
A class implementing the :ref:`descriptor protocol <descriptors>`
|
||||
that is instantiated and assigned to the model instance attribute. The
|
||||
constructor must accept a single argument, the ``Field`` instance.
|
||||
Overriding this class attribute allows for customizing the get and set
|
||||
|
|
|
@ -889,7 +889,7 @@ Attributes
|
|||
|
||||
.. attribute:: HttpResponse.cookies
|
||||
|
||||
A :py:obj:`http.cookies.SimpleCookie` object holding the cookies included
|
||||
A :obj:`http.cookies.SimpleCookie` object holding the cookies included
|
||||
in the response.
|
||||
|
||||
.. attribute:: HttpResponse.headers
|
||||
|
@ -952,7 +952,7 @@ Methods
|
|||
``"text/html; charset=utf-8"``.
|
||||
|
||||
``status`` is the :rfc:`HTTP status code <9110#section-15>` for the
|
||||
response. You can use Python's :py:class:`http.HTTPStatus` for meaningful
|
||||
response. You can use Python's :class:`http.HTTPStatus` for meaningful
|
||||
aliases, such as ``HTTPStatus.NO_CONTENT``.
|
||||
|
||||
``reason`` is the HTTP response phrase. If not provided, a default phrase
|
||||
|
@ -1187,7 +1187,7 @@ Custom response classes
|
|||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
If you find yourself needing a response class that Django doesn't provide, you
|
||||
can create it with the help of :py:class:`http.HTTPStatus`. For example::
|
||||
can create it with the help of :class:`http.HTTPStatus`. For example::
|
||||
|
||||
from http import HTTPStatus
|
||||
from django.http import HttpResponse
|
||||
|
|
|
@ -1225,14 +1225,14 @@ attribute and calling the result ``country_list``.
|
|||
|
||||
``{% regroup %}`` produces a list (in this case, ``country_list``) of
|
||||
**group objects**. Group objects are instances of
|
||||
:py:func:`~collections.namedtuple` with two fields:
|
||||
:func:`~collections.namedtuple` with two fields:
|
||||
|
||||
* ``grouper`` -- the item that was grouped by (e.g., the string "India" or
|
||||
"Japan").
|
||||
* ``list`` -- a list of all items in this group (e.g., a list of all cities
|
||||
with country='India').
|
||||
|
||||
Because ``{% regroup %}`` produces :py:func:`~collections.namedtuple` objects,
|
||||
Because ``{% regroup %}`` produces :func:`~collections.namedtuple` objects,
|
||||
you can also write the previous example as:
|
||||
|
||||
.. code-block:: html+django
|
||||
|
@ -1839,7 +1839,7 @@ For example:
|
|||
|
||||
{{ value|date:"D d M Y" }}
|
||||
|
||||
If ``value`` is a :py:class:`~datetime.datetime` object (e.g., the result of
|
||||
If ``value`` is a :class:`~datetime.datetime` object (e.g., the result of
|
||||
``datetime.datetime.now()``), the output will be the string
|
||||
``'Wed 09 Jan 2008'``.
|
||||
|
||||
|
@ -2736,7 +2736,7 @@ specifier for the ``de`` locale as shipped with Django is ``"H:i"``).
|
|||
The ``time`` filter will only accept parameters in the format string that
|
||||
relate to the time of day, not the date. If you need to format a ``date``
|
||||
value, use the :tfilter:`date` filter instead (or along with :tfilter:`time` if
|
||||
you need to render a full :py:class:`~datetime.datetime` value).
|
||||
you need to render a full :class:`~datetime.datetime` value).
|
||||
|
||||
There is one exception the above rule: When passed a ``datetime`` value with
|
||||
attached timezone information (a :ref:`time-zone-aware
|
||||
|
|
|
@ -268,7 +268,7 @@ Use strings when creating templates manually::
|
|||
|
||||
But the common case is to read templates from the filesystem. If your template
|
||||
files are not stored with a UTF-8 encoding, adjust the :setting:`TEMPLATES`
|
||||
setting. The built-in :py:mod:`~django.template.backends.django` backend
|
||||
setting. The built-in :mod:`~django.template.backends.django` backend
|
||||
provides the ``'file_charset'`` option to change the encoding used to read
|
||||
files from disk.
|
||||
|
||||
|
|
|
@ -95,7 +95,7 @@ Returns an element for inclusion in ``urlpatterns``. For example::
|
|||
The ``route`` argument should be a string or
|
||||
:func:`~django.utils.translation.gettext_lazy` (see
|
||||
:ref:`translating-urlpatterns`) that contains a regular expression compatible
|
||||
with Python's :py:mod:`re` module. Strings typically use raw string syntax
|
||||
with Python's :mod:`re` module. Strings typically use raw string syntax
|
||||
(``r''``) so that they can contain sequences like ``\d`` without the need to
|
||||
escape the backslash with another backslash. When a match is made, captured
|
||||
groups from the regular expression are passed to the view -- as named arguments
|
||||
|
@ -104,7 +104,7 @@ passed as strings, without any type conversion.
|
|||
|
||||
When a ``route`` ends with ``$`` the whole requested URL, matching against
|
||||
:attr:`~django.http.HttpRequest.path_info`, must match the regular expression
|
||||
pattern (:py:func:`re.fullmatch` is used).
|
||||
pattern (:func:`re.fullmatch` is used).
|
||||
|
||||
The ``view``, ``kwargs`` and ``name`` arguments are the same as for
|
||||
:func:`~django.urls.path`.
|
||||
|
|
|
@ -352,7 +352,7 @@ compatibility
|
|||
|
||||
An optional string containing the MIME type of the stylesheet. If not
|
||||
specified, Django will attempt to guess it by using Python's
|
||||
:py:func:`mimetypes.guess_type`. Use ``mimetype=None`` if you don't
|
||||
:func:`mimetypes.guess_type`. Use ``mimetype=None`` if you don't
|
||||
want your stylesheet to have a MIME type specified.
|
||||
|
||||
.. attribute:: media
|
||||
|
@ -532,7 +532,7 @@ compatibility
|
|||
# set a value manually, that will persist on the instance until cleared
|
||||
person.friends = ["Huckleberry Finn", "Tom Sawyer"]
|
||||
|
||||
Because of the way the :py:ref:`descriptor protocol
|
||||
Because of the way the :ref:`descriptor protocol
|
||||
<descriptor-invocation>` works, using ``del`` (or ``delattr``) on a
|
||||
``cached_property`` that hasn't been accessed raises ``AttributeError``.
|
||||
|
||||
|
@ -560,7 +560,7 @@ compatibility
|
|||
|
||||
.. class:: classproperty(method=None)
|
||||
|
||||
Similar to :py:func:`@classmethod <classmethod>`, the ``@classproperty``
|
||||
Similar to :func:`@classmethod <classmethod>`, the ``@classproperty``
|
||||
decorator converts the result of a method with a single ``cls`` argument
|
||||
into a property that can be accessed directly from the class.
|
||||
|
||||
|
|
|
@ -448,7 +448,7 @@ Requests and Responses
|
|||
* Added :class:`~django.http.HttpResponse` methods
|
||||
:meth:`~django.http.HttpResponse.readable` and
|
||||
:meth:`~django.http.HttpResponse.seekable` to make an instance a
|
||||
stream-like object and allow wrapping it with :py:class:`io.TextIOWrapper`.
|
||||
stream-like object and allow wrapping it with :class:`io.TextIOWrapper`.
|
||||
|
||||
* Added the :attr:`HttpRequest.content_type
|
||||
<django.http.HttpRequest.content_type>` and
|
||||
|
|
|
@ -332,7 +332,8 @@ Models
|
|||
|
||||
* :class:`~django.db.models.ImageField` now has a default
|
||||
:data:`~django.core.validators.validate_image_file_extension` validator.
|
||||
(This validator moved to the form field in :doc:`Django 1.11.2 <1.11.2>`.)
|
||||
(This validator moved to the form field in :doc:`Django 1.11.2
|
||||
</releases/1.11.2>`.)
|
||||
|
||||
* Added support for time truncation to
|
||||
:class:`~django.db.models.functions.Trunc` functions.
|
||||
|
|
|
@ -266,7 +266,7 @@ and in Django 1.5 will raise an ``ImproperlyConfigured`` exception.
|
|||
Everything else
|
||||
---------------
|
||||
|
||||
Django :doc:`1.1 <1.1>` and :doc:`1.2 <1.2>` added
|
||||
Django :doc:`1.1 </releases/1.1>` and :doc:`1.2 </releases/1.2>` added
|
||||
lots of big ticket items to Django, like multiple-database support,
|
||||
model validation, and a session-based messages framework. However,
|
||||
this focus on big features came at the cost of lots of smaller
|
||||
|
|
|
@ -5,4 +5,5 @@ Django 1.8.11 release notes
|
|||
*March 5, 2016*
|
||||
|
||||
Django 1.8.11 fixes a regression on Python 2 in the 1.8.10 security release
|
||||
where ``utils.http.is_safe_url()`` crashes on bytestring URLs (:ticket:`26308`).
|
||||
where ``utils.http.is_safe_url()`` crashes on bytestring URLs
|
||||
(:ticket:`26308`).
|
||||
|
|
|
@ -275,7 +275,7 @@ Cryptography
|
|||
|
||||
* The ``max_age`` parameter of the
|
||||
:meth:`django.core.signing.TimestampSigner.unsign` method now also accepts a
|
||||
:py:class:`datetime.timedelta` object.
|
||||
:class:`datetime.timedelta` object.
|
||||
|
||||
Database backends
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
@ -384,7 +384,7 @@ Generic Views
|
|||
|
||||
* Placeholders in :attr:`ModelFormMixin.success_url
|
||||
<django.views.generic.edit.ModelFormMixin.success_url>` now support the
|
||||
Python :py:meth:`str.format` syntax. The legacy ``%(<foo>)s`` syntax is still
|
||||
Python :meth:`str.format` syntax. The legacy ``%(<foo>)s`` syntax is still
|
||||
supported but will be removed in Django 1.10.
|
||||
|
||||
Internationalization
|
||||
|
@ -753,7 +753,7 @@ Management commands that only accept positional arguments
|
|||
If you have written a custom management command that only accepts positional
|
||||
arguments and you didn't specify the ``args`` command variable, you might get
|
||||
an error like ``Error: unrecognized arguments: ...``, as variable parsing is
|
||||
now based on :py:mod:`argparse` which doesn't implicitly accept positional
|
||||
now based on :mod:`argparse` which doesn't implicitly accept positional
|
||||
arguments. You can make your command backwards compatible by simply setting the
|
||||
``args`` class variable. However, if you don't have to keep compatibility with
|
||||
older Django versions, it's better to implement the new
|
||||
|
@ -766,10 +766,10 @@ Custom test management command arguments through test runner
|
|||
The method to add custom arguments to the ``test`` management command through
|
||||
the test runner has changed. Previously, you could provide an ``option_list``
|
||||
class variable on the test runner to add more arguments (à la
|
||||
:py:mod:`optparse`). Now to implement the same behavior, you have to create an
|
||||
:mod:`optparse`). Now to implement the same behavior, you have to create an
|
||||
``add_arguments(cls, parser)`` class method on the test runner and call
|
||||
``parser.add_argument`` to add any custom arguments, as parser is now an
|
||||
:py:class:`argparse.ArgumentParser` instance.
|
||||
:class:`argparse.ArgumentParser` instance.
|
||||
|
||||
Model check ensures auto-generated column names are within limits specified by database
|
||||
---------------------------------------------------------------------------------------
|
||||
|
@ -1407,7 +1407,7 @@ in Django 1.10:
|
|||
Extending management command arguments through ``Command.option_list``
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Management commands now use :py:mod:`argparse` instead of :py:mod:`optparse` to
|
||||
Management commands now use :mod:`argparse` instead of :mod:`optparse` to
|
||||
parse command-line arguments passed to commands. This also means that the way
|
||||
to add custom arguments to commands has changed: instead of extending the
|
||||
``option_list`` class list, you should now override the
|
||||
|
|
|
@ -5,4 +5,5 @@ Django 1.9.4 release notes
|
|||
*March 5, 2016*
|
||||
|
||||
Django 1.9.4 fixes a regression on Python 2 in the 1.9.3 security release
|
||||
where ``utils.http.is_safe_url()`` crashes on bytestring URLs (:ticket:`26308`).
|
||||
where ``utils.http.is_safe_url()`` crashes on bytestring URLs
|
||||
(:ticket:`26308`).
|
||||
|
|
|
@ -285,7 +285,7 @@ Models
|
|||
|
||||
* The new :attr:`.Field.descriptor_class` attribute allows model fields to
|
||||
customize the get and set behavior by overriding their
|
||||
:py:ref:`descriptors <descriptors>`.
|
||||
:ref:`descriptors <descriptors>`.
|
||||
|
||||
* :class:`~django.db.models.Avg` and :class:`~django.db.models.Sum` now support
|
||||
the ``distinct`` argument.
|
||||
|
|
|
@ -43,7 +43,7 @@ Bugfixes
|
|||
* Fixed a regression in Django 3.1 where
|
||||
:exc:`ProtectedError.protected_objects <django.db.models.ProtectedError>` and
|
||||
:exc:`RestrictedError.restricted_objects <django.db.models.RestrictedError>`
|
||||
attributes returned iterators instead of :py:class:`set` of objects
|
||||
attributes returned iterators instead of :class:`set` of objects
|
||||
(:ticket:`32107`).
|
||||
|
||||
* Fixed a regression in Django 3.1.2 that caused incorrect form input layout on
|
||||
|
|
|
@ -407,7 +407,7 @@ Models
|
|||
SQL on MySQL by using ``DELETE`` instead of ``TRUNCATE`` statements for
|
||||
tables which don't require resetting sequences.
|
||||
|
||||
* SQLite functions are now marked as :py:meth:`deterministic
|
||||
* SQLite functions are now marked as :meth:`deterministic
|
||||
<sqlite3.Connection.create_function>` on Python 3.8+. This allows using them
|
||||
in check constraints and partial indexes.
|
||||
|
||||
|
|
|
@ -406,11 +406,11 @@ Models
|
|||
* :class:`Value() <django.db.models.Value>` expression now
|
||||
automatically resolves its ``output_field`` to the appropriate
|
||||
:class:`Field <django.db.models.Field>` subclass based on the type of
|
||||
its provided ``value`` for :py:class:`bool`, :py:class:`bytes`,
|
||||
:py:class:`float`, :py:class:`int`, :py:class:`str`,
|
||||
:py:class:`datetime.date`, :py:class:`datetime.datetime`,
|
||||
:py:class:`datetime.time`, :py:class:`datetime.timedelta`,
|
||||
:py:class:`decimal.Decimal`, and :py:class:`uuid.UUID` instances. As a
|
||||
its provided ``value`` for :class:`bool`, :class:`bytes`,
|
||||
:class:`float`, :class:`int`, :class:`str`,
|
||||
:class:`datetime.date`, :class:`datetime.datetime`,
|
||||
:class:`datetime.time`, :class:`datetime.timedelta`,
|
||||
:class:`decimal.Decimal`, and :class:`uuid.UUID` instances. As a
|
||||
consequence, resolving an ``output_field`` for database functions and
|
||||
combined expressions may now crash with mixed types when using ``Value()``.
|
||||
You will need to explicitly set the ``output_field`` in such cases.
|
||||
|
@ -519,11 +519,11 @@ Tests
|
|||
|
||||
* Objects assigned to class attributes in :meth:`.TestCase.setUpTestData` are
|
||||
now isolated for each test method. Such objects are now required to support
|
||||
creating deep copies with :py:func:`copy.deepcopy`. Assigning objects which
|
||||
creating deep copies with :func:`copy.deepcopy`. Assigning objects which
|
||||
don't support ``deepcopy()`` is deprecated and will be removed in Django 4.1.
|
||||
|
||||
* :class:`~django.test.runner.DiscoverRunner` now enables
|
||||
:py:mod:`faulthandler` by default. This can be disabled by using the
|
||||
:mod:`faulthandler` by default. This can be disabled by using the
|
||||
:option:`test --no-faulthandler` option.
|
||||
|
||||
* :class:`~django.test.runner.DiscoverRunner` and the
|
||||
|
@ -703,8 +703,8 @@ Miscellaneous
|
|||
removed. Please use :func:`urllib.parse.parse_qsl` instead.
|
||||
|
||||
* ``django.test.utils.TestContextDecorator`` now uses
|
||||
:py:meth:`~unittest.TestCase.addCleanup` so that cleanups registered in the
|
||||
:py:meth:`~unittest.TestCase.setUp` method are called before
|
||||
:meth:`~unittest.TestCase.addCleanup` so that cleanups registered in the
|
||||
:meth:`~unittest.TestCase.setUp` method are called before
|
||||
``TestContextDecorator.disable()``.
|
||||
|
||||
* ``SessionMiddleware`` now raises a
|
||||
|
@ -758,7 +758,7 @@ Miscellaneous
|
|||
-------------
|
||||
|
||||
* Assigning objects which don't support creating deep copies with
|
||||
:py:func:`copy.deepcopy` to class attributes in
|
||||
:func:`copy.deepcopy` to class attributes in
|
||||
:meth:`.TestCase.setUpTestData` is deprecated.
|
||||
|
||||
* Using a boolean value in :attr:`.BaseCommand.requires_system_checks` is
|
||||
|
|
|
@ -289,7 +289,7 @@ Management Commands
|
|||
|
||||
* On PostgreSQL, :djadmin:`dbshell` now supports specifying a password file.
|
||||
|
||||
* The :djadmin:`shell` command now respects :py:data:`sys.__interactivehook__`
|
||||
* The :djadmin:`shell` command now respects :data:`sys.__interactivehook__`
|
||||
at startup. This allows loading shell history between interactive sessions.
|
||||
As a consequence, ``readline`` is no longer loaded if running in *isolated*
|
||||
mode.
|
||||
|
@ -349,7 +349,7 @@ Signals
|
|||
* The new ``stdout`` argument for :func:`~django.db.models.signals.pre_migrate`
|
||||
and :func:`~django.db.models.signals.post_migrate` signals allows redirecting
|
||||
output to a stream-like object. It should be preferred over
|
||||
:py:data:`sys.stdout` and :py:func:`print` when emitting verbose output in
|
||||
:data:`sys.stdout` and :func:`print` when emitting verbose output in
|
||||
order to allow proper capture when testing.
|
||||
|
||||
Templates
|
||||
|
@ -370,7 +370,7 @@ Tests
|
|||
* The :option:`test --buffer` option now supports parallel tests.
|
||||
|
||||
* The new ``logger`` argument to :class:`~django.test.runner.DiscoverRunner`
|
||||
allows a Python :py:ref:`logger <logger>` to be used for logging.
|
||||
allows a Python :ref:`logger <logger>` to be used for logging.
|
||||
|
||||
* The new :meth:`.DiscoverRunner.log` method provides a way to log messages
|
||||
that uses the ``DiscoverRunner.logger``, or prints to the console if not set.
|
||||
|
|
|
@ -536,7 +536,7 @@ Miscellaneous
|
|||
|
||||
* :class:`~django.test.runner.DiscoverRunner` now returns a non-zero error code
|
||||
for unexpected successes from tests marked with
|
||||
:py:func:`unittest.expectedFailure`.
|
||||
:func:`unittest.expectedFailure`.
|
||||
|
||||
* :class:`~django.middleware.csrf.CsrfViewMiddleware` no longer masks the CSRF
|
||||
cookie like it does the CSRF token in the DOM.
|
||||
|
@ -608,7 +608,7 @@ Features deprecated in 4.1
|
|||
Log out via GET
|
||||
---------------
|
||||
|
||||
Logging out via ``GET`` requests to the :py:class:`built-in logout view
|
||||
Logging out via ``GET`` requests to the :class:`built-in logout view
|
||||
<django.contrib.auth.views.LogoutView>` is deprecated. Use ``POST`` requests
|
||||
instead.
|
||||
|
||||
|
|
7
docs/releases/4.2.24.txt
Normal file
7
docs/releases/4.2.24.txt
Normal file
|
@ -0,0 +1,7 @@
|
|||
===========================
|
||||
Django 4.2.24 release notes
|
||||
===========================
|
||||
|
||||
*September 3, 2025*
|
||||
|
||||
Django 4.2.24 fixes a security issue with severity "high" in 4.2.23.
|
|
@ -475,8 +475,8 @@ Miscellaneous
|
|||
* Support for ``PROJ`` < 5 is removed.
|
||||
|
||||
* :class:`~django.core.mail.backends.smtp.EmailBackend` now verifies a
|
||||
:py:attr:`hostname <ssl.SSLContext.check_hostname>` and
|
||||
:py:attr:`certificates <ssl.SSLContext.verify_mode>`. If you need the
|
||||
:attr:`hostname <ssl.SSLContext.check_hostname>` and
|
||||
:attr:`certificates <ssl.SSLContext.verify_mode>`. If you need the
|
||||
previous behavior that is less restrictive and not recommended, subclass
|
||||
``EmailBackend`` and override the ``ssl_context`` property.
|
||||
|
||||
|
@ -564,7 +564,7 @@ Miscellaneous
|
|||
* The ``BaseUserManager.make_random_password()`` method is deprecated. See
|
||||
`recipes and best practices
|
||||
<https://docs.python.org/3/library/secrets.html#recipes-and-best-practices>`_
|
||||
for using Python's :py:mod:`secrets` module to generate passwords.
|
||||
for using Python's :mod:`secrets` module to generate passwords.
|
||||
|
||||
* The ``length_is`` template filter is deprecated in favor of :tfilter:`length`
|
||||
and the ``==`` operator within an :ttag:`{% if %}<if>` tag. For example
|
||||
|
|
7
docs/releases/5.1.12.txt
Normal file
7
docs/releases/5.1.12.txt
Normal file
|
@ -0,0 +1,7 @@
|
|||
===========================
|
||||
Django 5.1.12 release notes
|
||||
===========================
|
||||
|
||||
*September 3, 2025*
|
||||
|
||||
Django 5.1.12 fixes a security issue with severity "high" in 5.1.11.
|
|
@ -382,7 +382,7 @@ Miscellaneous
|
|||
|
||||
* ``django.utils.text.Truncator`` used by :tfilter:`truncatechars_html` and
|
||||
:tfilter:`truncatewords_html` template filters now uses
|
||||
:py:class:`html.parser.HTMLParser` subclasses. This results in a more robust
|
||||
:class:`html.parser.HTMLParser` subclasses. This results in a more robust
|
||||
and faster operation, but there may be small differences in the output.
|
||||
|
||||
* The undocumented ``django.urls.converters.get_converter()`` function is
|
||||
|
|
|
@ -2,11 +2,14 @@
|
|||
Django 5.2.6 release notes
|
||||
==========================
|
||||
|
||||
*Expected September 3, 2025*
|
||||
*September 3, 2025*
|
||||
|
||||
Django 5.2.6 fixes several bugs in 5.2.5.
|
||||
Django 5.2.6 fixes a security issue with severity "high" and several bugs in
|
||||
5.2.5.
|
||||
|
||||
Bugfixes
|
||||
========
|
||||
|
||||
* ...
|
||||
* Fixed a bug where using ``QuerySet.values()`` or ``values_list()`` with a
|
||||
``ForeignObject`` composed of multiple fields returned incorrect results
|
||||
instead of tuples of the referenced fields (:ticket:`36431`).
|
||||
|
|
|
@ -380,8 +380,8 @@ Utilities
|
|||
~~~~~~~~~
|
||||
|
||||
* :class:`~django.utils.safestring.SafeString` now returns
|
||||
:py:data:`NotImplemented` in ``__add__`` for non-string right-hand side
|
||||
values. This aligns with the :py:class:`str` addition behavior and allows
|
||||
:data:`NotImplemented` in ``__add__`` for non-string right-hand side
|
||||
values. This aligns with the :class:`str` addition behavior and allows
|
||||
``__radd__`` to be used if available.
|
||||
|
||||
* :func:`~django.utils.html.format_html_join` now supports taking an iterable
|
||||
|
|
|
@ -72,22 +72,23 @@ The resulting ``Content-Security-Policy`` header would be set to:
|
|||
|
||||
To get started, follow the :doc:`CSP how-to guide </howto/csp>`. For in-depth
|
||||
guidance, see the :ref:`CSP security overview <security-csp>` and the
|
||||
:doc:`reference docs </ref/csp>`.
|
||||
:doc:`reference docs </ref/csp>`, which include details about decorators to
|
||||
override or disable policies on a per-view basis.
|
||||
|
||||
Adoption of Python's modern email API
|
||||
-------------------------------------
|
||||
|
||||
Email handling in Django now uses Python's modern email API, introduced in
|
||||
Python 3.6. This API, centered around the
|
||||
:py:class:`email.message.EmailMessage` class, offers a cleaner and
|
||||
:class:`email.message.EmailMessage` class, offers a cleaner and
|
||||
Unicode-friendly interface for composing and sending emails. It replaces use of
|
||||
Python's older legacy (``Compat32``) API, which relied on lower-level MIME
|
||||
classes (from :py:mod:`email.mime`) and required more manual handling of
|
||||
classes (from :mod:`email.mime`) and required more manual handling of
|
||||
message structure and encoding.
|
||||
|
||||
Notably, the return type of the :class:`EmailMessage.message()
|
||||
<django.core.mail.EmailMessage>` method is now an instance of Python's
|
||||
:py:class:`email.message.EmailMessage`. This supports the same API as the
|
||||
:class:`email.message.EmailMessage`. This supports the same API as the
|
||||
previous ``SafeMIMEText`` and ``SafeMIMEMultipart`` return types, but is not an
|
||||
instance of those now-deprecated classes.
|
||||
|
||||
|
@ -228,7 +229,7 @@ Email
|
|||
* The new ``policy`` argument for :class:`EmailMessage.message()
|
||||
<django.core.mail.EmailMessage>` allows specifying the email policy, the set
|
||||
of rules for updating and serializing the representation of the message.
|
||||
Defaults to :py:data:`email.policy.default`.
|
||||
Defaults to :data:`email.policy.default`.
|
||||
|
||||
* :class:`EmailMessage.attach() <django.core.mail.EmailMessage>` now accepts a
|
||||
:class:`~email.message.MIMEPart` object from Python's modern email API.
|
||||
|
@ -402,6 +403,18 @@ backends.
|
|||
* :class:`~django.db.backends.base.schema.BaseDatabaseSchemaEditor` and
|
||||
PostgreSQL backends no longer use ``CASCADE`` when dropping a column.
|
||||
|
||||
* ``DatabaseOperations.return_insert_columns()`` and
|
||||
``DatabaseOperations.fetch_returned_insert_rows()`` methods are renamed to
|
||||
``returning_columns()`` and ``fetch_returned_rows()``, respectively, to
|
||||
denote they can be used in the context ``UPDATE … RETURNING`` statements as
|
||||
well as ``INSERT … RETURNING``.
|
||||
|
||||
* The ``DatabaseOperations.fetch_returned_insert_columns()`` method is removed
|
||||
and the ``fetch_returned_rows()`` method replacing
|
||||
``fetch_returned_insert_rows()`` expects both a ``cursor`` and
|
||||
``returning_params`` to be provided just like
|
||||
``fetch_returned_insert_columns()`` did.
|
||||
|
||||
Dropped support for MariaDB 10.5
|
||||
--------------------------------
|
||||
|
||||
|
@ -439,7 +452,7 @@ Email
|
|||
|
||||
* The undocumented ``encoding`` property of
|
||||
:class:`~django.core.mail.EmailMessage` no longer supports Python legacy
|
||||
:py:class:`email.charset.Charset` objects.
|
||||
:class:`email.charset.Charset` objects.
|
||||
|
||||
* As the internal implementations of :class:`~django.core.mail.EmailMessage`
|
||||
and :class:`~django.core.mail.EmailMultiAlternatives` have changed
|
||||
|
@ -471,7 +484,7 @@ Miscellaneous
|
|||
at the end of the output, even without the ``indent`` option set.
|
||||
|
||||
* The undocumented ``django.utils.http.parse_header_parameters()`` function is
|
||||
refactored to use Python's :py:class:`email.message.Message` for parsing.
|
||||
refactored to use Python's :class:`email.message.Message` for parsing.
|
||||
Input headers exceeding 10000 characters will now raise :exc:`ValueError`.
|
||||
|
||||
* Widgets from :mod:`django.contrib.gis.forms.widgets` now render without
|
||||
|
@ -571,7 +584,7 @@ Miscellaneous
|
|||
``django.core.mail.message.sanitize_address()`` functions are deprecated.
|
||||
|
||||
* The ``django.utils.crypto.constant_time_compare()`` function is deprecated
|
||||
because it is merely an alias of :py:func:`hmac.compare_digest`.
|
||||
because it is merely an alias of :func:`hmac.compare_digest`.
|
||||
|
||||
Features removed in 6.0
|
||||
=======================
|
||||
|
|
|
@ -45,6 +45,7 @@ versions of the documentation contain the release notes for any later releases.
|
|||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
5.1.12
|
||||
5.1.11
|
||||
5.1.10
|
||||
5.1.9
|
||||
|
@ -85,6 +86,7 @@ versions of the documentation contain the release notes for any later releases.
|
|||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
4.2.24
|
||||
4.2.23
|
||||
4.2.22
|
||||
4.2.21
|
||||
|
|
|
@ -82,6 +82,8 @@ view functions:
|
|||
* :func:`~django.views.decorators.cache.cache_control`
|
||||
* :func:`~django.views.decorators.cache.never_cache`
|
||||
* :func:`~django.views.decorators.common.no_append_slash`
|
||||
* :func:`~django.views.decorators.csp.csp_override`
|
||||
* :func:`~django.views.decorators.csp.csp_report_only_override`
|
||||
* :func:`~django.views.decorators.csrf.csrf_exempt`
|
||||
* :func:`~django.views.decorators.csrf.csrf_protect`
|
||||
* :func:`~django.views.decorators.csrf.ensure_csrf_cookie`
|
||||
|
@ -312,7 +314,7 @@ Threadlocals and contextvars values are preserved across the boundary in both
|
|||
directions.
|
||||
|
||||
:func:`async_to_sync` is essentially a more powerful version of the
|
||||
:py:func:`asyncio.run` function in Python's standard library. As well
|
||||
:func:`asyncio.run` function in Python's standard library. As well
|
||||
as ensuring threadlocals work, it also enables the ``thread_sensitive`` mode of
|
||||
:func:`sync_to_async` when that wrapper is used below it.
|
||||
|
||||
|
|
|
@ -75,7 +75,7 @@ models defined in your installed apps.
|
|||
Usage
|
||||
=====
|
||||
|
||||
:doc:`Using Django's default implementation <default>`
|
||||
:doc:`Using Django's default implementation </topics/auth/default>`
|
||||
|
||||
* :ref:`Working with User objects <user-objects>`
|
||||
* :ref:`Permissions and authorization <topic-authorization>`
|
||||
|
@ -84,6 +84,6 @@ Usage
|
|||
|
||||
:doc:`API reference for the default implementation </ref/contrib/auth>`
|
||||
|
||||
:doc:`Customizing Users and authentication <customizing>`
|
||||
:doc:`Customizing Users and authentication </topics/auth/customizing>`
|
||||
|
||||
:doc:`Password management in Django <passwords>`
|
||||
:doc:`Password management in Django </topics/auth/passwords>`
|
||||
|
|
|
@ -5,8 +5,8 @@ Using mixins with class-based views
|
|||
.. caution::
|
||||
|
||||
This is an advanced topic. A working knowledge of :doc:`Django's
|
||||
class-based views<index>` is advised before exploring these
|
||||
techniques.
|
||||
class-based views </topics/class-based-views/index>` is advised before
|
||||
exploring these techniques.
|
||||
|
||||
Django's built-in class-based views provide a lot of functionality,
|
||||
but some of it you may want to use separately. For instance, you may
|
||||
|
@ -120,9 +120,9 @@ but the main one that most people are going to use is
|
|||
``<app_label>/<model_name>_detail.html``. The ``_detail`` part can be changed
|
||||
by setting
|
||||
:attr:`~django.views.generic.detail.SingleObjectTemplateResponseMixin.template_name_suffix`
|
||||
on a subclass to something else. (For instance, the :doc:`generic edit
|
||||
views<generic-editing>` use ``_form`` for create and update views, and
|
||||
``_confirm_delete`` for delete views.)
|
||||
on a subclass to something else. (For instance, the :doc:`generic edit views
|
||||
</topics/class-based-views/generic-editing>` use ``_form`` for create and
|
||||
update views, and ``_confirm_delete`` for delete views.)
|
||||
|
||||
``ListView``: working with many Django objects
|
||||
----------------------------------------------
|
||||
|
@ -213,8 +213,8 @@ in the subclass. However if we want our processing to work on a particular
|
|||
object, identified from the URL, we'll want the functionality provided by
|
||||
:class:`~django.views.generic.detail.SingleObjectMixin`.
|
||||
|
||||
We'll demonstrate this with the ``Author`` model we used in the
|
||||
:doc:`generic class-based views introduction<generic-display>`.
|
||||
We'll demonstrate this with the ``Author`` model we used in the :doc:`generic
|
||||
class-based views introduction </topics/class-based-views/generic-display>`.
|
||||
|
||||
.. code-block:: python
|
||||
:caption: ``views.py``
|
||||
|
@ -390,11 +390,11 @@ increasingly complex as you try to do so, and a good rule of thumb is:
|
|||
|
||||
.. hint::
|
||||
|
||||
Each of your views should use only mixins or views from one of the
|
||||
groups of generic class-based views: :doc:`detail,
|
||||
list<generic-display>`, :doc:`editing<generic-editing>` and
|
||||
date. For example it's fine to combine
|
||||
:class:`TemplateView` (built in view) with
|
||||
Each of your views should use only mixins or views from one of the groups
|
||||
of generic class-based views: :doc:`detail, list
|
||||
</topics/class-based-views/generic-display>`, :doc:`editing
|
||||
</topics/class-based-views/generic-editing>` and date. For example it's
|
||||
fine to combine :class:`TemplateView` (built in view) with
|
||||
:class:`~django.views.generic.list.MultipleObjectMixin` (generic list), but
|
||||
you're likely to have problems combining ``SingleObjectMixin`` (generic
|
||||
detail) with ``MultipleObjectMixin`` (generic list).
|
||||
|
|
|
@ -1060,7 +1060,7 @@ representation of the JSON scalar ``null`` is the same as SQL ``NULL``, i.e.
|
|||
``None``. Therefore, it can be hard to distinguish between them.
|
||||
|
||||
This only applies to ``None`` as the top-level value of the field. If ``None``
|
||||
is inside a :py:class:`list` or :py:class:`dict`, it will always be interpreted
|
||||
is inside a :class:`list` or :class:`dict`, it will always be interpreted
|
||||
as JSON ``null``.
|
||||
|
||||
When querying, ``None`` value will always be interpreted as JSON ``null``. To
|
||||
|
|
|
@ -113,7 +113,7 @@ Django provides a single API to control database transactions.
|
|||
durability and can be achieved by setting ``durable=True``. If the
|
||||
``atomic`` block is nested within another it raises a ``RuntimeError``.
|
||||
|
||||
``atomic`` is usable both as a :py:term:`decorator`::
|
||||
``atomic`` is usable both as a :term:`decorator`::
|
||||
|
||||
from django.db import transaction
|
||||
|
||||
|
@ -123,7 +123,7 @@ Django provides a single API to control database transactions.
|
|||
# This code executes inside a transaction.
|
||||
do_stuff()
|
||||
|
||||
and as a :py:term:`context manager`::
|
||||
and as a :term:`context manager`::
|
||||
|
||||
from django.db import transaction
|
||||
|
||||
|
|
|
@ -418,11 +418,11 @@ The class has the following methods:
|
|||
|
||||
The keyword argument ``policy`` allows specifying the set of rules for
|
||||
updating and serializing the representation of the message. It must be an
|
||||
:py:mod:`email.policy.Policy <email.policy>` object. Defaults to
|
||||
:py:data:`email.policy.default`. In certain cases you may want to use
|
||||
:py:data:`~email.policy.SMTP`, :py:data:`~email.policy.SMTPUTF8` or a custom
|
||||
:mod:`email.policy.Policy <email.policy>` object. Defaults to
|
||||
:data:`email.policy.default`. In certain cases you may want to use
|
||||
:data:`~email.policy.SMTP`, :data:`~email.policy.SMTPUTF8` or a custom
|
||||
policy. For example, :class:`django.core.mail.backends.smtp.EmailBackend`
|
||||
uses the :py:data:`~email.policy.SMTP` policy to ensure ``\r\n`` line endings
|
||||
uses the :data:`~email.policy.SMTP` policy to ensure ``\r\n`` line endings
|
||||
as required by the SMTP protocol.
|
||||
|
||||
If you ever need to extend Django's :class:`~django.core.mail.EmailMessage`
|
||||
|
@ -432,7 +432,7 @@ The class has the following methods:
|
|||
.. versionchanged:: 6.0
|
||||
|
||||
The ``policy`` keyword argument was added and the return type was updated
|
||||
to an instance of :py:class:`~email.message.EmailMessage`.
|
||||
to an instance of :class:`~email.message.EmailMessage`.
|
||||
|
||||
* ``recipients()`` returns a list of all the recipients of the message,
|
||||
whether they're recorded in the ``to``, ``cc`` or ``bcc`` attributes. This
|
||||
|
|
|
@ -50,8 +50,8 @@ following example will create a formset class to display two blank forms:
|
|||
|
||||
Formsets can be iterated and indexed, accessing forms in the order they were
|
||||
created. You can reorder the forms by overriding the default
|
||||
:py:meth:`iteration <object.__iter__>` and
|
||||
:py:meth:`indexing <object.__getitem__>` behavior if needed.
|
||||
:meth:`iteration <object.__iter__>` and
|
||||
:meth:`indexing <object.__getitem__>` behavior if needed.
|
||||
|
||||
.. _formsets-initial-data:
|
||||
|
||||
|
|
|
@ -38,6 +38,8 @@ For example:
|
|||
>>> article = Article.objects.get(pk=1)
|
||||
>>> form = ArticleForm(instance=article)
|
||||
|
||||
.. _model-form-field-types:
|
||||
|
||||
Field types
|
||||
-----------
|
||||
|
||||
|
@ -683,6 +685,8 @@ the field declaratively and setting its ``validators`` parameter::
|
|||
See the :doc:`form field documentation </ref/forms/fields>` for more
|
||||
information on fields and their arguments.
|
||||
|
||||
.. _modelforms-enabling-localization-of-fields:
|
||||
|
||||
Enabling localization of fields
|
||||
-------------------------------
|
||||
|
||||
|
|
|
@ -129,7 +129,7 @@ have more than a single parameter. If you used positional interpolation,
|
|||
translations wouldn't be able to reorder placeholder text.
|
||||
|
||||
Since string extraction is done by the ``xgettext`` command, only syntaxes
|
||||
supported by ``gettext`` are supported by Django. Python :py:ref:`f-strings
|
||||
supported by ``gettext`` are supported by Django. Python :ref:`f-strings
|
||||
<f-strings>` cannot be used directly with ``gettext`` functions because
|
||||
f-string expressions are evaluated before they reach ``gettext``. This means
|
||||
``_(f"Welcome {name}")`` will not work as expected, as the variable is
|
||||
|
|
|
@ -204,7 +204,7 @@ therefore have performance implications, and the more expensive the work
|
|||
concerned, the more there is to gain through laziness.
|
||||
|
||||
Python provides a number of tools for lazy evaluation, particularly through the
|
||||
:py:term:`generator` and :py:term:`generator expression` constructs. It's worth
|
||||
:term:`generator` and :term:`generator expression` constructs. It's worth
|
||||
reading up on laziness in Python to discover opportunities for making use of
|
||||
lazy patterns in your code.
|
||||
|
||||
|
|
|
@ -44,7 +44,7 @@ by using an environment variable, :envvar:`DJANGO_SETTINGS_MODULE`.
|
|||
|
||||
The value of :envvar:`DJANGO_SETTINGS_MODULE` should be in Python path syntax,
|
||||
e.g. ``mysite.settings``. Note that the settings module should be on the
|
||||
Python :py:data:`sys.path`.
|
||||
Python :data:`sys.path`.
|
||||
|
||||
|
||||
The ``django-admin`` utility
|
||||
|
|
|
@ -116,7 +116,7 @@ generate signatures. You can use a different secret by passing it to the
|
|||
separate values. ``sep`` cannot be in the :rfc:`URL safe base64 alphabet
|
||||
<4648#section-5>`. This alphabet contains alphanumeric characters, hyphens,
|
||||
and underscores. ``algorithm`` must be an algorithm supported by
|
||||
:py:mod:`hashlib`, it defaults to ``'sha256'``. ``fallback_keys`` is a list
|
||||
:mod:`hashlib`, it defaults to ``'sha256'``. ``fallback_keys`` is a list
|
||||
of additional values used to validate signed data, defaults to
|
||||
:setting:`SECRET_KEY_FALLBACKS`.
|
||||
|
||||
|
@ -192,7 +192,7 @@ created within a specified period of time:
|
|||
|
||||
Checks if ``value`` was signed less than ``max_age`` seconds ago,
|
||||
otherwise raises ``SignatureExpired``. The ``max_age`` parameter can
|
||||
accept an integer or a :py:class:`datetime.timedelta` object.
|
||||
accept an integer or a :class:`datetime.timedelta` object.
|
||||
|
||||
.. method:: sign_object(obj, serializer=JSONSerializer, compress=False)
|
||||
|
||||
|
@ -203,7 +203,7 @@ created within a specified period of time:
|
|||
|
||||
Checks if ``signed_obj`` was signed less than ``max_age`` seconds ago,
|
||||
otherwise raises ``SignatureExpired``. The ``max_age`` parameter can
|
||||
accept an integer or a :py:class:`datetime.timedelta` object.
|
||||
accept an integer or a :class:`datetime.timedelta` object.
|
||||
|
||||
.. _signing-complex-data:
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user