summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarc Tamlyn <marc.tamlyn@gmail.com>2014-03-14 22:18:20 +0000
committerMarc Tamlyn <marc.tamlyn@gmail.com>2014-03-14 22:32:17 +0000
commitd22b291890c1736a40c0ad97448c7318df2eebb2 (patch)
tree23faf94f32ee295dce7b73d16b81f842c5159ef1
parent37f7f233f5f30c28ea60a7fbc272ffd296e2dbe1 (diff)
Fixed #22001 -- Ensure db_type is respected.
db_parameters should respect an already existing db_type method and return that as its type string. In particular, this was causing some fields from gis to not be generated. Thanks to @bigsassy and @blueyed for their work on the patch. Also fixed #22260
-rw-r--r--AUTHORS1
-rw-r--r--django/contrib/gis/tests/migrations/__init__.py0
-rw-r--r--django/contrib/gis/tests/migrations/migrations/0001_initial.py33
-rw-r--r--django/contrib/gis/tests/migrations/migrations/__init__.py0
-rw-r--r--django/contrib/gis/tests/migrations/test_commands.py47
-rw-r--r--django/db/models/fields/__init__.py24
-rw-r--r--tests/field_subclassing/fields.py5
-rw-r--r--tests/field_subclassing/tests.py10
8 files changed, 105 insertions, 15 deletions
diff --git a/AUTHORS b/AUTHORS
index 747c3bc6a8..7be78035a1 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -147,6 +147,7 @@ answer newbie questions, and generally made Django that much better:
Ricardo Javier Cárdenes Medina <ricardo.cardenes@gmail.com>
Jeremy Carbaugh <jcarbaugh@gmail.com>
Graham Carlyle <graham.carlyle@maplecroft.net>
+ Eric Palakovich Carr <carreric@gmail.com>
Juan Catalano <catalanojuan@gmail.com>
Antonio Cavedoni <http://cavedoni.com/>
cedric@terramater.net
diff --git a/django/contrib/gis/tests/migrations/__init__.py b/django/contrib/gis/tests/migrations/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/django/contrib/gis/tests/migrations/__init__.py
diff --git a/django/contrib/gis/tests/migrations/migrations/0001_initial.py b/django/contrib/gis/tests/migrations/migrations/0001_initial.py
new file mode 100644
index 0000000000..165a21700c
--- /dev/null
+++ b/django/contrib/gis/tests/migrations/migrations/0001_initial.py
@@ -0,0 +1,33 @@
+from django.db import models, migrations
+import django.contrib.gis.db.models.fields
+
+
+# Used for regression test of ticket #22001: https://code.djangoproject.com/ticket/22001
+class Migration(migrations.Migration):
+
+ operations = [
+ migrations.CreateModel(
+ name='Neighborhood',
+ fields=[
+ (u'id', models.AutoField(verbose_name=u'ID', serialize=False, auto_created=True, primary_key=True)),
+ ('name', models.TextField(unique=True)),
+ ('geom', django.contrib.gis.db.models.fields.MultiPolygonField(srid=4326, null=True)),
+ ],
+ options={
+ },
+ bases=(models.Model,),
+ ),
+ migrations.CreateModel(
+ name='Household',
+ fields=[
+ (u'id', models.AutoField(verbose_name=u'ID', serialize=False, auto_created=True, primary_key=True)),
+ ('neighborhood', models.ForeignKey(to='gis.Neighborhood', to_field=u'id', null=True)),
+ ('address', models.TextField()),
+ ('zip_code', models.IntegerField(null=True, blank=True)),
+ ('geom', django.contrib.gis.db.models.fields.PointField(srid=4326, null=True, geography=True)),
+ ],
+ options={
+ },
+ bases=(models.Model,),
+ )
+ ]
diff --git a/django/contrib/gis/tests/migrations/migrations/__init__.py b/django/contrib/gis/tests/migrations/migrations/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/django/contrib/gis/tests/migrations/migrations/__init__.py
diff --git a/django/contrib/gis/tests/migrations/test_commands.py b/django/contrib/gis/tests/migrations/test_commands.py
new file mode 100644
index 0000000000..5454042100
--- /dev/null
+++ b/django/contrib/gis/tests/migrations/test_commands.py
@@ -0,0 +1,47 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.core.management import call_command
+from django.db import connection
+from django.test import override_settings, override_system_checks, TransactionTestCase
+
+
+class MigrateTests(TransactionTestCase):
+ """
+ Tests running the migrate command in Geodjango.
+ """
+ available_apps = ["django.contrib.gis"]
+
+ def get_table_description(self, table):
+ with connection.cursor() as cursor:
+ return connection.introspection.get_table_description(cursor, table)
+
+ def assertTableExists(self, table):
+ with connection.cursor() as cursor:
+ self.assertIn(table, connection.introspection.get_table_list(cursor))
+
+ def assertTableNotExists(self, table):
+ with connection.cursor() as cursor:
+ self.assertNotIn(table, connection.introspection.get_table_list(cursor))
+
+ @override_system_checks([])
+ @override_settings(MIGRATION_MODULES={"gis": "django.contrib.gis.tests.migrations.migrations"})
+ def test_migrate_gis(self):
+ """
+ Tests basic usage of the migrate command when a model uses Geodjango
+ fields. Regression test for ticket #22001:
+ https://code.djangoproject.com/ticket/22001
+ """
+ # Make sure no tables are created
+ self.assertTableNotExists("migrations_neighborhood")
+ self.assertTableNotExists("migrations_household")
+ # Run the migrations to 0001 only
+ call_command("migrate", "gis", "0001", verbosity=0)
+ # Make sure the right tables exist
+ self.assertTableExists("gis_neighborhood")
+ self.assertTableExists("gis_household")
+ # Unmigrate everything
+ call_command("migrate", "gis", "zero", verbosity=0)
+ # Make sure it's all gone
+ self.assertTableNotExists("gis_neighborhood")
+ self.assertTableNotExists("gis_household")
diff --git a/django/db/models/fields/__init__.py b/django/db/models/fields/__init__.py
index dd88471d78..8dfe7e79e5 100644
--- a/django/db/models/fields/__init__.py
+++ b/django/db/models/fields/__init__.py
@@ -511,7 +511,7 @@ class Field(RegisterLookupMixin):
connection.
"""
# The default implementation of this method looks at the
- # backend-specific DATA_TYPES dictionary, looking up the field by its
+ # backend-specific data_types dictionary, looking up the field by its
# "internal type".
#
# A Field class can implement the get_internal_type() method to specify
@@ -525,24 +525,20 @@ class Field(RegisterLookupMixin):
# mapped to one of the built-in Django field types. In this case, you
# can implement db_type() instead of get_internal_type() to specify
# exactly which wacky database column type you want to use.
- params = self.db_parameters(connection)
- if params['type']:
- if params['check']:
- return "%s CHECK (%s)" % (params['type'], params['check'])
- else:
- return params['type']
- return None
+ data = DictWrapper(self.__dict__, connection.ops.quote_name, "qn_")
+ try:
+ return connection.creation.data_types[self.get_internal_type()] % data
+ except KeyError:
+ return None
def db_parameters(self, connection):
"""
- Replacement for db_type, providing a range of different return
- values (type, checks)
+ Extension of db_type(), providing a range of different return
+ values (type, checks).
+ This will look at db_type(), allowing custom model fields to override it.
"""
data = DictWrapper(self.__dict__, connection.ops.quote_name, "qn_")
- try:
- type_string = connection.creation.data_types[self.get_internal_type()] % data
- except KeyError:
- type_string = None
+ type_string = self.db_type(connection)
try:
check_string = connection.creation.data_type_check_constraints[self.get_internal_type()] % data
except KeyError:
diff --git a/tests/field_subclassing/fields.py b/tests/field_subclassing/fields.py
index 43ece22e82..d96ce8d873 100644
--- a/tests/field_subclassing/fields.py
+++ b/tests/field_subclassing/fields.py
@@ -74,3 +74,8 @@ class JSONField(six.with_metaclass(models.SubfieldBase, models.TextField)):
if value is None:
return None
return json.dumps(value)
+
+
+class CustomTypedField(models.TextField):
+ def db_type(self, connection):
+ return 'custom_field'
diff --git a/tests/field_subclassing/tests.py b/tests/field_subclassing/tests.py
index 6a3d1cad20..5f1dbac8a3 100644
--- a/tests/field_subclassing/tests.py
+++ b/tests/field_subclassing/tests.py
@@ -3,9 +3,10 @@ from __future__ import unicode_literals
import inspect
from django.core import serializers
+from django.db import connection
from django.test import TestCase
-from .fields import Small
+from .fields import Small, CustomTypedField
from .models import DataModel, MyModel, OtherModel
@@ -104,3 +105,10 @@ class CustomField(TestCase):
data = dict(inspect.getmembers(MyModel))
self.assertIn('__module__', data)
self.assertEqual(data['__module__'], 'field_subclassing.models')
+
+
+class TestDbType(TestCase):
+
+ def test_db_parameters_respects_db_type(self):
+ f = CustomTypedField()
+ self.assertEqual(f.db_parameters(connection)['type'], 'custom_field')