2
0

tests.py 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. from __future__ import unicode_literals
  2. import os
  3. import re
  4. from unittest import skipUnless
  5. from django.contrib.gis.gdal import HAS_GDAL
  6. from django.core.management import call_command
  7. from django.db import connection, connections
  8. from django.test import TestCase, skipUnlessDBFeature
  9. from django.utils.six import StringIO
  10. from ..test_data import TEST_DATA
  11. if HAS_GDAL:
  12. from django.contrib.gis.gdal import Driver, GDALException
  13. from django.contrib.gis.utils.ogrinspect import ogrinspect
  14. from .models import AllOGRFields
  15. @skipUnless(HAS_GDAL, "InspectDbTests needs GDAL support")
  16. @skipUnlessDBFeature("gis_enabled")
  17. class InspectDbTests(TestCase):
  18. def test_geom_columns(self):
  19. """
  20. Test the geo-enabled inspectdb command.
  21. """
  22. out = StringIO()
  23. call_command('inspectdb',
  24. table_name_filter=lambda tn: tn.startswith('inspectapp_'),
  25. stdout=out)
  26. output = out.getvalue()
  27. if connection.features.supports_geometry_field_introspection:
  28. self.assertIn('geom = models.PolygonField()', output)
  29. self.assertIn('point = models.PointField()', output)
  30. else:
  31. self.assertIn('geom = models.GeometryField(', output)
  32. self.assertIn('point = models.GeometryField(', output)
  33. self.assertIn('objects = models.GeoManager()', output)
  34. @skipUnless(HAS_GDAL, "OGRInspectTest needs GDAL support")
  35. @skipUnlessDBFeature("gis_enabled")
  36. class OGRInspectTest(TestCase):
  37. maxDiff = 1024
  38. def test_poly(self):
  39. shp_file = os.path.join(TEST_DATA, 'test_poly', 'test_poly.shp')
  40. model_def = ogrinspect(shp_file, 'MyModel')
  41. expected = [
  42. '# This is an auto-generated Django model module created by ogrinspect.',
  43. 'from django.contrib.gis.db import models',
  44. '',
  45. 'class MyModel(models.Model):',
  46. ' float = models.FloatField()',
  47. ' int = models.FloatField()',
  48. ' str = models.CharField(max_length=80)',
  49. ' geom = models.PolygonField(srid=-1)',
  50. ' objects = models.GeoManager()',
  51. ]
  52. self.assertEqual(model_def, '\n'.join(expected))
  53. def test_date_field(self):
  54. shp_file = os.path.join(TEST_DATA, 'cities', 'cities.shp')
  55. model_def = ogrinspect(shp_file, 'City')
  56. expected = [
  57. '# This is an auto-generated Django model module created by ogrinspect.',
  58. 'from django.contrib.gis.db import models',
  59. '',
  60. 'class City(models.Model):',
  61. ' name = models.CharField(max_length=80)',
  62. ' population = models.FloatField()',
  63. ' density = models.FloatField()',
  64. ' created = models.DateField()',
  65. ' geom = models.PointField(srid=-1)',
  66. ' objects = models.GeoManager()',
  67. ]
  68. self.assertEqual(model_def, '\n'.join(expected))
  69. def test_time_field(self):
  70. # Getting the database identifier used by OGR, if None returned
  71. # GDAL does not have the support compiled in.
  72. ogr_db = get_ogr_db_string()
  73. if not ogr_db:
  74. self.skipTest("Unable to setup an OGR connection to your database")
  75. try:
  76. # Writing shapefiles via GDAL currently does not support writing OGRTime
  77. # fields, so we need to actually use a database
  78. model_def = ogrinspect(ogr_db, 'Measurement',
  79. layer_key=AllOGRFields._meta.db_table,
  80. decimal=['f_decimal'])
  81. except GDALException:
  82. self.skipTest("Unable to setup an OGR connection to your database")
  83. self.assertTrue(model_def.startswith(
  84. '# This is an auto-generated Django model module created by ogrinspect.\n'
  85. 'from django.contrib.gis.db import models\n'
  86. '\n'
  87. 'class Measurement(models.Model):\n'
  88. ))
  89. # The ordering of model fields might vary depending on several factors (version of GDAL, etc.)
  90. self.assertIn(' f_decimal = models.DecimalField(max_digits=0, decimal_places=0)', model_def)
  91. self.assertIn(' f_int = models.IntegerField()', model_def)
  92. self.assertIn(' f_datetime = models.DateTimeField()', model_def)
  93. self.assertIn(' f_time = models.TimeField()', model_def)
  94. self.assertIn(' f_float = models.FloatField()', model_def)
  95. self.assertIn(' f_char = models.CharField(max_length=10)', model_def)
  96. self.assertIn(' f_date = models.DateField()', model_def)
  97. self.assertIsNotNone(re.search(
  98. r' geom = models.PolygonField\(([^\)])*\)\n' # Some backends may have srid=-1
  99. r' objects = models.GeoManager\(\)', model_def))
  100. def test_management_command(self):
  101. shp_file = os.path.join(TEST_DATA, 'cities', 'cities.shp')
  102. out = StringIO()
  103. call_command('ogrinspect', shp_file, 'City', stdout=out)
  104. output = out.getvalue()
  105. self.assertIn('class City(models.Model):', output)
  106. def get_ogr_db_string():
  107. """
  108. Construct the DB string that GDAL will use to inspect the database.
  109. GDAL will create its own connection to the database, so we re-use the
  110. connection settings from the Django test.
  111. """
  112. db = connections.databases['default']
  113. # Map from the django backend into the OGR driver name and database identifier
  114. # http://www.gdal.org/ogr/ogr_formats.html
  115. #
  116. # TODO: Support Oracle (OCI).
  117. drivers = {
  118. 'django.contrib.gis.db.backends.postgis': ('PostgreSQL', "PG:dbname='%(db_name)s'", ' '),
  119. 'django.contrib.gis.db.backends.mysql': ('MySQL', 'MYSQL:"%(db_name)s"', ','),
  120. 'django.contrib.gis.db.backends.spatialite': ('SQLite', '%(db_name)s', '')
  121. }
  122. db_engine = db['ENGINE']
  123. if db_engine not in drivers:
  124. return None
  125. drv_name, db_str, param_sep = drivers[db_engine]
  126. # Ensure that GDAL library has driver support for the database.
  127. try:
  128. Driver(drv_name)
  129. except:
  130. return None
  131. # SQLite/Spatialite in-memory databases
  132. if db['NAME'] == ":memory:":
  133. return None
  134. # Build the params of the OGR database connection string
  135. params = [db_str % {'db_name': db['NAME']}]
  136. def add(key, template):
  137. value = db.get(key, None)
  138. # Don't add the parameter if it is not in django's settings
  139. if value:
  140. params.append(template % value)
  141. add('HOST', "host='%s'")
  142. add('PORT', "port='%s'")
  143. add('USER', "user='%s'")
  144. add('PASSWORD', "password='%s'")
  145. return param_sep.join(params)