tests.py 6.4 KB

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