Package madrona :: Package shapes :: Module forms
[hide private]

Source Code for Module madrona.shapes.forms

  1  import os 
  2  import zipfile 
  3  import tempfile 
  4  import datetime 
  5  from django import forms 
  6  from django.forms.util import ValidationError 
  7  from django.utils.translation import ugettext_lazy as _ 
  8  from django.conf import settings 
  9  from django.contrib.gis import gdal 
 10   
 11  #http://docs.djangoproject.com/en/dev/topics/http/file-uploads/ 
 12  #http://www.neverfriday.com/sweetfriday/2008/09/-a-long-time-ago.html  
 13   
14 -class UploadForm(forms.Form):
15 16 file_obj = forms.FileField(label=_('Upload a Zipped Shapefile')) 17 # TODO: 18 # collect attribute info to stick in potential model 19 #title = forms.CharField(max_length=50,label=_('Title')) 20 #epsg = forms.IntegerField() 21
22 - def clean_file_obj(self):
23 f = self.cleaned_data['file_obj'] 24 valid_shp, error = self.validate(f) 25 if not valid_shp: 26 raise ValidationError("A problem occured: %s" % error)
27
28 - def handle(self,filefield_data):
29 """ Upload the file data, in chunks, to the SHP_UPLOAD_DIR specified in settings.py. 30 """ 31 # ensure the upload directory exists 32 if not os.path.exists(settings.SHP_UPLOAD_DIR): 33 os.makedirs(settings.SHP_UPLOAD_DIR) 34 35 # contruct the full filepath and filename 36 downloaded_file = os.path.normpath(os.path.join(settings.SHP_UPLOAD_DIR, filefield_data.name)) 37 38 print downloaded_file 39 # if we've already got an upload with the same name, append the daymonthyear_minute 40 if os.path.exists(downloaded_file): 41 name, ext = os.path.splitext(downloaded_file) 42 append = datetime.datetime.now().strftime('%d%m%Y_%m') 43 downloaded_file = '%s_%s%s' % (name,append,ext) 44 45 print downloaded_file 46 # write the zip archive to final location 47 self.write_file(downloaded_file,filefield_data)
48
49 - def write_file(self,filename,filefield_data):
50 destination = open(filename, 'wb+') 51 for chunk in filefield_data.chunks(): 52 destination.write(chunk) 53 destination.close()
54
55 - def check_zip_contents(self, ext, zip_file):
56 if not True in [info.filename.endswith(ext) for info in zip_file.infolist()]: 57 return False 58 return True
59
60 - def validate(self,filefield_data):
61 """ Validate the uploaded, zipped shapefile by unpacking to a temporary sandbox. 62 """ 63 # create a temporary file to write the zip archive to 64 tmp = tempfile.NamedTemporaryFile(suffix='.zip', mode='w') 65 66 # write zip to tmp sandbox 67 self.write_file(tmp.name,filefield_data) 68 69 if not zipfile.is_zipfile(tmp.name): 70 return False, 'That file is not a valid Zip Archive' 71 72 # create zip object 73 zfile = zipfile.ZipFile(tmp.name) 74 75 # ensure proper file contents by extensions inside 76 if not self.check_zip_contents('shp', zfile): 77 return False, 'Found Zip Archive but no file with a .shp extension found inside.' 78 elif not self.check_zip_contents('prj', zfile): 79 return False, 'You must supply a .prj file with the Shapefile to indicate the projection.' 80 elif not self.check_zip_contents('dbf', zfile): 81 return False, 'You must supply a .dbf file with the Shapefile to supply attribute data.' 82 elif not self.check_zip_contents('shx', zfile): 83 return False, 'You must supply a .shx file for the Shapefile to have a valid index.' 84 85 # unpack contents into tmp directory 86 tmp_dir = tempfile.gettempdir() 87 for info in zfile.infolist(): 88 data = zfile.read(info.filename) 89 shp_part = '%s%s%s' % (tmp_dir,os.path.sep,info.filename) 90 fout = open(shp_part, "wb") 91 fout.write(data) 92 fout.close() 93 94 # get the datasource name without extension 95 ds_name = os.path.splitext(zfile.namelist()[0])[0] 96 97 # ogr needs the full path to the unpacked 'file.shp' 98 ds = gdal.DataSource('%s%s%s.shp' % (tmp_dir,os.path.sep,ds_name)) 99 100 # shapefiles have just one layer, so grab the first... 101 layer = ds[0] 102 103 # one way of testing a sane shapefile... 104 # further tests should be able to be plugged in here... 105 if layer.test_capability('RandomRead'): 106 if str(ds.driver) == 'ESRI Shapefile': 107 return True, None 108 else: 109 return False, "Sorry, we've experienced a problem on our server. Please try again later." 110 else: 111 return False, 'Cannot read the shapefile, data is corrupted inside the zip, please try to upload again'
112