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
2 changes: 1 addition & 1 deletion django/db/models/sql/query.py
Original file line number Diff line number Diff line change
Expand Up @@ -1444,7 +1444,7 @@ def build_lookup(self, lookups, lhs, rhs):
# DEFAULT_DB_ALIAS isn't nice but it's the best that can be done here.
# A similar thing is done in is_nullable(), too.
if (
lookup_name == "exact"
lookup_name in ("exact", "iexact")
and lookup.rhs == ""
and connections[DEFAULT_DB_ALIAS].features.interprets_empty_strings_as_nulls
):
Expand Down
2 changes: 1 addition & 1 deletion docs/internals/contributing/writing-code/unit-tests.txt
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ default environments can be seen as follows:
docs
isort>=7.0.0
lint-docs
zizmor>=1.16.3
zizmor>=1.19.0

Testing other Python versions and database backends
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Expand Down
6 changes: 6 additions & 0 deletions docs/releases/6.0.txt
Original file line number Diff line number Diff line change
Expand Up @@ -481,6 +481,12 @@ Miscellaneous
* The minimum supported version of ``asgiref`` is increased from 3.8.1 to
3.9.1.

.. currentmodule:: django.db.models

* :meth:`Field.pre_save` may now be called more than once when saving model
instances, so custom implementations should be idempotent and free of side
effects.

.. _deprecated-features-6.0:

Features deprecated in 6.0
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"npm": ">=1.3.0"
},
"devDependencies": {
"eslint": "^9.36.0",
"eslint": "^9.39.1",
"puppeteer": "^24.22.0",
"grunt": "^1.6.1",
"grunt-cli": "^1.5.0",
Expand Down
2 changes: 1 addition & 1 deletion tests/null_queries/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ class Poll(models.Model):

class Choice(models.Model):
poll = models.ForeignKey(Poll, models.CASCADE)
choice = models.CharField(max_length=200)
choice = models.CharField(max_length=200, null=True)


# A set of models with an inner one pointing to two outer ones.
Expand Down
14 changes: 13 additions & 1 deletion tests/null_queries/tests.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from django.core.exceptions import FieldError
from django.test import TestCase
from django.test import TestCase, skipUnlessDBFeature

from .models import Choice, Inner, OuterA, OuterB, Poll

Expand Down Expand Up @@ -44,6 +44,18 @@ def test_none_as_null(self):
with self.assertRaisesMessage(ValueError, "Cannot use None as a query value"):
Choice.objects.filter(id__gt=None)

@skipUnlessDBFeature("interprets_empty_strings_as_nulls")
def test_empty_string_is_null(self):
p = Poll.objects.create(question="?")
c1 = Choice.objects.create(poll=p, choice=None)
c2 = Choice.objects.create(poll=p, choice="")
cases = [{"choice__exact": ""}, {"choice__iexact": ""}]
for lookup in cases:
with self.subTest(lookup):
self.assertSequenceEqual(
Choice.objects.filter(**lookup).order_by("id"), [c1, c2]
)

def test_unsaved(self):
poll = Poll(question="How?")
msg = (
Expand Down
2 changes: 1 addition & 1 deletion tests/requirements/py3.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ aiosmtpd >= 1.4.5
asgiref >= 3.9.1
argon2-cffi >= 23.1.0
bcrypt >= 4.1.1
black >= 25.9.0
black >= 25.12.0
docutils >= 0.22
geoip2 >= 4.8.0
jinja2 >= 2.11.0
Expand Down
2 changes: 1 addition & 1 deletion tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ commands =
[testenv:zizmor]
basepython = python3
usedevelop = false
deps = zizmor >= 1.16.3
deps = zizmor >= 1.19.0
changedir = {toxinidir}
commands =
zizmor .