PageRenderTime 37ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/django/contrib/gis/management/commands/ogrinspect.py

https://code.google.com/p/mango-py/
Python | 122 lines | 107 code | 3 blank | 12 comment | 16 complexity | 5129a33bbacfa4f6e9385ec572f29359 MD5 | raw file
Possible License(s): BSD-3-Clause
  1. import os, sys
  2. from optparse import make_option
  3. from django.contrib.gis import gdal
  4. from django.contrib.gis.management.base import ArgsCommand, CommandError
  5. def layer_option(option, opt, value, parser):
  6. """
  7. Callback for `make_option` for the `ogrinspect` `layer_key`
  8. keyword option which may be an integer or a string.
  9. """
  10. try:
  11. dest = int(value)
  12. except ValueError:
  13. dest = value
  14. setattr(parser.values, option.dest, dest)
  15. def list_option(option, opt, value, parser):
  16. """
  17. Callback for `make_option` for `ogrinspect` keywords that require
  18. a string list. If the string is 'True'/'true' then the option
  19. value will be a boolean instead.
  20. """
  21. if value.lower() == 'true':
  22. dest = True
  23. else:
  24. dest = [s for s in value.split(',')]
  25. setattr(parser.values, option.dest, dest)
  26. class Command(ArgsCommand):
  27. help = ('Inspects the given OGR-compatible data source (e.g., a shapefile) and outputs\n'
  28. 'a GeoDjango model with the given model name. For example:\n'
  29. ' ./manage.py ogrinspect zipcode.shp Zipcode')
  30. args = '[data_source] [model_name]'
  31. option_list = ArgsCommand.option_list + (
  32. make_option('--blank', dest='blank', type='string', action='callback',
  33. callback=list_option, default=False,
  34. help='Use a comma separated list of OGR field names to add '
  35. 'the `blank=True` option to the field definition. Set with'
  36. '`true` to apply to all applicable fields.'),
  37. make_option('--decimal', dest='decimal', type='string', action='callback',
  38. callback=list_option, default=False,
  39. help='Use a comma separated list of OGR float fields to '
  40. 'generate `DecimalField` instead of the default '
  41. '`FloatField`. Set to `true` to apply to all OGR float fields.'),
  42. make_option('--geom-name', dest='geom_name', type='string', default='geom',
  43. help='Specifies the model name for the Geometry Field '
  44. '(defaults to `geom`)'),
  45. make_option('--layer', dest='layer_key', type='string', action='callback',
  46. callback=layer_option, default=0,
  47. help='The key for specifying which layer in the OGR data '
  48. 'source to use. Defaults to 0 (the first layer). May be '
  49. 'an integer or a string identifier for the layer.'),
  50. make_option('--multi-geom', action='store_true', dest='multi_geom', default=False,
  51. help='Treat the geometry in the data source as a geometry collection.'),
  52. make_option('--name-field', dest='name_field',
  53. help='Specifies a field name to return for the `__unicode__` function.'),
  54. make_option('--no-imports', action='store_false', dest='imports', default=True,
  55. help='Do not include `from django.contrib.gis.db import models` '
  56. 'statement.'),
  57. make_option('--null', dest='null', type='string', action='callback',
  58. callback=list_option, default=False,
  59. help='Use a comma separated list of OGR field names to add '
  60. 'the `null=True` option to the field definition. Set with'
  61. '`true` to apply to all applicable fields.'),
  62. make_option('--srid', dest='srid',
  63. help='The SRID to use for the Geometry Field. If it can be '
  64. 'determined, the SRID of the data source is used.'),
  65. make_option('--mapping', action='store_true', dest='mapping',
  66. help='Generate mapping dictionary for use with `LayerMapping`.')
  67. )
  68. requires_model_validation = False
  69. def handle_args(self, *args, **options):
  70. try:
  71. data_source, model_name = args
  72. except ValueError:
  73. raise CommandError('Invalid arguments, must provide: %s' % self.args)
  74. if not gdal.HAS_GDAL:
  75. raise CommandError('GDAL is required to inspect geospatial data sources.')
  76. # TODO: Support non file-based OGR datasources.
  77. if not os.path.isfile(data_source):
  78. raise CommandError('The given data source cannot be found: "%s"' % data_source)
  79. # Removing options with `None` values.
  80. options = dict([(k, v) for k, v in options.items() if not v is None])
  81. # Getting the OGR DataSource from the string parameter.
  82. try:
  83. ds = gdal.DataSource(data_source)
  84. except gdal.OGRException, msg:
  85. raise CommandError(msg)
  86. # Whether the user wants to generate the LayerMapping dictionary as well.
  87. show_mapping = options.pop('mapping', False)
  88. # Popping the verbosity global option, as it's not accepted by `_ogrinspect`.
  89. verbosity = options.pop('verbosity', False)
  90. # Returning the output of ogrinspect with the given arguments
  91. # and options.
  92. from django.contrib.gis.utils.ogrinspect import _ogrinspect, mapping
  93. output = [s for s in _ogrinspect(ds, model_name, **options)]
  94. if show_mapping:
  95. # Constructing the keyword arguments for `mapping`, and
  96. # calling it on the data source.
  97. kwargs = {'geom_name' : options['geom_name'],
  98. 'layer_key' : options['layer_key'],
  99. 'multi_geom' : options['multi_geom'],
  100. }
  101. mapping_dict = mapping(ds, **kwargs)
  102. # This extra legwork is so that the dictionary definition comes
  103. # out in the same order as the fields in the model definition.
  104. rev_mapping = dict([(v, k) for k, v in mapping_dict.items()])
  105. output.extend(['', '# Auto-generated `LayerMapping` dictionary for %s model' % model_name,
  106. '%s_mapping = {' % model_name.lower()])
  107. output.extend([" '%s' : '%s'," % (rev_mapping[ogr_fld], ogr_fld) for ogr_fld in ds[options['layer_key']].fields])
  108. output.extend([" '%s' : '%s'," % (options['geom_name'], mapping_dict[options['geom_name']]), '}'])
  109. return '\n'.join(output)