Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 16 additions & 1 deletion django/core/serializers/python.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,15 @@ def queryset_iterator(obj, field):
chunk_size = (
2000 if getattr(attr, "prefetch_cache_name", None) else None
)
return attr.iterator(chunk_size)
query_set = attr.all()
if not query_set.totally_ordered:
current_ordering = (
query_set.query.order_by
or query_set.model._meta.ordering
or []
)
query_set = query_set.order_by(*current_ordering, "pk")
return query_set.iterator(chunk_size)

else:

Expand All @@ -86,6 +94,13 @@ def m2m_value(value):

def queryset_iterator(obj, field):
query_set = getattr(obj, field.name).select_related(None).only("pk")
if not query_set.totally_ordered:
current_ordering = (
query_set.query.order_by
or query_set.model._meta.ordering
or []
)
query_set = query_set.order_by(*current_ordering, "pk")
chunk_size = 2000 if query_set._prefetch_related_lookups else None
return query_set.iterator(chunk_size=chunk_size)

Expand Down
17 changes: 16 additions & 1 deletion django/core/serializers/xml_serializer.py
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,15 @@ def queryset_iterator(obj, field):
chunk_size = (
2000 if getattr(attr, "prefetch_cache_name", None) else None
)
return attr.iterator(chunk_size)
query_set = attr.all()
if not query_set.totally_ordered:
current_ordering = (
query_set.query.order_by
or query_set.model._meta.ordering
or []
)
query_set = query_set.order_by(*current_ordering, "pk")
return query_set.iterator(chunk_size)

else:

Expand All @@ -186,6 +194,13 @@ def handle_m2m(value):

def queryset_iterator(obj, field):
query_set = getattr(obj, field.name).select_related(None).only("pk")
if not query_set.totally_ordered:
current_ordering = (
query_set.query.order_by
or query_set.model._meta.ordering
or []
)
query_set = query_set.order_by(*current_ordering, "pk")
chunk_size = 2000 if query_set._prefetch_related_lookups else None
return query_set.iterator(chunk_size=chunk_size)

Expand Down
13 changes: 10 additions & 3 deletions docs/internals/security.txt
Original file line number Diff line number Diff line change
Expand Up @@ -347,8 +347,10 @@ will not issue patches or new releases for those versions.
Security issue severity levels
==============================

The severity level of a security vulnerability is determined by the attack
type.
The severity level of a security vulnerability is determined primarily by the
attack type. The Django Security Team retains the authority to adjust severity
levels based on the specific characteristics, context, and potential real-world
impact of individual vulnerabilities.

Severity levels are:

Expand All @@ -361,16 +363,21 @@ Severity levels are:

* Cross site scripting (XSS)
* Cross site request forgery (CSRF)
* Denial-of-service attacks
* Broken authentication

* **Low**

* Denial-of-service attacks
* Sensitive data exposure
* Broken session management
* Unvalidated redirects/forwards
* Issues requiring an uncommon configuration option

For example, a denial-of-service vulnerability that is exploitable by
unauthenticated attackers and affects default Django configurations, causing
severe performance degradation or service unavailability, may be elevated to
**Moderate**, given the potential impact across the Django ecosystem.

.. _security-disclosure:

How Django discloses security issues
Expand Down
2 changes: 2 additions & 0 deletions tests/admin_scripts/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ def run_test(self, args, settings_file=None, apps=None, umask=-1):
python_path.extend(ext_backend_base_dirs)
test_environ["PYTHONPATH"] = os.pathsep.join(python_path)
test_environ["PYTHONWARNINGS"] = ""
test_environ["PYTHON_COLORS"] = "0"

p = subprocess.run(
[sys.executable, *args],
Expand Down Expand Up @@ -2551,6 +2552,7 @@ def _test(self, args, option_b="'2'"):
)


@mock.patch.dict(os.environ, {"PYTHON_COLORS": "0"})
class ExecuteFromCommandLine(SimpleTestCase):
def test_program_name_from_argv(self):
"""
Expand Down
23 changes: 22 additions & 1 deletion tests/serializers/test_natural.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
from unittest import mock

from django.core import serializers
from django.db import connection
from django.db import connection, models
from django.test import TestCase

from .models import (
Expand Down Expand Up @@ -336,6 +338,20 @@ def nullable_natural_key_m2m_test(self, format):
)


def natural_key_m2m_totally_ordered_test(self, format):
t1 = NaturalKeyThing.objects.create(key="t1")
t2 = NaturalKeyThing.objects.create(key="t2")
t3 = NaturalKeyThing.objects.create(key="t3")
t1.other_things.add(t2, t3)

with mock.patch.object(models.QuerySet, "order_by") as mock_order_by:
serializers.serialize(format, [t1], use_natural_foreign_keys=True)
mock_order_by.assert_called_once_with("pk")
mock_order_by.reset_mock()
serializers.serialize(format, [t1], use_natural_foreign_keys=False)
mock_order_by.assert_called_once_with("pk")


# Dynamically register tests for each serializer
register_tests(
NaturalKeySerializerTests,
Expand Down Expand Up @@ -385,3 +401,8 @@ def nullable_natural_key_m2m_test(self, format):
"test_%s_nullable_natural_key_m2m",
nullable_natural_key_m2m_test,
)
register_tests(
NaturalKeySerializerTests,
"test_%s_natural_key_m2m_totally_ordered",
natural_key_m2m_totally_ordered_test,
)
2 changes: 2 additions & 0 deletions tests/test_runner/test_debug_sql.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import logging
import os
import unittest
from io import StringIO
from time import time
Expand Down Expand Up @@ -183,6 +184,7 @@ def test_log_record_sql_extra_none(self):
@unittest.skipUnless(
connection.vendor == "sqlite", "Only run on sqlite so we can check output SQL."
)
@mock.patch.dict(os.environ, {"PYTHON_COLORS": "0"})
class TestDebugSQL(unittest.TestCase):
class PassingTest(TestCase):
def runTest(self):
Expand Down
2 changes: 2 additions & 0 deletions tests/test_utils/test_simpletestcase.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import os
import unittest
from io import StringIO
from unittest import mock
Expand All @@ -19,6 +20,7 @@ def skipped_test(self):
pass


@mock.patch.dict(os.environ, {"PYTHON_COLORS": "0"})
@mock.patch.object(ErrorTestCase, "_post_teardown")
@mock.patch.object(ErrorTestCase, "_pre_setup")
class DebugInvocationTests(SimpleTestCase):
Expand Down