Django

Code

Changeset 7570

Show
Ignore:
Timestamp:
06/04/08 12:21:54 (6 months ago)
Author:
jbronn
Message:

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.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • django/branches/gis/django/contrib/gis/utils/__init__.py

    r7547 r7570  
    77    from django.contrib.gis.utils.ogrinfo import ogrinfo, sample 
    88    from django.contrib.gis.utils.ogrinspect import mapping, ogrinspect 
     9    from django.contrib.gis.utils.srs import add_postgis_srs 
    910    try: 
    1011        # LayerMapping requires DJANGO_SETTINGS_MODULE to be set,  
     
    2122    HAS_GEOIP = False 
    2223 
    23 from django.contrib.gis.utils.srs import add_postgis_srs 
    2424from django.contrib.gis.utils.wkt import precision_wkt 
    2525 
  • django/branches/gis/django/contrib/gis/utils/ogrinspect.py

    r6966 r7570  
    11""" 
    2  This module is for inspecting OGR data sources and generating either 
    3  models for GeoDjango and/or mapping dictionaries for use with the 
    4  LayerMapping utility. 
    5  
    6  Author: Travis Pinney 
     2This module is for inspecting OGR data sources and generating either 
     3models for GeoDjango and/or mapping dictionaries for use with the 
     4`LayerMapping` utility. 
     5 
     6Author: Travis Pinney, Dane Springmeyer, & Justin Bronn 
    77""" 
    8  
     8from itertools import izip 
    99# Requires GDAL to use. 
    1010from django.contrib.gis.gdal import DataSource 
     11from django.contrib.gis.gdal.field import OFTDate, OFTDateTime, OFTInteger, OFTReal, OFTString, OFTTime 
    1112 
    1213def mapping(data_source, geom_name='geom', layer_key=0): 
     
    1718    Keyword Arguments: 
    1819     `geom_name` => The name of the geometry field to use for the model. 
    19  
     20      
    2021     `layer_key` => The key for specifying which layer in the DataSource to use; 
    2122       defaults to 0 (the first layer).  May be an integer index or a string 
     
    4849    model name this function will generate a GeoDjango model. 
    4950 
    50     Keyword Arguments 
    51      `geom_name` => For specifying the model name for the Geometry Field. 
     51    Usage: 
     52     
     53    >>> from django.contrib.gis.utils import ogrinspect 
     54    >>> ogrinspect('/path/to/shapefile.shp','NewModel') 
     55     
     56    ...will print model definition to stout 
     57     
     58    or put this in a python script and use to redirect the output to a new 
     59    model like: 
     60     
     61    $ python generate_model.py > myapp/models.py 
     62     
     63    # generate_model.py  
     64    from django.contrib.gis.utils import ogrinspect 
     65    shp_file = 'data/mapping_hacks/world_borders.shp' 
     66    model_name = 'WorldBorders' 
     67 
     68    print ogrinspect(shp_file, model_name, multi_geom=True, srid=4326, 
     69                     geom_name='shapes', blank=True) 
     70                      
     71    Required Arguments 
     72     `datasource` => string or DataSource object to file pointer 
     73      
     74     `model name` => string of name of new model class to create 
     75       
     76    Optional Keyword Arguments 
     77     `geom_name` => For specifying the model name for the Geometry Field.  
     78       Otherwise will default to `geom` 
    5279 
    5380     `layer_key` => The key for specifying which layer in the DataSource to use; 
     
    5683 
    5784     `srid` => The SRID to use for the Geometry Field.  If it can be determined, 
    58        the SRID of the datasource 
    59  
     85       the SRID of the datasource is used. 
     86       
     87     `multi_geom` => Boolean (default: False) - specify as multigeometry. 
     88      
     89     `name_field` => String - specifies a field name to return for the 
     90       `__unicode__` function (which will be generated if specified). 
     91      
     92     `imports` => Boolean (default: True) - set to False to omit the  
     93       `from django.contrib.gis.db import models` code from the  
     94       autogenerated models thus avoiding duplicated imports when building 
     95       more than one model by batching ogrinspect() 
     96      
     97     `decimal` => Boolean or sequence (default: False).  When set to True 
     98       all generated model fields corresponding to the `OFTReal` type will 
     99       be `DecimalField` instead of `FloatField`.  A sequence of specific 
     100       field names to generate as `DecimalField` may also be used. 
     101 
     102     `blank` => Boolean or sequence (default: False).  When set to True all 
     103       generated model fields will have `blank=True`.  If the user wants to  
     104       give specific fields to have blank, then a list/tuple of OGR field 
     105       names may be used. 
     106 
     107     `null` => Boolean (default: False) - When set to True all generated 
     108       model fields will have `null=True`.  If the user wants to specify 
     109       give specific fields to have null, then a list/tuple of OGR field 
     110       names may be used. 
     111      
    60112    Note: This routine calls the _ogrinspect() helper to do the heavy lifting. 
    61113    """ 
    62114    return '\n'.join(s for s in _ogrinspect(*args, **kwargs)) 
    63115 
    64 def _ogrinspect(data_source, model_name, geom_name='geom', layer_key=0, srid=None): 
     116def _ogrinspect(data_source, model_name, geom_name='geom', layer_key=0, srid=None, 
     117                multi_geom=False, name_field=None, imports=True,  
     118                decimal=False, blank=False, null=False): 
    65119    """ 
    66120    Helper routine for `ogrinspect` that generates GeoDjango models corresponding 
    67121    to the given data source.  See the `ogrinspect` docstring for more details. 
    68122    """ 
    69  
    70123    # Getting the DataSource 
    71124    if isinstance(data_source, str): 
     
    76129        raise TypeError('Data source parameter must be a string or a DataSource object.') 
    77130 
    78     yield '# This is an auto-generated Django model module created by ogrinspect.' 
    79     yield 'from django.contrib.gis.db import models' 
    80     yield '' 
     131    # Getting the layer corresponding to the layer key and getting 
     132    # a string listing of all OGR fields in the Layer. 
     133    layer = data_source[layer_key] 
     134    ogr_fields = layer.fields 
     135 
     136    # Creating lists from the `null`, `blank`, and `decimal` 
     137    # keyword arguments. 
     138    def process_kwarg(kwarg): 
     139        if isinstance(kwarg, (list, tuple)): 
     140            return [s.lower() for s in kwarg]  
     141        elif kwarg: 
     142            return [s.lower() for s in ogr_fields] 
     143        else: 
     144            return [] 
     145    null_fields = process_kwarg(null) 
     146    blank_fields = process_kwarg(blank) 
     147    decimal_fields = process_kwarg(decimal) 
     148 
     149    # Gets the `null` and `blank` keywords for the given field name. 
     150    def get_kwargs_str(field_name): 
     151        kwlist = [] 
     152        if field_name.lower() in null_fields: kwlist.append('null=True') 
     153        if field_name.lower() in blank_fields: kwlist.append('blank=True') 
     154        if kwlist: return ', ' + ', '.join(kwlist) 
     155        else: return '' 
     156 
     157    # For those wishing to disable the imports. 
     158    if imports: 
     159        yield '# This is an auto-generated Django model module created by ogrinspect.' 
     160        yield 'from django.contrib.gis.db import models' 
     161        yield '' 
     162 
    81163    yield 'class %s(models.Model):' % model_name 
    82164     
    83     layer = data_source[layer_key]         
    84      
    85     for width, precision, field in zip(layer.field_widths, layer.field_precisions, layer.fields): 
    86         feature = layer[0] 
    87         fld_type = feature[field].type_name 
    88         mfield = field.lower() 
     165    for field_name, width, precision, field_type in izip(ogr_fields, layer.field_widths, layer.field_precisions, layer.field_types): 
     166        # The model field name. 
     167        mfield = field_name.lower() 
     168        if mfield[-1:] == '_': mfield += 'field' 
    89169         
    90         if mfield[-1:] == '_': 
    91             mfield += 'field' 
    92          
    93         if fld_type == 'Real': 
    94             yield '    %s = models.DecimalField(max_digits=%s, decimal_places=%s)' % (mfield, width, precision) 
    95         elif fld_type == 'Integer': 
    96             yield '    %s = models.IntegerField()' % mfield 
    97         elif fld_type == 'String': 
    98             yield '    %s = models.CharField(max_length=%s)' % (mfield, width) 
    99         elif fld_type == 'Date': 
    100             yield '    %s = models.DateField()' % mfield 
    101         elif fld_type == 'DateTime': 
    102             yield '    %s = models.DateTimeField()' % mfield 
    103         elif fld_type == 'Time': 
    104             yield '    %s = models.TimeField()' % mfield 
     170        # Getting the keyword args string. 
     171        kwargs_str = get_kwargs_str(field_name) 
     172 
     173        if field_type is OFTReal: 
     174            # By default OFTReals are mapped to `FloatField`, however, they 
     175            # may also be mapped to `DecimalField` if specified in the  
     176            # `decimal` keyword. 
     177            if field_name.lower() in decimal_fields: 
     178                yield '    %s = models.DecimalField(max_digits=%d, decimal_places=%d%s)' % (mfield, width, precision, kwargs_str) 
     179            else: 
     180                yield '    %s = models.FloatField(%s)' % (mfield, kwargs_str[2:]) 
     181        elif field_type is OFTInteger: 
     182            yield '    %s = models.IntegerField(%s)' % (mfield, kwargs_str[2:]) 
     183        elif field_type is OFTString: 
     184            yield '    %s = models.CharField(max_length=%s%s)' % (mfield, width, kwargs_str) 
     185        elif field_type is OFTDate: 
     186            yield '    %s = models.DateField(%s)' % (mfield, kwargs_str[2:]) 
     187        elif field_type is OFTDateTime: 
     188            yield '    %s = models.DateTimeField(%s)' % (mfield, kwargs_str[2:]) 
     189        elif field_type is OFTDate: 
     190            yield '    %s = models.TimeField(%s)' % (mfield, kwargs_str[2:]) 
    105191        else: 
    106             raise Exception('Unknown field type %s in %s' % (fld_type, mfield)) 
    107      
    108     # Getting the geometry type 
     192            raise TypeError('Unknown field type %s in %s' % (fld_type, mfield)) 
     193     
     194    # TODO: Autodetection of multigeometry types (see #7218). 
    109195    gtype = layer.geom_type 
    110      
    111     # Setting up the SRID parameter string. 
     196    if multi_geom and gtype.num in (1, 2, 3): 
     197        geom_field = 'Multi%s' % gtype.django 
     198    else: 
     199        geom_field = gtype.django 
     200 
     201    # Setting up the SRID keyword string. 
    112202    if srid is None: 
    113203        if layer.srs is None: 
     
    118208                srid_str = 'srid=-1' 
    119209            elif srid == 4326: 
    120                 # WGS84 is the default. 
     210                # WGS84 is already the default. 
    121211                srid_str = '' 
    122212            else: 
     
    125215        srid_str = 'srid=%s' % srid 
    126216 
    127     yield '    %s = models.%s(%s)' % (geom_name, gtype.django, srid_str) 
     217    yield '    %s = models.%s(%s)' % (geom_name, geom_field, srid_str) 
    128218    yield '    objects = models.GeoManager()' 
     219 
     220    if name_field: 
     221        yield '' 
     222        yield '    def __unicode__(self): return self.%s' % name_field 
  • django/branches/gis/django/contrib/gis/utils/srs.py

    r7547 r7570  
    1 from django.contrib.gis.gdal import SpatialReference 
    2  
    31def add_postgis_srs(srs): 
    42    """ 
     
    1614    """ 
    1715    from django.contrib.gis.models import SpatialRefSys 
     16    from django.contrib.gis.gdal import SpatialReference 
    1817 
    1918    if not isinstance(srs, SpatialReference):