mirror of
https://github.com/django/django.git
synced 2025-07-03 17:29:12 +00:00
gis: Went through and cleaned up ogrinspect
code and added features provided in patch from springmeyer (thanks); add_postgis_srs
requires GDAL, so modified utils
imports accordingly.
git-svn-id: http://code.djangoproject.com/svn/django/branches/gis@7570 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
09ee2359cf
commit
462d731423
@ -6,6 +6,7 @@ from django.contrib.gis.gdal import HAS_GDAL
|
|||||||
if HAS_GDAL:
|
if HAS_GDAL:
|
||||||
from django.contrib.gis.utils.ogrinfo import ogrinfo, sample
|
from django.contrib.gis.utils.ogrinfo import ogrinfo, sample
|
||||||
from django.contrib.gis.utils.ogrinspect import mapping, ogrinspect
|
from django.contrib.gis.utils.ogrinspect import mapping, ogrinspect
|
||||||
|
from django.contrib.gis.utils.srs import add_postgis_srs
|
||||||
try:
|
try:
|
||||||
# LayerMapping requires DJANGO_SETTINGS_MODULE to be set,
|
# LayerMapping requires DJANGO_SETTINGS_MODULE to be set,
|
||||||
# so this needs to be in try/except.
|
# so this needs to be in try/except.
|
||||||
@ -20,6 +21,5 @@ try:
|
|||||||
except:
|
except:
|
||||||
HAS_GEOIP = False
|
HAS_GEOIP = False
|
||||||
|
|
||||||
from django.contrib.gis.utils.srs import add_postgis_srs
|
|
||||||
from django.contrib.gis.utils.wkt import precision_wkt
|
from django.contrib.gis.utils.wkt import precision_wkt
|
||||||
|
|
||||||
|
@ -1,13 +1,14 @@
|
|||||||
"""
|
"""
|
||||||
This module is for inspecting OGR data sources and generating either
|
This module is for inspecting OGR data sources and generating either
|
||||||
models for GeoDjango and/or mapping dictionaries for use with the
|
models for GeoDjango and/or mapping dictionaries for use with the
|
||||||
LayerMapping utility.
|
`LayerMapping` utility.
|
||||||
|
|
||||||
Author: Travis Pinney
|
Author: Travis Pinney, Dane Springmeyer, & Justin Bronn
|
||||||
"""
|
"""
|
||||||
|
from itertools import izip
|
||||||
# Requires GDAL to use.
|
# Requires GDAL to use.
|
||||||
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
|
||||||
|
|
||||||
def mapping(data_source, geom_name='geom', layer_key=0):
|
def mapping(data_source, geom_name='geom', layer_key=0):
|
||||||
"""
|
"""
|
||||||
@ -16,7 +17,7 @@ def mapping(data_source, geom_name='geom', layer_key=0):
|
|||||||
|
|
||||||
Keyword Arguments:
|
Keyword Arguments:
|
||||||
`geom_name` => The name of the geometry field to use for the model.
|
`geom_name` => The name of the geometry field to use for the model.
|
||||||
|
|
||||||
`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.
|
||||||
@ -47,26 +48,78 @@ def ogrinspect(*args, **kwargs):
|
|||||||
Given a data source (either a string or a DataSource object) and a string
|
Given a data source (either a string or a DataSource object) and a string
|
||||||
model name this function will generate a GeoDjango model.
|
model name this function will generate a GeoDjango model.
|
||||||
|
|
||||||
Keyword Arguments
|
Usage:
|
||||||
`geom_name` => For specifying the model name for the Geometry Field.
|
|
||||||
|
>>> from django.contrib.gis.utils import ogrinspect
|
||||||
|
>>> ogrinspect('/path/to/shapefile.shp','NewModel')
|
||||||
|
|
||||||
|
...will print model definition to stout
|
||||||
|
|
||||||
|
or put this in a python script and use to redirect the output to a new
|
||||||
|
model like:
|
||||||
|
|
||||||
|
$ python generate_model.py > myapp/models.py
|
||||||
|
|
||||||
|
# generate_model.py
|
||||||
|
from django.contrib.gis.utils import ogrinspect
|
||||||
|
shp_file = 'data/mapping_hacks/world_borders.shp'
|
||||||
|
model_name = 'WorldBorders'
|
||||||
|
|
||||||
|
print ogrinspect(shp_file, model_name, multi_geom=True, srid=4326,
|
||||||
|
geom_name='shapes', blank=True)
|
||||||
|
|
||||||
|
Required Arguments
|
||||||
|
`datasource` => string or DataSource object to file pointer
|
||||||
|
|
||||||
|
`model name` => string of name of new model class to create
|
||||||
|
|
||||||
|
Optional Keyword Arguments
|
||||||
|
`geom_name` => For specifying the model name for the Geometry Field.
|
||||||
|
Otherwise will default to `geom`
|
||||||
|
|
||||||
`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.
|
||||||
|
|
||||||
`srid` => The SRID to use for the Geometry Field. If it can be determined,
|
`srid` => The SRID to use for the Geometry Field. If it can be determined,
|
||||||
the SRID of the datasource
|
the SRID of the datasource is used.
|
||||||
|
|
||||||
|
`multi_geom` => Boolean (default: False) - specify as multigeometry.
|
||||||
|
|
||||||
|
`name_field` => String - specifies a field name to return for the
|
||||||
|
`__unicode__` function (which will be generated if specified).
|
||||||
|
|
||||||
|
`imports` => Boolean (default: True) - set to False to omit the
|
||||||
|
`from django.contrib.gis.db import models` code from the
|
||||||
|
autogenerated models thus avoiding duplicated imports when building
|
||||||
|
more than one model by batching ogrinspect()
|
||||||
|
|
||||||
|
`decimal` => Boolean or sequence (default: False). When set to True
|
||||||
|
all generated model fields corresponding to the `OFTReal` type will
|
||||||
|
be `DecimalField` instead of `FloatField`. A sequence of specific
|
||||||
|
field names to generate as `DecimalField` may also be used.
|
||||||
|
|
||||||
|
`blank` => Boolean or sequence (default: False). When set to True all
|
||||||
|
generated model fields will have `blank=True`. If the user wants to
|
||||||
|
give specific fields to have blank, then a list/tuple of OGR field
|
||||||
|
names may be used.
|
||||||
|
|
||||||
|
`null` => Boolean (default: False) - When set to True all generated
|
||||||
|
model fields will have `null=True`. If the user wants to specify
|
||||||
|
give specific fields to have null, then a list/tuple of OGR field
|
||||||
|
names may be used.
|
||||||
|
|
||||||
Note: This routine calls the _ogrinspect() helper to do the heavy lifting.
|
Note: This routine calls the _ogrinspect() helper to do the heavy lifting.
|
||||||
"""
|
"""
|
||||||
return '\n'.join(s for s in _ogrinspect(*args, **kwargs))
|
return '\n'.join(s for s in _ogrinspect(*args, **kwargs))
|
||||||
|
|
||||||
def _ogrinspect(data_source, model_name, geom_name='geom', layer_key=0, srid=None):
|
def _ogrinspect(data_source, model_name, geom_name='geom', layer_key=0, srid=None,
|
||||||
|
multi_geom=False, name_field=None, imports=True,
|
||||||
|
decimal=False, blank=False, null=False):
|
||||||
"""
|
"""
|
||||||
Helper routine for `ogrinspect` that generates GeoDjango models corresponding
|
Helper routine for `ogrinspect` that generates GeoDjango models corresponding
|
||||||
to the given data source. See the `ogrinspect` docstring for more details.
|
to the given data source. See the `ogrinspect` docstring for more details.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Getting the DataSource
|
# Getting the DataSource
|
||||||
if isinstance(data_source, str):
|
if isinstance(data_source, str):
|
||||||
data_source = DataSource(data_source)
|
data_source = DataSource(data_source)
|
||||||
@ -75,40 +128,77 @@ def _ogrinspect(data_source, model_name, geom_name='geom', layer_key=0, srid=Non
|
|||||||
else:
|
else:
|
||||||
raise TypeError('Data source parameter must be a string or a DataSource object.')
|
raise TypeError('Data source parameter must be a string or a DataSource object.')
|
||||||
|
|
||||||
yield '# This is an auto-generated Django model module created by ogrinspect.'
|
# Getting the layer corresponding to the layer key and getting
|
||||||
yield 'from django.contrib.gis.db import models'
|
# a string listing of all OGR fields in the Layer.
|
||||||
yield ''
|
layer = data_source[layer_key]
|
||||||
|
ogr_fields = layer.fields
|
||||||
|
|
||||||
|
# Creating lists from the `null`, `blank`, and `decimal`
|
||||||
|
# keyword arguments.
|
||||||
|
def process_kwarg(kwarg):
|
||||||
|
if isinstance(kwarg, (list, tuple)):
|
||||||
|
return [s.lower() for s in kwarg]
|
||||||
|
elif kwarg:
|
||||||
|
return [s.lower() for s in ogr_fields]
|
||||||
|
else:
|
||||||
|
return []
|
||||||
|
null_fields = process_kwarg(null)
|
||||||
|
blank_fields = process_kwarg(blank)
|
||||||
|
decimal_fields = process_kwarg(decimal)
|
||||||
|
|
||||||
|
# Gets the `null` and `blank` keywords for the given field name.
|
||||||
|
def get_kwargs_str(field_name):
|
||||||
|
kwlist = []
|
||||||
|
if field_name.lower() in null_fields: kwlist.append('null=True')
|
||||||
|
if field_name.lower() in blank_fields: kwlist.append('blank=True')
|
||||||
|
if kwlist: return ', ' + ', '.join(kwlist)
|
||||||
|
else: return ''
|
||||||
|
|
||||||
|
# For those wishing to disable the imports.
|
||||||
|
if imports:
|
||||||
|
yield '# This is an auto-generated Django model module created by ogrinspect.'
|
||||||
|
yield 'from django.contrib.gis.db import models'
|
||||||
|
yield ''
|
||||||
|
|
||||||
yield 'class %s(models.Model):' % model_name
|
yield 'class %s(models.Model):' % model_name
|
||||||
|
|
||||||
layer = data_source[layer_key]
|
for field_name, width, precision, field_type in izip(ogr_fields, layer.field_widths, layer.field_precisions, layer.field_types):
|
||||||
|
# The model field name.
|
||||||
for width, precision, field in zip(layer.field_widths, layer.field_precisions, layer.fields):
|
mfield = field_name.lower()
|
||||||
feature = layer[0]
|
if mfield[-1:] == '_': mfield += 'field'
|
||||||
fld_type = feature[field].type_name
|
|
||||||
mfield = field.lower()
|
|
||||||
|
|
||||||
if mfield[-1:] == '_':
|
# Getting the keyword args string.
|
||||||
mfield += 'field'
|
kwargs_str = get_kwargs_str(field_name)
|
||||||
|
|
||||||
if fld_type == 'Real':
|
if field_type is OFTReal:
|
||||||
yield ' %s = models.DecimalField(max_digits=%s, decimal_places=%s)' % (mfield, width, precision)
|
# By default OFTReals are mapped to `FloatField`, however, they
|
||||||
elif fld_type == 'Integer':
|
# may also be mapped to `DecimalField` if specified in the
|
||||||
yield ' %s = models.IntegerField()' % mfield
|
# `decimal` keyword.
|
||||||
elif fld_type == 'String':
|
if field_name.lower() in decimal_fields:
|
||||||
yield ' %s = models.CharField(max_length=%s)' % (mfield, width)
|
yield ' %s = models.DecimalField(max_digits=%d, decimal_places=%d%s)' % (mfield, width, precision, kwargs_str)
|
||||||
elif fld_type == 'Date':
|
else:
|
||||||
yield ' %s = models.DateField()' % mfield
|
yield ' %s = models.FloatField(%s)' % (mfield, kwargs_str[2:])
|
||||||
elif fld_type == 'DateTime':
|
elif field_type is OFTInteger:
|
||||||
yield ' %s = models.DateTimeField()' % mfield
|
yield ' %s = models.IntegerField(%s)' % (mfield, kwargs_str[2:])
|
||||||
elif fld_type == 'Time':
|
elif field_type is OFTString:
|
||||||
yield ' %s = models.TimeField()' % mfield
|
yield ' %s = models.CharField(max_length=%s%s)' % (mfield, width, kwargs_str)
|
||||||
|
elif field_type is OFTDate:
|
||||||
|
yield ' %s = models.DateField(%s)' % (mfield, kwargs_str[2:])
|
||||||
|
elif field_type is OFTDateTime:
|
||||||
|
yield ' %s = models.DateTimeField(%s)' % (mfield, kwargs_str[2:])
|
||||||
|
elif field_type is OFTDate:
|
||||||
|
yield ' %s = models.TimeField(%s)' % (mfield, kwargs_str[2:])
|
||||||
else:
|
else:
|
||||||
raise Exception('Unknown field type %s in %s' % (fld_type, mfield))
|
raise TypeError('Unknown field type %s in %s' % (fld_type, mfield))
|
||||||
|
|
||||||
# Getting the geometry type
|
# TODO: Autodetection of multigeometry types (see #7218).
|
||||||
gtype = layer.geom_type
|
gtype = layer.geom_type
|
||||||
|
if multi_geom and gtype.num in (1, 2, 3):
|
||||||
# Setting up the SRID parameter string.
|
geom_field = 'Multi%s' % gtype.django
|
||||||
|
else:
|
||||||
|
geom_field = gtype.django
|
||||||
|
|
||||||
|
# Setting up the SRID keyword string.
|
||||||
if srid is None:
|
if srid is None:
|
||||||
if layer.srs is None:
|
if layer.srs is None:
|
||||||
srid_str = 'srid=-1'
|
srid_str = 'srid=-1'
|
||||||
@ -117,12 +207,16 @@ def _ogrinspect(data_source, model_name, geom_name='geom', layer_key=0, srid=Non
|
|||||||
if srid is None:
|
if srid is None:
|
||||||
srid_str = 'srid=-1'
|
srid_str = 'srid=-1'
|
||||||
elif srid == 4326:
|
elif srid == 4326:
|
||||||
# WGS84 is the default.
|
# WGS84 is already the default.
|
||||||
srid_str = ''
|
srid_str = ''
|
||||||
else:
|
else:
|
||||||
srid_str = 'srid=%s' % srid
|
srid_str = 'srid=%s' % srid
|
||||||
else:
|
else:
|
||||||
srid_str = 'srid=%s' % srid
|
srid_str = 'srid=%s' % srid
|
||||||
|
|
||||||
yield ' %s = models.%s(%s)' % (geom_name, gtype.django, srid_str)
|
yield ' %s = models.%s(%s)' % (geom_name, geom_field, srid_str)
|
||||||
yield ' objects = models.GeoManager()'
|
yield ' objects = models.GeoManager()'
|
||||||
|
|
||||||
|
if name_field:
|
||||||
|
yield ''
|
||||||
|
yield ' def __unicode__(self): return self.%s' % name_field
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
from django.contrib.gis.gdal import SpatialReference
|
|
||||||
|
|
||||||
def add_postgis_srs(srs):
|
def add_postgis_srs(srs):
|
||||||
"""
|
"""
|
||||||
This function takes a GDAL SpatialReference system and adds its
|
This function takes a GDAL SpatialReference system and adds its
|
||||||
@ -15,6 +13,7 @@ def add_postgis_srs(srs):
|
|||||||
probably be changed.
|
probably be changed.
|
||||||
"""
|
"""
|
||||||
from django.contrib.gis.models import SpatialRefSys
|
from django.contrib.gis.models import SpatialRefSys
|
||||||
|
from django.contrib.gis.gdal import SpatialReference
|
||||||
|
|
||||||
if not isinstance(srs, SpatialReference):
|
if not isinstance(srs, SpatialReference):
|
||||||
srs = SpatialReference(srs)
|
srs = SpatialReference(srs)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user