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
This commit is contained in:
parent
37f7f233f5
commit
d22b291890
1
AUTHORS
1
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
|
||||
|
|
|
@ -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,),
|
||||
)
|
||||
]
|
|
@ -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")
|
|
@ -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:
|
||||
|
|
|
@ -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'
|
||||
|
|
|
@ -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')
|
||||
|
|
Loading…
Reference in New Issue