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 .github/workflows/schedule_tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ jobs:
name: Selenium tests, PostgreSQL
services:
postgres:
image: postgres:14-alpine
image: postgres:15-alpine
env:
POSTGRES_DB: django
POSTGRES_USER: user
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/selenium.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ jobs:
name: PostgreSQL
services:
postgres:
image: postgres:14-alpine
image: postgres:15-alpine
env:
POSTGRES_DB: django
POSTGRES_USER: user
Expand Down
2 changes: 1 addition & 1 deletion django/contrib/gis/db/backends/postgis/operations.py
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ def spatial_version(self):
raise ImproperlyConfigured(
'Cannot determine PostGIS version for database "%s" '
'using command "SELECT postgis_lib_version()". '
"GeoDjango requires at least PostGIS version 3.1. "
"GeoDjango requires at least PostGIS version 3.2. "
"Was the database created from a spatial database "
"template?" % self.connection.settings_dict["NAME"]
)
Expand Down
11 changes: 2 additions & 9 deletions django/db/backends/postgresql/features.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@


class DatabaseFeatures(BaseDatabaseFeatures):
minimum_database_version = (14,)
minimum_database_version = (15,)
allows_group_by_selected_pks = True
can_return_columns_from_insert = True
can_return_rows_from_bulk_insert = True
Expand Down Expand Up @@ -67,6 +67,7 @@ class DatabaseFeatures(BaseDatabaseFeatures):
supports_update_conflicts_with_target = True
supports_covering_indexes = True
supports_stored_generated_columns = True
supports_nulls_distinct_unique_constraints = True
can_rename_index = True
test_collations = {
"deterministic": "C",
Expand Down Expand Up @@ -155,10 +156,6 @@ def introspected_field_types(self):
"PositiveSmallIntegerField": "SmallIntegerField",
}

@cached_property
def is_postgresql_15(self):
return self.connection.pg_version >= 150000

@cached_property
def is_postgresql_16(self):
return self.connection.pg_version >= 160000
Expand All @@ -172,10 +169,6 @@ def is_postgresql_18(self):
return self.connection.pg_version >= 180000

supports_unlimited_charfield = True
supports_nulls_distinct_unique_constraints = property(
operator.attrgetter("is_postgresql_15")
)

supports_any_value = property(operator.attrgetter("is_postgresql_16"))
supports_virtual_generated_columns = property(
operator.attrgetter("is_postgresql_18")
Expand Down
6 changes: 3 additions & 3 deletions django/views/i18n.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@ def builtin_template_path(name):

def set_language(request):
"""
Redirect to a given URL while setting the chosen language in the session
(if enabled) and in a cookie. The URL and the language code need to be
specified in the request parameters.
Redirect to a given URL while setting the chosen language in the language
cookie. The URL and the language code need to be specified in the request
parameters.

Since this view changes how the user will see the rest of the site, it must
only be accessed as a POST request. If called as a GET request, it will
Expand Down
4 changes: 2 additions & 2 deletions docs/ref/contrib/gis/install/geolibs.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ Program Description Required
`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
`PostGIS`__ Spatial extensions for PostgreSQL Yes (PostgreSQL only) 3.6, 3.5, 3.4, 3.3, 3.2
`SpatiaLite`__ Spatial extensions for SQLite Yes (SQLite only) 5.1, 5.0, 4.3
============================== ==================================== ================================ =======================================================

Expand All @@ -44,11 +44,11 @@ totally fine with GeoDjango. Your mileage may vary.
GDAL 3.9.0 2024-05-10
GDAL 3.10.0 2024-11-06
GDAL 3.11.0 2025-05-09
PostGIS 3.1.0 2020-12-18
PostGIS 3.2.0 2021-12-18
PostGIS 3.3.0 2022-08-27
PostGIS 3.4.0 2023-08-15
PostGIS 3.5.0 2024-09-25
PostGIS 3.6.0 2025-09-02
PROJ 9.0.0 2022-03-01
PROJ 8.0.0 2021-03-01
PROJ 8.0.0 2021-03-01
Expand Down
8 changes: 4 additions & 4 deletions docs/ref/contrib/gis/install/index.txt
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ supported versions, and any notes for each of the supported database backends:
================== ============================== ================== =========================================
Database Library Requirements Supported Versions Notes
================== ============================== ================== =========================================
PostgreSQL GEOS, GDAL, PROJ, PostGIS 14+ Requires PostGIS.
PostgreSQL GEOS, GDAL, PROJ, PostGIS 15+ Requires PostGIS.
MySQL GEOS, GDAL 8.0.11+ :ref:`Limited functionality <mysql-spatial-limitations>`.
Oracle GEOS, GDAL 19+ XE not supported.
SQLite GEOS, GDAL, PROJ, SpatiaLite 3.31.0+ Requires SpatiaLite 4.3+
Expand Down Expand Up @@ -305,7 +305,7 @@ Summary:

.. code-block:: shell

$ sudo port install postgresql14-server
$ sudo port install postgresql15-server
$ sudo port install geos
$ sudo port install proj6
$ sudo port install postgis3
Expand All @@ -319,14 +319,14 @@ Summary:

.. code-block:: shell

export PATH=/opt/local/bin:/opt/local/lib/postgresql14/bin
export PATH=/opt/local/bin:/opt/local/lib/postgresql15/bin

In addition, add the ``DYLD_FALLBACK_LIBRARY_PATH`` setting so that
the libraries can be found by Python:

.. code-block:: shell

export DYLD_FALLBACK_LIBRARY_PATH=/opt/local/lib:/opt/local/lib/postgresql14
export DYLD_FALLBACK_LIBRARY_PATH=/opt/local/lib:/opt/local/lib/postgresql15

__ https://www.macports.org/

Expand Down
2 changes: 1 addition & 1 deletion docs/ref/contrib/postgres/aggregates.txt
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ General-purpose aggregation functions
.. class:: BitXor(expression, filter=None, default=None, **extra)

Returns an ``int`` of the bitwise ``XOR`` of all non-null input values, or
``default`` if all values are null. It requires PostgreSQL 14+.
``default`` if all values are null.

``BoolAnd``
-----------
Expand Down
3 changes: 1 addition & 2 deletions docs/ref/contrib/postgres/constraints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -130,8 +130,7 @@ used for queries that select only included fields
(:attr:`~ExclusionConstraint.include`) and filter only by indexed fields
(:attr:`~ExclusionConstraint.expressions`).

``include`` is supported for GiST indexes. PostgreSQL 14+ also supports
``include`` for SP-GiST indexes.
``include`` is supported for GiST and SP-GiST indexes.

``violation_error_code``
------------------------
Expand Down
2 changes: 1 addition & 1 deletion docs/ref/databases.txt
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ below for information on how to set up your database correctly.
PostgreSQL notes
================

Django supports PostgreSQL 14 and higher. `psycopg`_ 3.1.12+ or `psycopg2`_
Django supports PostgreSQL 15 and higher. `psycopg`_ 3.1.12+ or `psycopg2`_
2.9.9+ is required, though the latest `psycopg`_ 3.1.12+ is recommended.

.. note::
Expand Down
2 changes: 1 addition & 1 deletion docs/ref/models/constraints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,7 @@ creates a unique constraint that only allows one row to store a ``NULL`` value
in the ``ordering`` column.

Unique constraints with ``nulls_distinct`` are ignored for databases besides
PostgreSQL 15+.
PostgreSQL.

``violation_error_code``
------------------------
Expand Down
5 changes: 2 additions & 3 deletions docs/ref/models/indexes.txt
Original file line number Diff line number Diff line change
Expand Up @@ -214,9 +214,8 @@ See the PostgreSQL documentation for more details about `covering indexes`_.

.. admonition:: Restrictions on PostgreSQL

PostgreSQL supports covering B-Tree and :class:`GiST indexes
<django.contrib.postgres.indexes.GistIndex>`. PostgreSQL 14+ also supports
covering :class:`SP-GiST indexes
PostgreSQL supports covering B-Tree, :class:`GiST indexes
<django.contrib.postgres.indexes.GistIndex>`, and :class:`SP-GiST indexes
<django.contrib.postgres.indexes.SpGistIndex>`.

.. _covering indexes: https://www.postgresql.org/docs/current/indexes-index-only-scans.html
11 changes: 11 additions & 0 deletions docs/releases/6.1.txt
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,17 @@ backends.
database has native support for ``DurationField``, override this method to
simply return the value.

:mod:`django.contrib.gis`
-------------------------

* Support for PostGIS 3.1 is removed.

Dropped support for PostgreSQL 14
---------------------------------

Upstream support for PostgreSQL 14 ends in November 2026. Django 6.1 supports
PostgreSQL 15 and higher.

Miscellaneous
-------------

Expand Down
7 changes: 3 additions & 4 deletions docs/topics/i18n/translation.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1884,10 +1884,9 @@ Activate this view by adding the following line to your URLconf::
language-independent itself to work correctly.

The view expects to be called via the ``POST`` method, with a ``language``
parameter set in request. If session support is enabled, the view saves the
language choice in the user's session. It also saves the language choice in a
cookie that is named ``django_language`` by default. (The name can be changed
through the :setting:`LANGUAGE_COOKIE_NAME` setting.)
parameter set in request. The view saves the language choice in a cookie that
is named ``django_language`` by default. (The name can be changed through the
:setting:`LANGUAGE_COOKIE_NAME` setting.)

After setting the language choice, Django looks for a ``next`` parameter in the
``POST`` or ``GET`` data. If that is found and Django considers it to be a safe
Expand Down
8 changes: 4 additions & 4 deletions tests/backends/postgresql/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -549,12 +549,12 @@ def test_copy_cursors(self):

def test_get_database_version(self):
new_connection = no_pool_connection()
new_connection.pg_version = 140009
self.assertEqual(new_connection.get_database_version(), (14, 9))
new_connection.pg_version = 150009
self.assertEqual(new_connection.get_database_version(), (15, 9))

@mock.patch.object(connection, "get_database_version", return_value=(13,))
@mock.patch.object(connection, "get_database_version", return_value=(14,))
def test_check_database_version_supported(self, mocked_get_database_version):
msg = "PostgreSQL 14 or later is required (found 13)."
msg = "PostgreSQL 15 or later is required (found 14)."
with self.assertRaisesMessage(NotSupportedError, msg):
connection.check_database_version_supported()
self.assertTrue(mocked_get_database_version.called)
Expand Down