From d0d85cd165e54582cce98cf685252e771460a9d4 Mon Sep 17 00:00:00 2001 From: Skyiesac Date: Thu, 18 Dec 2025 16:35:38 +0530 Subject: [PATCH 1/7] Fixed #36376 -- Fixed --no-color for command help in Python 3.14+. https://github.com/python/cpython/pull/136809 made `color` default to True in ArgumentParser. --- django/core/management/base.py | 7 +++++-- docs/releases/5.2.10.txt | 4 +++- docs/releases/6.0.1.txt | 4 ++++ tests/user_commands/tests.py | 28 ++++++++++++++++++++++++++++ 4 files changed, 40 insertions(+), 3 deletions(-) diff --git a/django/core/management/base.py b/django/core/management/base.py index db7a01cc4cf0..8f2447905064 100644 --- a/django/core/management/base.py +++ b/django/core/management/base.py @@ -58,8 +58,11 @@ def __init__( ): self.missing_args_message = missing_args_message self.called_from_command_line = called_from_command_line - if PY314 and not PY315: - kwargs.setdefault("suggest_on_error", True) + if PY314: + if not PY315: + kwargs.setdefault("suggest_on_error", True) + if os.environ.get("DJANGO_COLORS") == "nocolor" or "--no-color" in sys.argv: + kwargs.setdefault("color", False) super().__init__(**kwargs) def parse_args(self, args=None, namespace=None): diff --git a/docs/releases/5.2.10.txt b/docs/releases/5.2.10.txt index 35626cfedc95..0b7ab06d549e 100644 --- a/docs/releases/5.2.10.txt +++ b/docs/releases/5.2.10.txt @@ -9,4 +9,6 @@ Django 5.2.10 fixes several bugs in 5.2.9. Bugfixes ======== -* ... +* Fixed a bug where management command colorized help (introduced in + Python 3.14) ignored the :option:`--no-color` option and the + :envvar:`DJANGO_COLORS` setting (:ticket:`36376`). diff --git a/docs/releases/6.0.1.txt b/docs/releases/6.0.1.txt index a84d49b07a9a..36e533a88871 100644 --- a/docs/releases/6.0.1.txt +++ b/docs/releases/6.0.1.txt @@ -16,3 +16,7 @@ Bugfixes * Fixed a regression in Django 6.0 that prevented changing the name of a :class:`~django.db.models.ManyToManyField` from taking effect when applying migrations (:ticket:`36800`). + +* Fixed a bug where management command colorized help (introduced in + Python 3.14) ignored the :option:`--no-color` option and the + :envvar:`DJANGO_COLORS` setting (:ticket:`36376`). diff --git a/tests/user_commands/tests.py b/tests/user_commands/tests.py index afd376307aff..0997c1001713 100644 --- a/tests/user_commands/tests.py +++ b/tests/user_commands/tests.py @@ -470,6 +470,34 @@ def test_suggest_on_error_explicit_false(self): ) self.assertFalse(parser.suggest_on_error) + @unittest.skipUnless(PY314, "Only relevant for Python 3.14+") + def test_color_enabled_by_default(self): + with mock.patch.dict(os.environ, {}, clear=True): + command = BaseCommand() + parser = command.create_parser("prog_name", "subcommand") + self.assertTrue(parser.color) + + @unittest.skipUnless(PY314, "Only relevant for Python 3.14+") + def test_color_disabled_with_django_colors_nocolor(self): + with mock.patch.dict(os.environ, {"DJANGO_COLORS": "nocolor"}): + command = BaseCommand() + parser = command.create_parser("prog_name", "subcommand") + self.assertFalse(parser.color) + + @unittest.skipUnless(PY314, "Only relevant for Python 3.14+") + def test_force_color_does_not_affect_argparse_color(self): + with mock.patch.dict(os.environ, {}, clear=True): + command = BaseCommand(force_color=True) + parser = command.create_parser("prog_name", "subcommand") + self.assertTrue(parser.color) + + @unittest.skipUnless(PY314, "Only relevant for Python 3.14+") + def test_no_color_flag_disables_color(self): + with mock.patch.object(sys, "argv", ["manage.py", "mycommand", "--no-color"]): + command = BaseCommand() + parser = command.create_parser("manage.py", "mycommand") + self.assertFalse(parser.color) + class CommandRunTests(AdminScriptTestCase): """ From 9cc5c87ffb989991524ee4eb91a435d2296ded2b Mon Sep 17 00:00:00 2001 From: Clifford Gama Date: Wed, 27 Aug 2025 14:24:47 +0200 Subject: [PATCH 2/7] Replaced per-object create() calls with bulk_create in tests/model_fields/test_jsonfield.py --- tests/model_fields/test_jsonfield.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/model_fields/test_jsonfield.py b/tests/model_fields/test_jsonfield.py index d0561e14d2ea..76cdc0e421c7 100644 --- a/tests/model_fields/test_jsonfield.py +++ b/tests/model_fields/test_jsonfield.py @@ -364,14 +364,14 @@ def setUpTestData(cls): "bax": {"foo": "bar"}, }, ] - cls.objs = [NullableJSONModel.objects.create(value=value) for value in values] + objs = [NullableJSONModel(value=value) for value in values] if connection.features.supports_primitives_in_json_field: - cls.objs.extend( - [ - NullableJSONModel.objects.create(value=value) - for value in cls.primitives - ] - ) + objs.extend([NullableJSONModel(value=value) for value in cls.primitives]) + objs = NullableJSONModel.objects.bulk_create(objs) + # Some backends don't return primary keys after bulk_create. + if any(obj.pk is None for obj in objs): + objs = list(NullableJSONModel.objects.order_by("id")) + cls.objs = objs cls.raw_sql = "%s::jsonb" if connection.vendor == "postgresql" else "%s" def test_exact(self): From 6ee8e9d56c17eb0014e73189950a9e8de2a8ec0e Mon Sep 17 00:00:00 2001 From: Clifford Gama Date: Sat, 25 Oct 2025 18:41:08 +0200 Subject: [PATCH 3/7] Fixed #36508 -- Interpreted __iexact=None on KeyTransforms as __exact=None. Thanks Jacob Walls for the report. --- django/db/models/fields/json.py | 14 +++++++++++++- docs/releases/6.1.txt | 5 +++++ tests/model_fields/test_jsonfield.py | 6 ++++++ 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/django/db/models/fields/json.py b/django/db/models/fields/json.py index 71c3f4d33558..cf4f5953a75c 100644 --- a/django/db/models/fields/json.py +++ b/django/db/models/fields/json.py @@ -665,7 +665,19 @@ def as_oracle(self, compiler, connection): class KeyTransformIExact( CaseInsensitiveMixin, KeyTransformTextLookupMixin, lookups.IExact ): - pass + can_use_none_as_rhs = True + + def as_sql(self, compiler, connection): + if self.rhs is None: + # Interpret __iexact=None on KeyTextTransform as __exact=None on + # KeyTransform. + keytransform = KeyTransform(self.lhs.key_name, self.lhs.lhs) + exact_lookup = keytransform.get_lookup("exact")(keytransform, self.rhs) + # Delegate to the backend vendor method, if it exists. + vendor = connection.vendor + as_vendor = getattr(exact_lookup, f"as_{vendor}", exact_lookup.as_sql) + return as_vendor(compiler, connection) + return super().as_sql(compiler, connection) class KeyTransformIContains( diff --git a/docs/releases/6.1.txt b/docs/releases/6.1.txt index 2e6e7235d7d9..c4ecefc08a2f 100644 --- a/docs/releases/6.1.txt +++ b/docs/releases/6.1.txt @@ -400,6 +400,11 @@ Miscellaneous * The minimum supported version of SQLite is increased from 3.31.0 to 3.37.0. +* The :lookup:`iexact=None ` lookup on + :class:`~django.db.models.JSONField` key transforms now matches JSON + ``null``, to match the behavior of :lookup:`exact=None ` on key + transforms. Previously, it was interpreted as an :lookup:`isnull` lookup. + .. _deprecated-features-6.1: Features deprecated in 6.1 diff --git a/tests/model_fields/test_jsonfield.py b/tests/model_fields/test_jsonfield.py index 76cdc0e421c7..1afeef31eb1b 100644 --- a/tests/model_fields/test_jsonfield.py +++ b/tests/model_fields/test_jsonfield.py @@ -782,6 +782,12 @@ def test_none_key(self): [self.objs[4]], ) + def test_key_iexact_none(self): + self.assertSequenceEqual( + NullableJSONModel.objects.filter(value__j__iexact=None), + [self.objs[4]], + ) + def test_none_key_exclude(self): obj = NullableJSONModel.objects.create(value={"j": 1}) if connection.vendor == "oracle": From 95394443bff2cd6c5cb47c752422fe1f391bb43d Mon Sep 17 00:00:00 2001 From: Youngkwang Yang Date: Thu, 18 Dec 2025 13:49:13 +0900 Subject: [PATCH 4/7] Fixed #36786 -- Fixed XML serialization of None values in natural keys. None values in natural keys were incorrectly serialized as the string "None", causing deserialization to fail for fields like UUIDField. --- django/core/serializers/xml_serializer.py | 42 +++++++++++---- tests/serializers/models/natural.py | 28 ++++++++++ tests/serializers/test_natural.py | 66 +++++++++++++++++++++++ 3 files changed, 127 insertions(+), 9 deletions(-) diff --git a/django/core/serializers/xml_serializer.py b/django/core/serializers/xml_serializer.py index a9fe3cf01d2d..d43865c25743 100644 --- a/django/core/serializers/xml_serializer.py +++ b/django/core/serializers/xml_serializer.py @@ -134,7 +134,10 @@ def handle_fk_field(self, obj, field): # Iterable natural keys are rolled out as subelements for key_value in natural_key_value: self.xml.startElement("natural", {}) - self.xml.characters(str(key_value)) + if key_value is None: + self.xml.addQuickElement("None") + else: + self.xml.characters(str(key_value)) self.xml.endElement("natural") else: self.xml.characters(str(related_att)) @@ -160,7 +163,10 @@ def handle_m2m(value): self.xml.startElement("object", {}) for key_value in natural: self.xml.startElement("natural", {}) - self.xml.characters(str(key_value)) + if key_value is None: + self.xml.addQuickElement("None") + else: + self.xml.characters(str(key_value)) self.xml.endElement("natural") self.xml.endElement("object") else: @@ -279,7 +285,11 @@ def _handle_object(self, node): if value == base.DEFER_FIELD: deferred_fields[field] = [ [ - getInnerText(nat_node).strip() + ( + None + if nat_node.getElementsByTagName("None") + else getInnerText(nat_node).strip() + ) for nat_node in obj_node.getElementsByTagName("natural") ] for obj_node in field_node.getElementsByTagName("object") @@ -292,7 +302,11 @@ def _handle_object(self, node): value = self._handle_fk_field_node(field_node, field) if value == base.DEFER_FIELD: deferred_fields[field] = [ - getInnerText(k).strip() + ( + None + if k.getElementsByTagName("None") + else getInnerText(k).strip() + ) for k in field_node.getElementsByTagName("natural") ] else: @@ -317,16 +331,21 @@ def _handle_fk_field_node(self, node, field): Handle a node for a ForeignKey """ # Check if there is a child node named 'None', returning None if so. - if node.getElementsByTagName("None"): + natural_keys = node.getElementsByTagName("natural") + if node.getElementsByTagName("None") and not natural_keys: return None else: model = field.remote_field.model if hasattr(model._default_manager, "get_by_natural_key"): - keys = node.getElementsByTagName("natural") - if keys: + if natural_keys: # If there are 'natural' subelements, it must be a natural # key - field_value = [getInnerText(k).strip() for k in keys] + field_value = [] + for k in natural_keys: + if k.getElementsByTagName("None"): + field_value.append(None) + else: + field_value.append(getInnerText(k).strip()) try: obj = model._default_manager.db_manager( self.db @@ -367,7 +386,12 @@ def m2m_convert(n): if keys: # If there are 'natural' subelements, it must be a natural # key - field_value = [getInnerText(k).strip() for k in keys] + field_value = [] + for k in keys: + if k.getElementsByTagName("None"): + field_value.append(None) + else: + field_value.append(getInnerText(k).strip()) obj_pk = ( default_manager.db_manager(self.db) .get_by_natural_key(*field_value) diff --git a/tests/serializers/models/natural.py b/tests/serializers/models/natural.py index f32d781a7618..3b01385e8f81 100644 --- a/tests/serializers/models/natural.py +++ b/tests/serializers/models/natural.py @@ -91,3 +91,31 @@ class PostToOptOutSubclassUser(models.Model): subscribers = models.ManyToManyField( SubclassNaturalKeyOptOutUser, related_name="subscribed_posts", blank=True ) + + +class NaturalKeyWithNullableFieldManager(models.Manager): + def get_by_natural_key(self, name, optional_id): + return self.get(name=name, optional_id=optional_id) + + +class NaturalKeyWithNullableField(models.Model): + name = models.CharField(max_length=100) + optional_id = models.CharField(max_length=100, null=True, blank=True) + + objects = NaturalKeyWithNullableFieldManager() + + class Meta: + unique_together = [["name", "optional_id"]] + + def natural_key(self): + return (self.name, self.optional_id) + + +class FKToNaturalKeyWithNullable(models.Model): + ref = models.ForeignKey( + NaturalKeyWithNullableField, on_delete=models.CASCADE, null=True + ) + refs = models.ManyToManyField( + NaturalKeyWithNullableField, related_name="m2m_referrers" + ) + data = models.CharField(max_length=100, default="") diff --git a/tests/serializers/test_natural.py b/tests/serializers/test_natural.py index 322abeb7fc60..e5592f97c8ee 100644 --- a/tests/serializers/test_natural.py +++ b/tests/serializers/test_natural.py @@ -6,8 +6,10 @@ Child, FKAsPKNoNaturalKey, FKDataNaturalKey, + FKToNaturalKeyWithNullable, NaturalKeyAnchor, NaturalKeyThing, + NaturalKeyWithNullableField, NaturalPKWithDefault, PostToOptOutSubclassUser, SubclassNaturalKeyOptOutUser, @@ -280,6 +282,60 @@ def natural_key_opt_out_test(self, format): ) +def nullable_natural_key_fk_test(self, format): + target_with_none = NaturalKeyWithNullableField.objects.create( + name="test_none", + optional_id=None, + ) + target_with_value = NaturalKeyWithNullableField.objects.create( + name="test_value", + optional_id="some_id", + ) + fk_to_none = FKToNaturalKeyWithNullable.objects.create( + ref=target_with_none, + data="points_to_none", + ) + fk_to_value = FKToNaturalKeyWithNullable.objects.create( + ref=target_with_value, + data="points_to_value", + ) + objects = [target_with_none, target_with_value, fk_to_none, fk_to_value] + serialized = serializers.serialize( + format, + objects, + use_natural_foreign_keys=True, + use_natural_primary_keys=True, + ) + objs = list(serializers.deserialize(format, serialized)) + self.assertEqual(objs[2].object.ref_id, target_with_none.pk) + self.assertEqual(objs[3].object.ref_id, target_with_value.pk) + + +def nullable_natural_key_m2m_test(self, format): + target_with_none = NaturalKeyWithNullableField.objects.create( + name="test_none", + optional_id=None, + ) + target_with_value = NaturalKeyWithNullableField.objects.create( + name="test_value", + optional_id="some_id", + ) + m2m_obj = FKToNaturalKeyWithNullable.objects.create(data="m2m_test") + m2m_obj.refs.set([target_with_none, target_with_value]) + objects = [target_with_none, target_with_value, m2m_obj] + serialized = serializers.serialize( + format, + objects, + use_natural_foreign_keys=True, + use_natural_primary_keys=True, + ) + objs = list(serializers.deserialize(format, serialized)) + self.assertCountEqual( + objs[2].m2m_data["refs"], + [target_with_none.pk, target_with_value.pk], + ) + + # Dynamically register tests for each serializer register_tests( NaturalKeySerializerTests, @@ -319,3 +375,13 @@ def natural_key_opt_out_test(self, format): "test_%s_natural_key_opt_out", natural_key_opt_out_test, ) +register_tests( + NaturalKeySerializerTests, + "test_%s_nullable_natural_key_fk", + nullable_natural_key_fk_test, +) +register_tests( + NaturalKeySerializerTests, + "test_%s_nullable_natural_key_m2m", + nullable_natural_key_m2m_test, +) From 163d92c1d66e2437a676da4ac8b11291dea3290b Mon Sep 17 00:00:00 2001 From: JaeHyuck Sa Date: Sun, 21 Dec 2025 22:45:21 +0900 Subject: [PATCH 5/7] Fixed #36787 -- Fixed crash in In lookups with mixed expressions and strings. Signed-off-by: JaeHyuck Sa --- django/db/models/lookups.py | 2 +- tests/lookup/tests.py | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/django/db/models/lookups.py b/django/db/models/lookups.py index 769b9c9198be..3489fe1e4015 100644 --- a/django/db/models/lookups.py +++ b/django/db/models/lookups.py @@ -295,7 +295,7 @@ def get_prep_lookup(self): ( value if hasattr(value, "resolve_expression") - else Value(value, self.lhs.output_field) + else Value(value, getattr(self.lhs, "output_field", None)) ) for value in self.rhs ] diff --git a/tests/lookup/tests.py b/tests/lookup/tests.py index 5b9dd8e5ec8f..31f247964caa 100644 --- a/tests/lookup/tests.py +++ b/tests/lookup/tests.py @@ -1855,6 +1855,14 @@ def test_in_lookup_in_filter(self): Season.objects.filter(In(F("year"), years)).order_by("pk"), seasons ) + def test_in_lookup_in_filter_text_field(self): + self.assertSequenceEqual( + Season.objects.filter( + In(F("nulled_text_field"), [F("nulled_text_field"), "special_value"]) + ), + [self.s2], + ) + def test_filter_lookup_lhs(self): qs = Season.objects.annotate(before_20=LessThan(F("year"), 2000)).filter( before_20=LessThan(F("year"), 1900), From cc8ee496a5293ecf7155d61c6052905c92db3ca0 Mon Sep 17 00:00:00 2001 From: ankan0503 Date: Wed, 19 Nov 2025 21:30:02 +0530 Subject: [PATCH 6/7] Refs #36305 -- Fixed indentation in checks and middleware documentation. --- docs/ref/checks.txt | 72 +++++++++++++++---------------- docs/ref/middleware.txt | 96 +++++++++++++++++++++-------------------- 2 files changed, 85 insertions(+), 83 deletions(-) diff --git a/docs/ref/checks.txt b/docs/ref/checks.txt index 7250df692f11..16f0c5dac474 100644 --- a/docs/ref/checks.txt +++ b/docs/ref/checks.txt @@ -19,42 +19,42 @@ API reference .. class:: CheckMessage(level, msg, hint=None, obj=None, id=None) -The warnings and errors raised by system checks must be instances of -``CheckMessage``. An instance encapsulates a single reportable error or -warning. It also provides context and hints applicable to the message, and a -unique identifier that is used for filtering purposes. - -Constructor arguments are: - -``level`` - The severity of the message. Use one of the predefined values: ``DEBUG``, - ``INFO``, ``WARNING``, ``ERROR``, ``CRITICAL``. If the level is greater or - equal to ``ERROR``, then Django will prevent management commands from - executing. Messages with level lower than ``ERROR`` (i.e. warnings) are - reported to the console, but can be silenced. - -``msg`` - A short (less than 80 characters) string describing the problem. The string - should *not* contain newlines. - -``hint`` - A single-line string providing a hint for fixing the problem. If no hint - can be provided, or the hint is self-evident from the error message, the - hint can be omitted, or a value of ``None`` can be used. - -``obj`` - Optional. An object providing context for the message (for example, the - model where the problem was discovered). The object should be a model, - field, or manager or any other object that defines a ``__str__()`` method. - The method is used while reporting all messages and its result precedes the - message. - -``id`` - Optional string. A unique identifier for the issue. Identifiers should - follow the pattern ``applabel.X001``, where ``X`` is one of the letters - ``CEWID``, indicating the message severity (``C`` for criticals, ``E`` for - errors and so). The number can be allocated by the application, but should - be unique within that application. + The warnings and errors raised by system checks must be instances of + ``CheckMessage``. An instance encapsulates a single reportable error or + warning. It also provides context and hints applicable to the message, and + a unique identifier that is used for filtering purposes. + + Constructor arguments are: + + ``level`` + The severity of the message. Use one of the predefined values: ``DEBUG`` + , ``INFO``, ``WARNING``, ``ERROR``, ``CRITICAL``. If the level is + greater or equal to ``ERROR``, then Django will prevent management + commands from executing. Messages with level lower than ``ERROR`` + (i.e. warnings) are reported to the console, but can be silenced. + + ``msg`` + A short (less than 80 characters) string describing the problem. The + string should *not* contain newlines. + + ``hint`` + A single-line string providing a hint for fixing the problem. If no hint + can be provided, or the hint is self-evident from the error message, the + hint can be omitted, or a value of ``None`` can be used. + + ``obj`` + Optional. An object providing context for the message (for example, the + model where the problem was discovered). The object should be a model, + field, or manager or any other object that defines a ``__str__()`` + method. The method is used while reporting all messages and its result + precedes the message. + + ``id`` + Optional string. A unique identifier for the issue. Identifiers should + follow the pattern ``applabel.X001``, where ``X`` is one of the letters + ``CEWID``, indicating the message severity (``C`` for criticals, ``E`` + for errors and so). The number can be allocated by the application, but + should be unique within that application. There are subclasses to make creating messages with common levels easier. When using them you can omit the ``level`` argument because it is implied by the diff --git a/docs/ref/middleware.txt b/docs/ref/middleware.txt index 29e8f7b9416e..a9638cf36e5c 100644 --- a/docs/ref/middleware.txt +++ b/docs/ref/middleware.txt @@ -147,14 +147,14 @@ Conditional GET middleware .. class:: ConditionalGetMiddleware -Handles conditional GET operations. If the response doesn't have an ``ETag`` -header, the middleware adds one if needed. If the response has an ``ETag`` or -``Last-Modified`` header, and the request has ``If-None-Match`` or -``If-Modified-Since``, the response is replaced by an -:class:`~django.http.HttpResponseNotModified`. + Handles conditional GET operations. If the response doesn't have an + ``ETag`` header, the middleware adds one if needed. If the response has an + ``ETag`` or ``Last-Modified`` header, and the request has ``If-None-Match`` + or ``If-Modified-Since``, the response is replaced by an + :class:`~django.http.HttpResponseNotModified`. -You can handle conditional GET operations with individual views using the -:func:`~django.views.decorators.http.conditional_page` decorator. + You can handle conditional GET operations with individual views using the + :func:`~django.views.decorators.http.conditional_page` decorator. Locale middleware ----------------- @@ -170,9 +170,9 @@ Locale middleware ``LocaleMiddleware`` and override the attribute to customize the redirects issued by the middleware. -Enables language selection based on data from the request. It customizes -content for each user. See the :doc:`internationalization documentation -`. + Enables language selection based on data from the request. It customizes + content for each user. See the :doc:`internationalization documentation + `. Message middleware ------------------ @@ -182,8 +182,8 @@ Message middleware .. class:: MessageMiddleware -Enables cookie- and session-based message support. See the -:doc:`messages documentation `. + Enables cookie- and session-based message support. See the + :doc:`messages documentation `. .. _security-middleware: @@ -202,19 +202,19 @@ Security middleware .. class:: SecurityMiddleware -The ``django.middleware.security.SecurityMiddleware`` provides several security -enhancements to the request/response cycle. Each one can be independently -enabled or disabled with a setting. + The ``django.middleware.security.SecurityMiddleware`` provides several + security enhancements to the request/response cycle. Each one can be + independently enabled or disabled with a setting. -* :setting:`SECURE_CONTENT_TYPE_NOSNIFF` -* :setting:`SECURE_CROSS_ORIGIN_OPENER_POLICY` -* :setting:`SECURE_HSTS_INCLUDE_SUBDOMAINS` -* :setting:`SECURE_HSTS_PRELOAD` -* :setting:`SECURE_HSTS_SECONDS` -* :setting:`SECURE_REDIRECT_EXEMPT` -* :setting:`SECURE_REFERRER_POLICY` -* :setting:`SECURE_SSL_HOST` -* :setting:`SECURE_SSL_REDIRECT` + * :setting:`SECURE_CONTENT_TYPE_NOSNIFF` + * :setting:`SECURE_CROSS_ORIGIN_OPENER_POLICY` + * :setting:`SECURE_HSTS_INCLUDE_SUBDOMAINS` + * :setting:`SECURE_HSTS_PRELOAD` + * :setting:`SECURE_HSTS_SECONDS` + * :setting:`SECURE_REDIRECT_EXEMPT` + * :setting:`SECURE_REFERRER_POLICY` + * :setting:`SECURE_SSL_HOST` + * :setting:`SECURE_SSL_REDIRECT` .. _http-strict-transport-security: @@ -339,11 +339,13 @@ this setting are: Instructs the browser to send the full URL as the referrer for same-origin links, and only the origin for cross-origin links. -``same-origin`` Instructs the browser to send a full URL, but only for -same-origin links. No referrer will be sent for cross-origin links. +``same-origin`` + Instructs the browser to send a full URL, but only for + same-origin links. No referrer will be sent for cross-origin links. -``strict-origin`` Instructs the browser to send only the origin, not the full -URL, and to send no referrer when a protocol downgrade occurs. +``strict-origin`` + Instructs the browser to send only the origin, not the full + URL, and to send no referrer when a protocol downgrade occurs. ``strict-origin-when-cross-origin`` Instructs the browser to send the full URL when the link is same-origin and @@ -470,8 +472,8 @@ Session middleware .. class:: SessionMiddleware -Enables session support. See the :doc:`session documentation -`. + Enables session support. See the :doc:`session documentation + `. Site middleware --------------- @@ -481,8 +483,8 @@ Site middleware .. class:: CurrentSiteMiddleware -Adds the ``site`` attribute representing the current site to every incoming -``HttpRequest`` object. See the :ref:`sites documentation `. + Adds the ``site`` attribute representing the current site to every incoming + ``HttpRequest`` object. See the :ref:`sites documentation `. Authentication middleware ------------------------- @@ -492,9 +494,9 @@ Authentication middleware .. class:: AuthenticationMiddleware -Adds the ``user`` attribute, representing the currently-logged-in user, to -every incoming ``HttpRequest`` object. See :ref:`Authentication in web requests -`. + Adds the ``user`` attribute, representing the currently-logged-in user, to + every incoming ``HttpRequest`` object. See :ref:`Authentication in web + requests `. .. class:: LoginRequiredMiddleware @@ -573,14 +575,14 @@ Customize the login URL or field name for authenticated views with the .. class:: RemoteUserMiddleware -Middleware for utilizing web server provided authentication. See -:doc:`/howto/auth-remote-user` for usage details. + Middleware for utilizing web server provided authentication. See + :doc:`/howto/auth-remote-user` for usage details. .. class:: PersistentRemoteUserMiddleware -Middleware for utilizing web server provided authentication when enabled only -on the login page. See :ref:`persistent-remote-user-middleware-howto` for usage -details. + Middleware for utilizing web server provided authentication when enabled + only on the login page. See :ref:`persistent-remote-user-middleware-howto` + for usage details. CSRF protection middleware -------------------------- @@ -589,12 +591,12 @@ CSRF protection middleware .. class:: CsrfViewMiddleware -Adds protection against Cross Site Request Forgeries by adding hidden form -fields to POST forms and checking requests for the correct value. See the -:doc:`Cross Site Request Forgery protection documentation `. + Adds protection against Cross Site Request Forgeries by adding hidden form + fields to POST forms and checking requests for the correct value. See the + :doc:`Cross Site Request Forgery protection documentation `. -You can add Cross Site Request Forgery protection to individual views using the -:func:`~django.views.decorators.csrf.csrf_protect` decorator. + You can add Cross Site Request Forgery protection to individual views + using the :func:`~django.views.decorators.csrf.csrf_protect` decorator. ``X-Frame-Options`` middleware ------------------------------ @@ -603,8 +605,8 @@ You can add Cross Site Request Forgery protection to individual views using the .. class:: XFrameOptionsMiddleware -Simple :doc:`clickjacking protection via the X-Frame-Options header -`. + Simple :doc:`clickjacking protection via the X-Frame-Options header + `. Content Security Policy middleware ---------------------------------- From bddcefb00f555196d3c488fbad71d303e9f7ede1 Mon Sep 17 00:00:00 2001 From: ankan0503 Date: Wed, 19 Nov 2025 22:28:51 +0530 Subject: [PATCH 7/7] Fixed #36305 -- Added documentation indentation guidelines to contributing docs. --- .../contributing/writing-documentation.txt | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/docs/internals/contributing/writing-documentation.txt b/docs/internals/contributing/writing-documentation.txt index 42e8aa7a89ad..b519fdbd8670 100644 --- a/docs/internals/contributing/writing-documentation.txt +++ b/docs/internals/contributing/writing-documentation.txt @@ -420,6 +420,43 @@ documentation: * Use :rst:role:`:cve:` to reference a Common Vulnerabilities and Exposures (CVE) identifier. For example, use ``:cve:`2019-14232```. +* When documenting Python objects (classes, methods, attributes, etc.) using + `Sphinx directives`__ such as ``.. class::``, ``.. method::``, and + ``.. attribute::``, all content must be properly indented to ensure correct + rendering and to support features like automatic table of contents + generation. + + Follow these rules: + + * The directive itself remains flush with the left margin (no indentation). + * All descriptive text under the directive must be indented by 4 spaces. + * Multi-line descriptions must keep the same indentation level. + * Nested directives (for example, methods inside a class) require an + additional 4 spaces of indentation to maintain hierarchy. + * Field lists (such as ``:param:``, ``:returns:``, etc.) must align with the + directive's content level. + + Example: + + .. code-block:: rst + + .. class:: MyClass + + A brief description of the class. + + .. method:: my_method(arg1, arg2) + + Method description. + + :param arg1: Description of the first parameter + :param arg2: Description of the second parameter + + .. attribute:: my_attribute + + Attribute description. + +__ https://www.sphinx-doc.org/en/master/usage/restructuredtext/basics.html + Django-specific markup ======================