mirror of
https://github.com/django/django.git
synced 2025-07-04 01:39:20 +00:00
gis: Added the ogrinspect
management command.
git-svn-id: http://code.djangoproject.com/svn/django/branches/gis@7709 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
6b12a135d6
commit
f83b8efefd
15
django/contrib/gis/management/base.py
Normal file
15
django/contrib/gis/management/base.py
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
from django.core.management.base import BaseCommand, CommandError
|
||||||
|
|
||||||
|
class ArgsCommand(BaseCommand):
|
||||||
|
"""
|
||||||
|
Command class for commands that take multiple arguments.
|
||||||
|
"""
|
||||||
|
args = '<arg arg ...>'
|
||||||
|
|
||||||
|
def handle(self, *args, **options):
|
||||||
|
if not args:
|
||||||
|
raise CommandError('Must provide the following arguments: %s' % self.args)
|
||||||
|
return self.handle_args(*args, **options)
|
||||||
|
|
||||||
|
def handle_args(self, *args, **options):
|
||||||
|
raise NotImplementedError()
|
119
django/contrib/gis/management/commands/ogrinspect.py
Normal file
119
django/contrib/gis/management/commands/ogrinspect.py
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
import os, sys
|
||||||
|
from optparse import make_option
|
||||||
|
from django.contrib.gis import gdal
|
||||||
|
from django.contrib.gis.management.base import ArgsCommand, CommandError
|
||||||
|
|
||||||
|
def layer_option(option, opt, value, parser):
|
||||||
|
"""
|
||||||
|
Callback for `make_option` for the `ogrinspect` `layer_key`
|
||||||
|
keyword option which may be an integer or a string.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
dest = int(value)
|
||||||
|
except ValueError:
|
||||||
|
dest = value
|
||||||
|
setattr(parser.values, option.dest, dest)
|
||||||
|
|
||||||
|
def list_option(option, opt, value, parser):
|
||||||
|
"""
|
||||||
|
Callback for `make_option` for `ogrinspect` keywords that require
|
||||||
|
a string list. If the string is 'True'/'true' then the option
|
||||||
|
value will be a boolean instead.
|
||||||
|
"""
|
||||||
|
if value.lower() == 'true':
|
||||||
|
dest = True
|
||||||
|
else:
|
||||||
|
dest = [s for s in value.split(',')]
|
||||||
|
setattr(parser.values, option.dest, dest)
|
||||||
|
|
||||||
|
class Command(ArgsCommand):
|
||||||
|
help = ('Inspects the given OGR-compatible data source (e.g., a shapefile) and outputs\n'
|
||||||
|
'a GeoDjango model with the given model name. For example:\n'
|
||||||
|
' ./manage.py ogrinspect zipcode.shp Zipcode')
|
||||||
|
args = '[data_source] [model_name]'
|
||||||
|
|
||||||
|
option_list = ArgsCommand.option_list + (
|
||||||
|
make_option('--blank', dest='blank', type='string', action='callback',
|
||||||
|
callback=list_option, default=False,
|
||||||
|
help='Use a comma separated list of OGR field names to add '
|
||||||
|
'the `blank=True` option to the field definition. Set with'
|
||||||
|
'`true` to apply to all applicable fields.'),
|
||||||
|
make_option('--decimal', dest='decimal', type='string', action='callback',
|
||||||
|
callback=list_option, default=False,
|
||||||
|
help='Use a comma separated list of OGR float fields to '
|
||||||
|
'generate `DecimalField` instead of the default '
|
||||||
|
'`FloatField`. Set to `true` to apply to all OGR float fields.'),
|
||||||
|
make_option('--geom-name', dest='geom_name', type='string', default='geom',
|
||||||
|
help='Specifies the model name for the Geometry Field '
|
||||||
|
'(defaults to `geom`)'),
|
||||||
|
make_option('--layer', dest='layer_key', type='string', action='callback',
|
||||||
|
callback=layer_option, default=0,
|
||||||
|
help='The key for specifying which layer in the OGR data '
|
||||||
|
'source to use. Defaults to 0 (the first layer). May be '
|
||||||
|
'an integer or a string identifier for the layer.'),
|
||||||
|
make_option('--multi-geom', action='store_true', dest='multi_geom', default=False,
|
||||||
|
help='Treat the geometry in the data source as a geometry collection.'),
|
||||||
|
make_option('--name-field', dest='name_field',
|
||||||
|
help='Specifies a field name to return for the `__unicode__` function.'),
|
||||||
|
make_option('--no-imports', action='store_false', dest='imports', default=True,
|
||||||
|
help='Do not include `from django.contrib.gis.db import models` '
|
||||||
|
'statement.'),
|
||||||
|
make_option('--null', dest='null', type='string', action='callback',
|
||||||
|
callback=list_option, default=False,
|
||||||
|
help='Use a comma separated list of OGR field names to add '
|
||||||
|
'the `null=True` option to the field definition. Set with'
|
||||||
|
'`true` to apply to all applicable fields.'),
|
||||||
|
make_option('--srid', dest='srid',
|
||||||
|
help='The SRID to use for the Geometry Field. If it can be '
|
||||||
|
'determined, the SRID of the data source is used.'),
|
||||||
|
make_option('--mapping', action='store_true', dest='mapping',
|
||||||
|
help='Generate mapping dictionary for use with `LayerMapping`.')
|
||||||
|
)
|
||||||
|
|
||||||
|
requires_model_validation = False
|
||||||
|
|
||||||
|
def handle_args(self, *args, **options):
|
||||||
|
try:
|
||||||
|
data_source, model_name = args
|
||||||
|
except ValueError:
|
||||||
|
raise CommandError('Invalid arguments, must provide: %s' % self.args)
|
||||||
|
|
||||||
|
if not gdal.HAS_GDAL:
|
||||||
|
raise CommandError('GDAL is required to inspect geospatial data sources.')
|
||||||
|
|
||||||
|
# TODO: Support non file-based OGR datasources.
|
||||||
|
if not os.path.isfile(data_source):
|
||||||
|
raise CommandError('The given data source cannot be found: "%s"' % data_source)
|
||||||
|
|
||||||
|
# Removing options with `None` values.
|
||||||
|
options = dict([(k, v) for k, v in options.items() if not v is None])
|
||||||
|
|
||||||
|
# Getting the OGR DataSource from the string parameter.
|
||||||
|
try:
|
||||||
|
ds = gdal.DataSource(data_source)
|
||||||
|
except gdal.OGRException, msg:
|
||||||
|
raise CommandError(msg)
|
||||||
|
|
||||||
|
# Whether the user wants to generate the LayerMapping dictionary as well.
|
||||||
|
show_mapping = options.pop('mapping', False)
|
||||||
|
|
||||||
|
# Returning the output of ogrinspect with the given arguments
|
||||||
|
# and options.
|
||||||
|
from django.contrib.gis.utils.ogrinspect import _ogrinspect, mapping
|
||||||
|
output = [s for s in _ogrinspect(ds, model_name, **options)]
|
||||||
|
if show_mapping:
|
||||||
|
# Constructing the keyword arguments for `mapping`, and
|
||||||
|
# calling it on the data source.
|
||||||
|
kwargs = {'geom_name' : options['geom_name'],
|
||||||
|
'layer_key' : options['layer_key'],
|
||||||
|
'multi_geom' : options['multi_geom'],
|
||||||
|
}
|
||||||
|
mapping_dict = mapping(ds, **kwargs)
|
||||||
|
# This extra legwork is so that the dictionary definition comes
|
||||||
|
# out in the same order as the fields in the model definition.
|
||||||
|
rev_mapping = dict([(v, k) for k, v in mapping_dict.items()])
|
||||||
|
output.extend(['', '# Auto-generated `LayerMapping` dictionary for %s model' % model_name,
|
||||||
|
'%s_mapping = {' % model_name.lower()])
|
||||||
|
output.extend([" '%s' : '%s'," % (rev_mapping[ogr_fld], ogr_fld) for ogr_fld in ds[options['layer_key']].fields])
|
||||||
|
output.extend([" '%s' : '%s'," % (options['geom_name'], mapping_dict[options['geom_name']]), '}'])
|
||||||
|
return '\n'.join(output)
|
@ -10,7 +10,7 @@ from itertools import izip
|
|||||||
from django.contrib.gis.gdal import DataSource
|
from django.contrib.gis.gdal import DataSource
|
||||||
from django.contrib.gis.gdal.field import OFTDate, OFTDateTime, OFTInteger, OFTReal, OFTString, OFTTime
|
from django.contrib.gis.gdal.field import OFTDate, OFTDateTime, OFTInteger, OFTReal, OFTString, OFTTime
|
||||||
|
|
||||||
def mapping(data_source, geom_name='geom', layer_key=0):
|
def mapping(data_source, geom_name='geom', layer_key=0, multi_geom=False):
|
||||||
"""
|
"""
|
||||||
Given a DataSource, generates a dictionary that may be used
|
Given a DataSource, generates a dictionary that may be used
|
||||||
for invoking the LayerMapping utility.
|
for invoking the LayerMapping utility.
|
||||||
@ -21,6 +21,8 @@ def mapping(data_source, geom_name='geom', layer_key=0):
|
|||||||
`layer_key` => The key for specifying which layer in the DataSource to use;
|
`layer_key` => The key for specifying which layer in the DataSource to use;
|
||||||
defaults to 0 (the first layer). May be an integer index or a string
|
defaults to 0 (the first layer). May be an integer index or a string
|
||||||
identifier for the layer.
|
identifier for the layer.
|
||||||
|
|
||||||
|
`multi_geom` => Boolean (default: False) - specify as multigeometry.
|
||||||
"""
|
"""
|
||||||
if isinstance(data_source, basestring):
|
if isinstance(data_source, basestring):
|
||||||
# Instantiating the DataSource from the string.
|
# Instantiating the DataSource from the string.
|
||||||
@ -39,8 +41,9 @@ def mapping(data_source, geom_name='geom', layer_key=0):
|
|||||||
if mfield[-1:] == '_': mfield += 'field'
|
if mfield[-1:] == '_': mfield += 'field'
|
||||||
_mapping[mfield] = field
|
_mapping[mfield] = field
|
||||||
gtype = data_source[layer_key].geom_type
|
gtype = data_source[layer_key].geom_type
|
||||||
_mapping[geom_name] = str(gtype).upper()
|
if multi_geom and gtype.num in (1, 2, 3): prefix = 'MULTI'
|
||||||
|
else: prefix = ''
|
||||||
|
_mapping[geom_name] = prefix + str(gtype).upper()
|
||||||
return _mapping
|
return _mapping
|
||||||
|
|
||||||
def ogrinspect(*args, **kwargs):
|
def ogrinspect(*args, **kwargs):
|
||||||
|
Loading…
x
Reference in New Issue
Block a user