From e01eed46a5a017dd1bc82a1e80de37d9a69ab12c Mon Sep 17 00:00:00 2001 From: "luxagraf@c63593aa-01b0-44d9-8516-4b9c7e931d7f" Date: Sun, 9 May 2010 02:32:42 +0000 Subject: revamped national parks project files --- apps/projects/admin.py | 153 +------------------------ apps/projects/models/__init__.py | 2 +- apps/projects/models/natparks.py | 46 ++++++++ apps/projects/shortcuts.py | 235 +++++++++++++++++++++++++++++++++++++++ apps/projects/urls.py | 1 + apps/projects/views.py | 14 ++- 6 files changed, 298 insertions(+), 153 deletions(-) create mode 100644 apps/projects/models/natparks.py create mode 100644 apps/projects/shortcuts.py (limited to 'apps') diff --git a/apps/projects/admin.py b/apps/projects/admin.py index e1142f8..66e1318 100644 --- a/apps/projects/admin.py +++ b/apps/projects/admin.py @@ -6,7 +6,7 @@ from django.conf import settings from projects.models.base import Project from projects.models.fiveby import FiveBy -from projects.models.natparks import NationalParkBorders,NationalParkBordersTwo, NationalParks +from projects.models.natparks import NationalParks GMAP = GoogleMap(key=settings.GOOGLE_MAPS_API_KEY) @@ -111,105 +111,7 @@ class FiveByAdmin(OSMGeoAdmin): #debug = False #widget = OpenLayersWidget -class NationalParkBordersAdmin(OSMGeoAdmin): - - list_display = ('name1','name2','name3','url') - search_fields = ['name1',] - fieldsets = ( - ('Project', {'fields': ('name1', 'mpoly','url'), 'classes': ('show','extrapretty','wide')}), - ) - - - - class Media: - js = ['/media/admin/custom/model.js'] - extra_js = [GMAP.api_url + GMAP.key] - map_template = 'gis/admin/google.html' - #map_template = 'gis/admin/google.html' - # Default GeoDjango OpenLayers map options - # Uncomment and modify as desired - # To learn more about this jargon visit: - # www.openlayers.org - - default_lon = -9314310 - default_lat = 3991847 - default_zoom = 6 - #display_wkt = False - #display_srid = False - #extra_js = [] - #num_zoom = 18 - #max_zoom = False - #min_zoom = False - #units = False - #max_resolution = False - #max_extent = False - #modifiable = True - #mouse_position = True - #scale_text = True - #layerswitcher = True - scrollable = False - #admin_media_prefix = settings.ADMIN_MEDIA_PREFIX - map_width = 700 - map_height = 325 - #map_srid = 4326 - #map_template = 'gis/admin/openlayers.html' - #openlayers_url = 'http://openlayers.org/api/2.6/OpenLayers.js' - #wms_url = 'http://labs.metacarta.com/wms/vmap0' - #wms_layer = 'basic' - #wms_name = 'OpenLayers WMS' - #debug = False - #widget = OpenLayersWidget - -class NationalParkBordersTwoAdmin(OSMGeoAdmin): - - list_display = ('name',) - search_fields = ['name',] - fieldsets = ( - ('Project', {'fields': ('name', 'mpoly','mline','mpoint'), 'classes': ('show','extrapretty','wide')}), - ) - - - - class Media: - js = ['/media/admin/custom/model.js'] - extra_js = [GMAP.api_url + GMAP.key] - map_template = 'gis/admin/google.html' - #map_template = 'gis/admin/google.html' - # Default GeoDjango OpenLayers map options - # Uncomment and modify as desired - # To learn more about this jargon visit: - # www.openlayers.org - - default_lon = -9314310 - default_lat = 3991847 - default_zoom = 6 - #display_wkt = False - #display_srid = False - #extra_js = [] - #num_zoom = 18 - #max_zoom = False - #min_zoom = False - #units = False - #max_resolution = False - #max_extent = False - #modifiable = True - #mouse_position = True - #scale_text = True - #layerswitcher = True - scrollable = False - #admin_media_prefix = settings.ADMIN_MEDIA_PREFIX - map_width = 700 - map_height = 325 - #map_srid = 4326 - #map_template = 'gis/admin/openlayers.html' - #openlayers_url = 'http://openlayers.org/api/2.6/OpenLayers.js' - #wms_url = 'http://labs.metacarta.com/wms/vmap0' - #wms_layer = 'basic' - #wms_name = 'OpenLayers WMS' - #debug = False - #widget = OpenLayersWidget - class NationalParksAdmin(OSMGeoAdmin): @@ -260,58 +162,7 @@ class NationalParksAdmin(OSMGeoAdmin): #wms_name = 'OpenLayers WMS' #debug = False #widget = OpenLayersWidget -''' -class NPEntryAdmin(OSMGeoAdmin): - - list_display = ('title',) - search_fields = ['title','park'] - fieldsets = ( - ('Project', {'fields': ('title', 'dek', 'park', 'post', ('slug', 'status'),'pub_date','point',), 'classes': ('show','extrapretty','wide')}), - ) - - - class Media: - js = ['/media/admin/custom/model.js'] - extra_js = [GMAP.api_url + GMAP.key] - map_template = 'gis/admin/google.html' - #map_template = 'gis/admin/google.html' - # Default GeoDjango OpenLayers map options - # Uncomment and modify as desired - # To learn more about this jargon visit: - # www.openlayers.org - - default_lon = -9314310 - default_lat = 3991847 - default_zoom = 6 - #display_wkt = False - #display_srid = False - #extra_js = [] - #num_zoom = 18 - #max_zoom = False - #min_zoom = False - #units = False - #max_resolution = False - #max_extent = False - #modifiable = True - #mouse_position = True - #scale_text = True - #layerswitcher = True - scrollable = False - #admin_media_prefix = settings.ADMIN_MEDIA_PREFIX - map_width = 700 - map_height = 325 - #map_srid = 4326 - #map_template = 'gis/admin/openlayers.html' - #openlayers_url = 'http://openlayers.org/api/2.6/OpenLayers.js' - #wms_url = 'http://labs.metacarta.com/wms/vmap0' - #wms_layer = 'basic' - #wms_name = 'OpenLayers WMS' - #debug = False - #widget = OpenLayersWidget -''' + admin.site.register(Project, ProjectAdmin) admin.site.register(FiveBy, FiveByAdmin) -#admin.site.register(NPEntry, NPEntryAdmin) -admin.site.register(NationalParkBorders, NationalParkBordersAdmin) -admin.site.register(NationalParkBordersTwo, NationalParkBordersTwoAdmin) admin.site.register(NationalParks, NationalParksAdmin) \ No newline at end of file diff --git a/apps/projects/models/__init__.py b/apps/projects/models/__init__.py index 5d544c1..fdee7fc 100644 --- a/apps/projects/models/__init__.py +++ b/apps/projects/models/__init__.py @@ -1,3 +1,3 @@ from base import Project from fiveby import FiveBy -from natparks import NationalParkBorders, NationalParkBordersTwo, NationalParks \ No newline at end of file +from natparks import NationalParks \ No newline at end of file diff --git a/apps/projects/models/natparks.py b/apps/projects/models/natparks.py new file mode 100644 index 0000000..c78052c --- /dev/null +++ b/apps/projects/models/natparks.py @@ -0,0 +1,46 @@ +from django.contrib.gis.db import models +from blog.models import Entry +from photos.models import PhotoGallery +from locations.models import State + +PUB_STATUS = ( + (0, 'Draft'), + (1, 'Published'), + ) + + +import datetime +def get_upload_path(self, filename): + return "images/projects/np/%s/%s" %(datetime.datetime.today().strftime("%Y"), filename) + + +class NationalParks(models.Model): + type = models.CharField(max_length=50) + name = models.CharField(max_length=254) + state = models.ForeignKey(State, null=True) + size = models.CharField(max_length=10, null=True) + fee = models.CharField(max_length=5, null=True) + camping_fee = models.CharField(max_length=10, null=True) + url = models.CharField(max_length=250, null=True) + code= models.CharField(max_length=16) + unit_name= models.CharField(max_length=254) + date_visited_begin = models.DateTimeField('Date Visited',null=True) + date_visited_end = models.DateTimeField('Date Visited',null=True) + zoom= models.IntegerField(null=True) + mpoly = models.MultiPolygonField(null=True) + visited = models.BooleanField(default=False) + dek = models.TextField(null=True, blank=True) + tag_line = models.CharField(max_length=254, null=True) + post = models.ForeignKey(Entry, null=True) + gallery = models.ForeignKey(PhotoGallery, blank=True, null=True, verbose_name='photo set') + image = models.FileField(upload_to=get_upload_path, null=True,blank=True,help_text="width: 980px, height: > 450px") + objects = models.GeoManager() + + class Meta: + verbose_name_plural = "National Parks" + app_label = 'projects' + ordering = ('-visited','unit_name',) + # Returns the string representation of the model. + def __unicode__(self): + return self.unit_name + diff --git a/apps/projects/shortcuts.py b/apps/projects/shortcuts.py new file mode 100644 index 0000000..d54410c --- /dev/null +++ b/apps/projects/shortcuts.py @@ -0,0 +1,235 @@ +from django.contrib.gis.db.models.fields import GeometryField +#from django.contrib.gis.gdal import Envelope +from django.contrib.gis.geos import Polygon +from django.utils import simplejson +from django.http import HttpResponse +#from django.db.models.fields.related import ManyRelatedManager + +# also need to check out: +# http://code.google.com/p/dojango/source/browse/trunk/dojango/util/__init__.py#82 + + +# example usages: + +""" + +def a_shapes(request): + ids = request.GET.get('ids').split(',') + mimetype = 'text/plain' #'application/javascript; charset=utf8' + pretty_print = True + if ids: + qs = WorldBorders.objects.filter(affiliates__in=ids).annotate(num_a=Count('affiliates')).filter(num_a__gt=0) + else: + qs = WorldBorders.objects.none() + return render_to_geojson(qs, + extra_attributes=['num_a','affiliates_set'], + geom_attribute='point', + included_fields=['id','name'], + mimetype=mimetype, + proj_transform=900913, + pretty_print=pretty_print + ) + +def responses(qs,type_='countries',pretty_print=True,mimetype='text/plain'): + if type_ == 'locations': + qs = qs.geolocations() + return render_to_geojson(qs, + excluded_fields=['json'], + geom_field='point', + proj_transform=900913, + mimetype=mimetype, + pretty_print=pretty_print + ) + elif type_ == 'affiliates': + qs = qs.exclude(geokeywords='').attach_locations() + return render_to_geojson(qs, + included_fields=['id','_geokeywords_cache'], + geom_attribute='point', + extra_attributes=['name'], + proj_transform=900913, + mimetype=mimetype, + pretty_print=pretty_print + ) + elif type_ == 'countries': + qs2 = W.objects.filter(affiliates__in=qs).annotate(num_a=Count('affiliates')).filter(num_a__gt=0) + return render_to_geojson(qs2, + extra_attributes=['num_a'], + #geom_attribute='point', + mimetype=mimetype, + pretty_print=pretty_print + ) + else:# type_ == 'countries' or type is None: + if len(qs) > 10: + # this is a limit, weird huh? + # requires another all() otherwise it + # returns a list! + qs = qs.all()[:10] + return render_to_geojson(qs, + included_fields=['id','_geokeywords_cache'], + geom_attribute='countries.unionagg', + extra_attributes=['name'], + mimetype=mimetype, + pretty_print=pretty_print + ) +""" + + + +def render_to_geojson(query_set, geom_field=None, geom_attribute=None, extra_attributes=[],mimetype='text/plain', pretty_print=False, excluded_fields=[],included_fields=[],proj_transform=None): + ''' + + Shortcut to render a GeoJson FeatureCollection from a Django QuerySet. + Currently computes a bbox and adds a crs member as a sr.org link + + ''' + excluded_fields.append('_state') + collection = {} + if hasattr(query_set,'_meta'): # its a model instance + fields = query_set._meta.fields + query_set = [query_set] + else: + fields = query_set.model._meta.fields + + if geom_attribute: + geometry_name = geom_attribute + geo_field = None + if '.' in geom_attribute: + prop, meth = geom_attribute.split('.') + if len(query_set): + p = getattr(query_set[0],prop) + geo_field = getattr(p,meth) + if callable(geo_field): + geo_field = geo_field() + else: + if len(query_set): + geo_field = getattr(query_set[0],geom_attribute) + if callable(geo_field): + geo_field = geo_field() + if not geo_field: + srid = 4326 + else: + srid = geo_field.srid + + else: + geo_fields = [f for f in fields if isinstance(f, GeometryField)] + + #attempt to assign geom_field that was passed in + if geom_field: + #import pdb;pdb.set_trace() + geo_fieldnames = [x.name for x in geo_fields] + try: + geo_field = geo_fields[geo_fieldnames.index(geom_field)] + except: + raise Exception('%s is not a valid geometry on this model' % geom_field) + else: + if not len(geo_fields): + raise Exception('There appears to be no valid geometry on this model') + geo_field = geo_fields[0] # no support yet for multiple geometry fields + + + #remove other geom fields from showing up in attributes + if len(geo_fields) > 1: + for field in geo_fields: + if field.name not in excluded_fields: + excluded_fields.append(field.name) + + geometry_name = geo_field.name + + + srid = geo_field.srid + + if proj_transform: + to_srid = proj_transform + else: + to_srid = srid + # Gather the projection information + crs = {} + crs['type'] = "link" + crs_properties = {} + crs_properties['href'] = 'http://spatialreference.org/ref/epsg/%s/' % to_srid + crs_properties['type'] = 'proj4' + crs['properties'] = crs_properties + collection['crs'] = crs + collection['srid'] = to_srid + + # Build list of features + features = [] + if query_set.distinct(): + for item in query_set: + feat = {} + feat['type'] = 'Feature' + if included_fields: + d = {} + for f in included_fields: + if hasattr(item,f): + d[f] = getattr(item,f) + else: + d = item.__dict__.copy() + for field in excluded_fields: + if field in d.keys(): + d.pop(field) + if geometry_name in d: + d.pop(geometry_name) + + for attr in extra_attributes: + a = getattr(item,attr) + # crappy way of trying to figure out it this is a + # m2m, aka 'ManyRelatedManager' + if hasattr(a,'values_list'): + a = list(a.values_list('id',flat=True)) + if callable(a): + d[attr] = a() + else: + d[attr] = a + if '.' in geometry_name: + prop, meth = geometry_name.split('.') + a = getattr(item,prop) + g = getattr(a,meth) + if callable(g): + g = g() + else: + g = getattr(item,geometry_name) + if g: + if proj_transform: + g.transform(proj_transform) + feat['geometry'] = simplejson.loads(g.geojson) + feat['properties'] = d + features.append(feat) + else: + pass #features.append({'type':'Feature','geometry': {},'properties':{}}) + + # Label as FeatureCollection and add Features + collection['type'] = "FeatureCollection" + collection['features'] = features + + # Attach extent of all features + if query_set: + ex = None + query_set.query.distinct = False + if hasattr(query_set,'agg_extent'): + ex = [x for x in query_set.agg_extent.tuple] + elif '.' in geometry_name: + prop, meth = geometry_name.split('.') + a = getattr(item,prop) + if a: + ex = [x for x in a.extent()] + else: + # make sure qs does not have .distinct() in it... + ex = [x for x in query_set.extent()] + if ex: + if proj_transform: + poly = Polygon.from_bbox(ex) + poly.srid = srid + poly.transform(proj_transform) + ex = poly.extent + collection['bbox'] = ex + + # Return response + response = HttpResponse() + if pretty_print: + response.write('%s' % simplejson.dumps(collection, indent=1)) + else: + response.write('%s' % simplejson.dumps(collection)) + response['Content-length'] = str(len(response.content)) + response['Content-Type'] = mimetype + return response \ No newline at end of file diff --git a/apps/projects/urls.py b/apps/projects/urls.py index 3ea4b45..14722a8 100644 --- a/apps/projects/urls.py +++ b/apps/projects/urls.py @@ -10,6 +10,7 @@ projects = { } urlpatterns = patterns('', + (r'data/(?P\d+)/$', 'projects.views.data_json'), (r'(?P[-\w]+)/$', 'projects.views.detail'), (r'^$',list_detail.object_list, dict(projects, template_name='archives/projects.html')), ) diff --git a/apps/projects/views.py b/apps/projects/views.py index e3ed773..65de8ae 100644 --- a/apps/projects/views.py +++ b/apps/projects/views.py @@ -2,8 +2,10 @@ from django.shortcuts import render_to_response,get_object_or_404 from django.template import RequestContext from django.views.generic.list_detail import object_list from django.db.models import get_model +from django.http import HttpResponse +from django.core import serializers - +from projects.shortcuts import render_to_geojson from projects.models.base import Project from projects.models.fiveby import FiveBy from projects.models.natparks import NationalParks @@ -24,3 +26,13 @@ def detail(request,slug): return object_list(request, queryset=qs, template_name=template,) +def data_json(request, id): + qs = NationalParks.objects.filter(pk=id) + return render_to_geojson( + qs, + included_fields=['id',], + geom_attribute='mpoly', + mimetype = 'application/json', + pretty_print=True + ) + \ No newline at end of file -- cgit v1.2.3-70-g09d2