From 81334610b2f4521581e8c01bf4ad9ef175014199 Mon Sep 17 00:00:00 2001 From: Mark Longair Date: Thu, 16 Jul 2015 17:58:08 +0100 Subject: [PATCH] Add --only-with to mapit_import so you can only import particular areas Sometimes one has to deal with a shapefile which has many features in it, but you only want to import some subset based on key / value combinations of their fields. This commit adds the --only-with option to let you specify that only features with particular properties should be imported from the file. For example, you could do: ./manage.py mapit_import \ --only-with=TIPO:CIUDAD \ --only-with=PROVINCIA:'BUENOS AIRES' \ ... 010_Ejidos_Urbanos.shp ... to only import the boundaries of cities in the province of Buenos Aires. --- mapit/management/commands/mapit_import.py | 32 +++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/mapit/management/commands/mapit_import.py b/mapit/management/commands/mapit_import.py index 7779fb7f..45549d15 100644 --- a/mapit/management/commands/mapit_import.py +++ b/mapit/management/commands/mapit_import.py @@ -11,6 +11,7 @@ # Not using LayerMapping as want more control, but what it does is what this does # from django.contrib.gis.utils import LayerMapping from django.contrib.gis.gdal import DataSource +from django.contrib.gis.gdal.error import OGRIndexError from django.conf import settings from django.utils import six from django.utils.six.moves import input @@ -113,6 +114,17 @@ class Command(LabelCommand): dest='fix_invalid_polygons', help="Try to fix any invalid polygons and multipolygons found" ), + make_option( + '--only-with', + action="append", + dest='only_with', + metavar='FIELD_NAME:VALUE', + help=( + "Ignore features without this field / value combination " + "(If specified multiple times, the feature must have all " + "such specified combinations.)" + ) + ), ) def handle_label(self, filename, **options): @@ -140,6 +152,14 @@ def handle_label(self, filename, **options): code_field = options['code_field'] code_type_code = options['code_type'] encoding = options['encoding'] or 'utf-8' + only_with = {} + if options['only_with']: + for kv in options['only_with']: + m = re.search(r'^(.*?):(.*)', kv) + if not m: + message = "The --only-with value '{0}' did not contain a ':'" + raise CommandError(message.format(kv)) + only_with[m.group(1)] = m.group(2) if len(area_type_code) > 3: raise CommandError("Area type code must be 3 letters or fewer, sorry") @@ -245,6 +265,18 @@ def verbose(*args): "Could not find code using code field '%s' - should it be something else? " "It will be one of these: %s. Specify which with --code_field" % (code_field, choices)) + # If some --only-with parameters were specified, the + # feature must have all such key / value combination: + if only_with: + try: + if not all( + feat.get(k) == str(v) for k, v in only_with.items() + ): + continue + except OGRIndexError: + # This is raised if the key is not found in the feature: + continue + self.stdout.write(" looking at '%s'%s" % (name, (' (%s)' % code) if code else '')) g = None