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
12 changes: 0 additions & 12 deletions django/contrib/admin/static/admin/js/SelectFilter2.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,6 @@ Requires core.js and SelectBox.js.
from_box.setAttribute('aria-labelledby', field_id + '_from_label');
from_box.setAttribute('aria-describedby', `${field_id}_helptext ${field_id}_choose_helptext`);

for (const p of from_box.parentNode.getElementsByTagName('p')) {
if (p.classList.contains("info")) {
// Remove <p class="info">, because it just gets in the way.
from_box.parentNode.removeChild(p);
} else if (p.classList.contains("help")) {
// Move help text up to the top so it isn't below the select
// boxes or wrapped off on the side to the right of the add
// button:
from_box.parentNode.insertBefore(p, from_box.parentNode.firstChild);
}
}

// <div class="selector"> or <div class="selector stacked">
const selector_div = quickElement('div', from_box.parentNode);
// Make sure the selector div appears between the label and the add link.
Expand Down
5 changes: 5 additions & 0 deletions django/contrib/postgres/apps.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,11 @@ def ready(self):
3910: "django.contrib.postgres.fields.DateTimeRangeField",
3912: "django.contrib.postgres.fields.DateRangeField",
3926: "django.contrib.postgres.fields.BigIntegerRangeField",
# PostgreSQL OIDs may vary depending on the
# installation, especially for datatypes from
# extensions, e.g. "hstore". In such cases, the
# type_display attribute (psycopg 3.2+) should be used.
"hstore": "django.contrib.postgres.fields.HStoreField",
}
)
if conn.connection is not None:
Expand Down
2 changes: 2 additions & 0 deletions django/db/backends/postgresql/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import threading
import warnings
from contextlib import contextmanager
from functools import lru_cache

from django.conf import settings
from django.core.exceptions import ImproperlyConfigured
Expand All @@ -29,6 +30,7 @@
raise ImproperlyConfigured("Error loading psycopg2 or psycopg module")


@lru_cache
def psycopg_version():
version = Database.__version__.split(" ", 1)[0]
return get_version_tuple(version)
Expand Down
12 changes: 11 additions & 1 deletion django/db/backends/postgresql/introspection.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from django.db.backends.base.introspection import BaseDatabaseIntrospection
from django.db.backends.base.introspection import FieldInfo as BaseFieldInfo
from django.db.backends.base.introspection import TableInfo as BaseTableInfo
from django.db.backends.postgresql.base import psycopg_version
from django.db.models import DB_CASCADE, DB_SET_DEFAULT, DB_SET_NULL, DO_NOTHING, Index

FieldInfo = namedtuple("FieldInfo", [*BaseFieldInfo._fields, "is_autofield", "comment"])
Expand Down Expand Up @@ -120,10 +121,19 @@ def get_table_description(self, cursor, table_name):
cursor.execute(
"SELECT * FROM %s LIMIT 1" % self.connection.ops.quote_name(table_name)
)

# PostgreSQL OIDs may vary depending on the installation, especially
# for datatypes from extensions, e.g. "hstore". In such cases, the
# type_display attribute (psycopg 3.2+) should be used.
type_display_available = psycopg_version() >= (3, 2)
return [
FieldInfo(
line.name,
line.type_code,
(
line.type_display
if type_display_available and line.type_display == "hstore"
else line.type_code
),
# display_size is always None on psycopg2.
line.internal_size if line.display_size is None else line.display_size,
line.internal_size,
Expand Down
4 changes: 3 additions & 1 deletion docs/releases/6.1.txt
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,9 @@ Minor features
:mod:`django.contrib.postgres`
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

* ...
* :djadmin:`inspectdb` now introspects
:class:`~django.contrib.postgres.fields.HStoreField` when ``psycopg`` 3.2+ is
installed and ``django.contrib.postgres`` is in :setting:`INSTALLED_APPS`.

:mod:`django.contrib.redirects`
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Expand Down
3 changes: 3 additions & 0 deletions tests/backends/postgresql/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -517,8 +517,11 @@ def test_lookup_cast_isnull_noop(self):
def test_correct_extraction_psycopg_version(self):
from django.db.backends.postgresql.base import Database, psycopg_version

psycopg_version.cache_clear()
with mock.patch.object(Database, "__version__", "4.2.1 (dt dec pq3 ext lo64)"):
self.addCleanup(psycopg_version.cache_clear)
self.assertEqual(psycopg_version(), (4, 2, 1))
psycopg_version.cache_clear()
with mock.patch.object(
Database, "__version__", "4.2b0.dev1 (dt dec pq3 ext lo64)"
):
Expand Down
13 changes: 13 additions & 0 deletions tests/postgres_tests/test_introspection.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,16 @@ def test_range_fields(self):
"null=True)",
],
)

def test_hstore_field(self):
from django.db.backends.postgresql.base import psycopg_version

if psycopg_version() < (3, 2):
self.skipTest("psycopg 3.2+ is required.")
self.assertFieldsInModel(
"postgres_tests_hstoremodel",
[
"field = django.contrib.postgres.fields.HStoreField(blank=True, "
"null=True)",
],
)