änderung1
This commit is contained in:
1 parent
cc1d096bc3
commit
cbdda613b7
2098 files changed
+274524
No files matched your search
@@ -0,0 +1,14 @@
|
||||
"""
|
||||
This module contains useful utilities for GeoDjango.
|
||||
"""
|
||||
from django.contrib.gis.utils.ogrinfo import ogrinfo # NOQA
|
||||
from django.contrib.gis.utils.ogrinspect import mapping, ogrinspect # NOQA
|
||||
from django.contrib.gis.utils.srs import add_srs_entry # NOQA
|
||||
from django.core.exceptions import ImproperlyConfigured
|
||||
|
||||
try:
|
||||
# LayerMapping requires DJANGO_SETTINGS_MODULE to be set,
|
||||
# and ImproperlyConfigured is raised if that's not the case.
|
||||
from django.contrib.gis.utils.layermapping import LayerMapping, LayerMapError # NOQA
|
||||
except ImproperlyConfigured:
|
||||
pass
|
||||
@@ -0,0 +1,51 @@
|
||||
"""
|
||||
This module includes some utility functions for inspecting the layout
|
||||
of a GDAL data source -- the functionality is analogous to the output
|
||||
produced by the `ogrinfo` utility.
|
||||
"""
|
||||
|
||||
from django.contrib.gis.gdal import DataSource
|
||||
from django.contrib.gis.gdal.geometries import GEO_CLASSES
|
||||
|
||||
|
||||
def ogrinfo(data_source, num_features=10):
|
||||
"""
|
||||
Walk the available layers in the supplied `data_source`, displaying
|
||||
the fields for the first `num_features` features.
|
||||
"""
|
||||
|
||||
# Checking the parameters.
|
||||
if isinstance(data_source, str):
|
||||
data_source = DataSource(data_source)
|
||||
elif isinstance(data_source, DataSource):
|
||||
pass
|
||||
else:
|
||||
raise Exception('Data source parameter must be a string or a DataSource object.')
|
||||
|
||||
for i, layer in enumerate(data_source):
|
||||
print("data source : %s" % data_source.name)
|
||||
print("==== layer %s" % i)
|
||||
print(" shape type: %s" % GEO_CLASSES[layer.geom_type.num].__name__)
|
||||
print(" # features: %s" % len(layer))
|
||||
print(" srs: %s" % layer.srs)
|
||||
extent_tup = layer.extent.tuple
|
||||
print(" extent: %s - %s" % (extent_tup[0:2], extent_tup[2:4]))
|
||||
print("Displaying the first %s features ====" % num_features)
|
||||
|
||||
width = max(*map(len, layer.fields))
|
||||
fmt = " %%%ss: %%s" % width
|
||||
for j, feature in enumerate(layer[:num_features]):
|
||||
print("=== Feature %s" % j)
|
||||
for fld_name in layer.fields:
|
||||
type_name = feature[fld_name].type_name
|
||||
output = fmt % (fld_name, type_name)
|
||||
val = feature.get(fld_name)
|
||||
if val:
|
||||
if isinstance(val, str):
|
||||
val_fmt = ' ("%s")'
|
||||
else:
|
||||
val_fmt = ' (%s)'
|
||||
output += val_fmt % val
|
||||
else:
|
||||
output += ' (None)'
|
||||
print(output)
|
||||
@@ -0,0 +1,237 @@
|
||||
"""
|
||||
This module is for inspecting OGR data sources and generating either
|
||||
models for GeoDjango and/or mapping dictionaries for use with the
|
||||
`LayerMapping` utility.
|
||||
"""
|
||||
from django.contrib.gis.gdal import DataSource
|
||||
from django.contrib.gis.gdal.field import (
|
||||
OFTDate, OFTDateTime, OFTInteger, OFTInteger64, OFTReal, OFTString,
|
||||
OFTTime,
|
||||
)
|
||||
|
||||
|
||||
def mapping(data_source, geom_name='geom', layer_key=0, multi_geom=False):
|
||||
"""
|
||||
Given a DataSource, generate a dictionary that may be used
|
||||
for invoking the LayerMapping utility.
|
||||
|
||||
Keyword Arguments:
|
||||
`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;
|
||||
defaults to 0 (the first layer). May be an integer index or a string
|
||||
identifier for the layer.
|
||||
|
||||
`multi_geom` => Boolean (default: False) - specify as multigeometry.
|
||||
"""
|
||||
if isinstance(data_source, str):
|
||||
# Instantiating the DataSource from the string.
|
||||
data_source = DataSource(data_source)
|
||||
elif isinstance(data_source, DataSource):
|
||||
pass
|
||||
else:
|
||||
raise TypeError('Data source parameter must be a string or a DataSource object.')
|
||||
|
||||
# Creating the dictionary.
|
||||
_mapping = {}
|
||||
|
||||
# Generating the field name for each field in the layer.
|
||||
for field in data_source[layer_key].fields:
|
||||
mfield = field.lower()
|
||||
if mfield[-1:] == '_':
|
||||
mfield += 'field'
|
||||
_mapping[mfield] = field
|
||||
gtype = data_source[layer_key].geom_type
|
||||
if multi_geom:
|
||||
gtype.to_multi()
|
||||
_mapping[geom_name] = str(gtype).upper()
|
||||
return _mapping
|
||||
|
||||
|
||||
def ogrinspect(*args, **kwargs):
|
||||
"""
|
||||
Given a data source (either a string or a DataSource object) and a string
|
||||
model name this function will generate a GeoDjango model.
|
||||
|
||||
Usage:
|
||||
|
||||
>>> 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;
|
||||
defaults to 0 (the first layer). May be an integer index or a string
|
||||
identifier for the layer.
|
||||
|
||||
`srid` => The SRID to use for the Geometry Field. If it can be determined,
|
||||
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
|
||||
__str__() method (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: Call the _ogrinspect() helper to do the heavy lifting.
|
||||
"""
|
||||
return '\n'.join(s for s in _ogrinspect(*args, **kwargs))
|
||||
|
||||
|
||||
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
|
||||
to the given data source. See the `ogrinspect` docstring for more details.
|
||||
"""
|
||||
# Getting the DataSource
|
||||
if isinstance(data_source, str):
|
||||
data_source = DataSource(data_source)
|
||||
elif isinstance(data_source, DataSource):
|
||||
pass
|
||||
else:
|
||||
raise TypeError('Data source parameter must be a string or a DataSource object.')
|
||||
|
||||
# Getting the layer corresponding to the layer key and getting
|
||||
# a string listing of all OGR fields in the Layer.
|
||||
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 ''
|
||||
|
||||
yield 'class %s(models.Model):' % model_name
|
||||
|
||||
for field_name, width, precision, field_type in zip(
|
||||
ogr_fields, layer.field_widths, layer.field_precisions, layer.field_types):
|
||||
# The model field name.
|
||||
mfield = field_name.lower()
|
||||
if mfield[-1:] == '_':
|
||||
mfield += 'field'
|
||||
|
||||
# Getting the keyword args string.
|
||||
kwargs_str = get_kwargs_str(field_name)
|
||||
|
||||
if field_type is OFTReal:
|
||||
# By default OFTReals are mapped to `FloatField`, however, they
|
||||
# may also be mapped to `DecimalField` if specified in the
|
||||
# `decimal` keyword.
|
||||
if field_name.lower() in decimal_fields:
|
||||
yield ' %s = models.DecimalField(max_digits=%d, decimal_places=%d%s)' % (
|
||||
mfield, width, precision, kwargs_str
|
||||
)
|
||||
else:
|
||||
yield ' %s = models.FloatField(%s)' % (mfield, kwargs_str[2:])
|
||||
elif field_type is OFTInteger:
|
||||
yield ' %s = models.IntegerField(%s)' % (mfield, kwargs_str[2:])
|
||||
elif field_type is OFTInteger64:
|
||||
yield ' %s = models.BigIntegerField(%s)' % (mfield, kwargs_str[2:])
|
||||
elif field_type is OFTString:
|
||||
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 OFTTime:
|
||||
yield ' %s = models.TimeField(%s)' % (mfield, kwargs_str[2:])
|
||||
else:
|
||||
raise TypeError('Unknown field type %s in %s' % (field_type, mfield))
|
||||
|
||||
# TODO: Autodetection of multigeometry types (see #7218).
|
||||
gtype = layer.geom_type
|
||||
if multi_geom:
|
||||
gtype.to_multi()
|
||||
geom_field = gtype.django
|
||||
|
||||
# Setting up the SRID keyword string.
|
||||
if srid is None:
|
||||
if layer.srs is None:
|
||||
srid_str = 'srid=-1'
|
||||
else:
|
||||
srid = layer.srs.srid
|
||||
if srid is None:
|
||||
srid_str = 'srid=-1'
|
||||
elif srid == 4326:
|
||||
# WGS84 is already the default.
|
||||
srid_str = ''
|
||||
else:
|
||||
srid_str = 'srid=%s' % srid
|
||||
else:
|
||||
srid_str = 'srid=%s' % srid
|
||||
|
||||
yield ' %s = models.%s(%s)' % (geom_name, geom_field, srid_str)
|
||||
|
||||
if name_field:
|
||||
yield ''
|
||||
yield ' def __str__(self): return self.%s' % name_field
|
||||
Reference in new issue
Block a user