diff --git a/django/db/backends/postgresql/features.py b/django/db/backends/postgresql/features.py index a9e1c77480..6fd6af9088 100644 --- a/django/db/backends/postgresql/features.py +++ b/django/db/backends/postgresql/features.py @@ -36,3 +36,7 @@ class DatabaseFeatures(BaseDatabaseFeatures): @cached_property def has_select_for_update_skip_locked(self): return self.connection.pg_version >= 90500 + + @cached_property + def has_jsonb_datatype(self): + return self.connection.pg_version >= 90400 diff --git a/tests/postgres_tests/migrations/0002_create_test_models.py b/tests/postgres_tests/migrations/0002_create_test_models.py index 974aae1ec8..161f883d3f 100644 --- a/tests/postgres_tests/migrations/0002_create_test_models.py +++ b/tests/postgres_tests/migrations/0002_create_test_models.py @@ -216,9 +216,6 @@ class Migration(migrations.Migration): }, bases=(models.Model,), ), - ] - - pg_94_operations = [ migrations.CreateModel( name='JSONModel', fields=[ @@ -227,17 +224,8 @@ class Migration(migrations.Migration): ('field_custom', JSONField(null=True, blank=True, encoder=DjangoJSONEncoder)), ], options={ + 'required_db_features': {'has_jsonb_datatype'}, }, bases=(models.Model,), ), ] - - def apply(self, project_state, schema_editor, collect_sql=False): - try: - PG_VERSION = schema_editor.connection.pg_version - except AttributeError: - pass # We are probably not on PostgreSQL - else: - if PG_VERSION >= 90400: - self.operations = self.operations + self.pg_94_operations - return super(Migration, self).apply(project_state, schema_editor, collect_sql) diff --git a/tests/postgres_tests/models.py b/tests/postgres_tests/models.py index 52dbc0335c..8913e60869 100644 --- a/tests/postgres_tests/models.py +++ b/tests/postgres_tests/models.py @@ -1,5 +1,5 @@ from django.core.serializers.json import DjangoJSONEncoder -from django.db import connection, models +from django.db import models from .fields import ( ArrayField, BigIntegerRangeField, DateRangeField, DateTimeRangeField, @@ -129,15 +129,12 @@ class RangeLookupsModel(PostgreSQLModel): date = models.DateField(blank=True, null=True) -# Only create this model for postgres >= 9.4 -if connection.vendor == 'postgresql' and connection.pg_version >= 90400: - class JSONModel(models.Model): - field = JSONField(blank=True, null=True) - field_custom = JSONField(blank=True, null=True, encoder=DjangoJSONEncoder) -else: - # create an object with this name so we don't have failing imports - class JSONModel(object): - pass +class JSONModel(models.Model): + field = JSONField(blank=True, null=True) + field_custom = JSONField(blank=True, null=True, encoder=DjangoJSONEncoder) + + class Meta: + required_db_features = ['has_jsonb_datatype'] class ArrayFieldSubclass(ArrayField): diff --git a/tests/postgres_tests/test_json.py b/tests/postgres_tests/test_json.py index aeaae0de34..f306284b7f 100644 --- a/tests/postgres_tests/test_json.py +++ b/tests/postgres_tests/test_json.py @@ -1,15 +1,13 @@ from __future__ import unicode_literals import datetime -import unittest import uuid from decimal import Decimal from django.core import exceptions, serializers from django.core.serializers.json import DjangoJSONEncoder -from django.db import connection from django.forms import CharField, Form, widgets -from django.test import TestCase +from django.test import skipUnlessDBFeature from django.utils.html import escape from . import PostgreSQLTestCase @@ -22,18 +20,8 @@ except ImportError: pass -def skipUnlessPG94(test): - try: - PG_VERSION = connection.pg_version - except AttributeError: - PG_VERSION = 0 - if PG_VERSION < 90400: - return unittest.skip('PostgreSQL >= 9.4 required')(test) - return test - - -@skipUnlessPG94 -class TestSaveLoad(TestCase): +@skipUnlessDBFeature('has_jsonb_datatype') +class TestSaveLoad(PostgreSQLTestCase): def test_null(self): instance = JSONModel() instance.save() @@ -106,8 +94,8 @@ class TestSaveLoad(TestCase): self.assertEqual(loaded.field_custom, obj_after) -@skipUnlessPG94 -class TestQuerying(TestCase): +@skipUnlessDBFeature('has_jsonb_datatype') +class TestQuerying(PostgreSQLTestCase): @classmethod def setUpTestData(cls): cls.objs = [ @@ -250,8 +238,8 @@ class TestQuerying(TestCase): ) -@skipUnlessPG94 -class TestSerialization(TestCase): +@skipUnlessDBFeature('has_jsonb_datatype') +class TestSerialization(PostgreSQLTestCase): test_data = ( '[{"fields": {"field": {"a": "b", "c": null}, "field_custom": null}, ' '"model": "postgres_tests.jsonmodel", "pk": null}]'