def layer_append(request, layername, template='upload/layer_append.html'): print 'layer append' context = {} layer_destination = _resolve_layer( request, layername, 'base.change_resourcebase_metadata', _PERMISSION_MSG_METADATA) def parse_layers(get_capabilities_xml_str): xml = etree.XML(get_capabilities_xml_str) tree = etree.ElementTree(xml) root = tree.getroot() # BUG with lxml? When elements do not have a prefix, even if None:'{http://www.opengis.net/wms}' is set as a namespace, # namespace elements are not resolved. xpath doesn't work and findXXX needs the namespace for wms to work: {http://www.opengis.net/wms}Layer # no luck getting tree.xpath('//WMS_Capabilities/Capability/Layer/Layer') or variation to work layer_elements = root.findall('.//{http://www.opengis.net/wms}Layer') layers = {} for layer in layer_elements: name_element = layer.find('{http://www.opengis.net/wms}Name') if name_element is not None and name_element.text: layers[name_element.text] = name_element.text return layers return render_to_response(template, context, context_instance=RequestContext(request),)
def ediproxy_importmd(request, layername): layer = _resolve_layer(request, layername, 'base.change_resourcebase', _PERMISSION_MSG_METADATA) isoml = request.POST.get('generatedXml').encode('utf8') ediml = request.POST.get('ediml').encode('utf8') edimlid = request.POST.get('edimlid') try: _savelayermd(layer, isoml, ediml, version='2') except Exception as e: return json_response(exception=e, status=500) return json_response(body={'success':True}) # fare una class base view # e spostare in una nuova funzione rest # def load_isoedimlid(request, layername): # def load_isoediml(request, layername): # layer = _resolve_layer(request, layername, 'base.change_layer', _PERMISSION_MSG_METADATA) # ediml = request.raw_post_data # _savelayermd(layer, rndt, ediml) # except Exception as e: # return json_response(exception=e, status=500) # return json_response(body={'success':True,'redirect': reverse('layer_detail', args=(layer.typename,))}) # # return HttpResponseRedirect() # # def load_
def feature_edit_check(request, layername): """ If the layer is not a raster and the user has edit permission, return a status of 200 (OK). Otherwise, return a status of 401 (unauthorized). """ try: layer = _resolve_layer(request, layername) except: # Intercept and handle correctly resource not found exception return HttpResponse( json.dumps({'authorized': False}), content_type="application/json") datastore = ogc_server_settings.DATASTORE feature_edit = getattr(settings, "GEOGIG_DATASTORE", None) or datastore is_admin = False is_staff = False is_owner = False is_manager = False if request.user: is_admin = request.user.is_superuser if request.user else False is_staff = request.user.is_staff if request.user else False is_owner = (str(request.user) == str(layer.owner)) try: is_manager = request.user.groupmember_set.all().filter(role='manager').exists() except: is_manager = False if is_admin or is_staff or is_owner or is_manager or request.user.has_perm( 'change_layer_data', obj=layer) and layer.storeType == 'dataStore' and feature_edit: return HttpResponse( json.dumps({'authorized': True}), content_type="application/json") else: return HttpResponse( json.dumps({'authorized': False}), content_type="application/json")
def crowd_layer_detail(request, layername, template='features/crowd_layer_detail.html'): layer = _resolve_layer(request, layername, 'layers.view_layer', _PERMISSION_MSG_VIEW) layer.json_url = layer.link_set.get(name='GeoJSON').url return render_to_response(template, RequestContext(request, { "layer": layer, "features": layer.feature_set.all(), }))
def layer_style(request, layername): layer = _resolve_layer( request, layername, 'base.change_resourcebase', _PERMISSION_MSG_MODIFY) style_name = request.POST.get('defaultStyle') # would be nice to implement # better handling of default style switching # in layer model or deeper (gsconfig.py, REST API) old_default = layer.default_style if old_default.name == style_name: return HttpResponse( "Default style for %s remains %s" % (layer.name, style_name), status=200) # This code assumes without checking # that the new default style name is included # in the list of possible styles. new_style = ( style for style in layer.styles if style.name == style_name).next() # Does this change this in geoserver?? layer.default_style = new_style layer.styles = [ s for s in layer.styles if s.name != style_name] + [old_default] layer.save() return HttpResponse( "Default style for %s changed to %s" % (layer.name, style_name), status=200)
def layer_remove(request, layername, template='layers/layer_remove.html'): layer = _resolve_layer( request, layername, 'base.delete_resourcebase', _PERMISSION_MSG_DELETE) if (request.method == 'GET'): return render_to_response(template, RequestContext(request, { "layer": layer })) if (request.method == 'POST'): try: delete_layer.delay(object_id=layer.id) except Exception as e: message = '{0}: {1}.'.format(_('Unable to delete layer'), layer.typename) if 'referenced by layer group' in getattr(e, 'message', ''): message = _('This layer is a member of a layer group, you must remove the layer from the group ' 'before deleting.') messages.error(request, message) return render_to_response(template, RequestContext(request, {"layer": layer})) return HttpResponseRedirect(reverse("index_view")) else: return HttpResponse("Not allowed", status=403)
def rndtproxy(request, layername): layer = _resolve_layer(request, layername, 'base.change_layer', _PERMISSION_MSG_METADATA) ediml = request.body try: rndt = _ediml2rndt(ediml) except UnregisteredSKException, e: return json_response(errors=e.message, status=500)
def layer_metadata_detail(request, layername, template='layers/metadata_detail.html'): layer = _resolve_layer(request, layername, 'view_resourcebase', _PERMISSION_MSG_METADATA) return render_to_response(template, RequestContext(request, { "layer": layer, 'SITEURL': settings.SITEURL[:-1] }))
def layer_publish(request, layername): layer = _resolve_layer(request, layername, 'view_resourcebase', _PERMISSION_MSG_METADATA) layer.is_published = True layer.save() return HttpResponseRedirect(reverse( 'layer_detail', args=([layer.service_typename]) ))
def rndteditor(request, layername): layer = _resolve_layer(request, layername, 'layers.change_layer', _PERMISSION_MSG_METADATA) queryStringValues = { 'template': 'RNDT', 'version': '2.00', 'parameters': "{}" } fileid = layer.mdextension.fileid pars = {} if fileid is not None: queryStringValues['edit'] = fileid pars = { 'uid': layer.uuid, 'westlon': layer.bbox_x0, 'eastlon': layer.bbox_x1, 'southlat': layer.bbox_y0, 'northlat': layer.bbox_y1, 'referencesystem': layer.srid.split(':')[1], } else: pars = { 'uid': layer.uuid, # inserire data_md 'title': layer.title, # 'data_md': layer.date.date().isoformat(), # layer.mdextension.md_date.date().isoformat(), 'date': datetime.date.today().isoformat(), # layer.date.date().isoformat(), # 'tipo_di_data': layer.date_type, 'abstract': layer.abstract, 'spatialrepresentationtype': (EDI_MAP_SPATIALREPRESENTATIONTYPE).get(layer.storeType), 'westlon': layer.bbox_x0, 'eastlon': layer.bbox_x1, 'southlat': layer.bbox_y0, 'northlat': layer.bbox_y1, 'resource': '%s%s' % (settings.SITEURL[:-1], layer.get_absolute_url()), 'referencesystem': layer.srid.split(':')[1], } js_pars = json.dumps(pars, cls=DjangoJSONEncoder) queryStringValues['parameters'] = json.dumps(pars, cls=DjangoJSONEncoder) js_queryStringValues = json.dumps(queryStringValues) return render_to_response( 'mdtools/rndt.html', RequestContext(request, { 'layername': layername, 'queryStringValues': mark_safe(js_queryStringValues) }) )
def feature_edit_check(request, layername): """ If the layer is not a raster and the user has edit permission, return a status of 200 (OK). Otherwise, return a status of 401 (unauthorized). """ layer = _resolve_layer(request, layername) datastore = ogc_server_settings.DATASTORE feature_edit = getattr(settings, "GEOGIG_DATASTORE", None) or datastore if request.user.has_perm("change_layer_data", obj=layer) and layer.storeType == "dataStore" and feature_edit: return HttpResponse(json.dumps({"authorized": True}), content_type="application/json") else: return HttpResponse(json.dumps({"authorized": False}), content_type="application/json")
def site_layer_detail(request, layername, template='layers/layer_detail.html'): # BETTER WAY INSTEAD OF DO TWO _RESOLVE_LAYER PER CALL? layer = _resolve_layer( request, layername, 'base.view_resourcebase', _PERMISSION_MSG_VIEW) site = get_current_site(request) if not SiteResources.objects.get(site=site).resources.filter(pk=layer.pk).exists(): raise Http404 else: return layer_detail(request, layername, template='layers/layer_detail.html')
def layer_style_upload(request, layername): def respond(*args, **kw): kw['content_type'] = 'text/html' return json_response(*args, **kw) form = LayerStyleUploadForm(request.POST, request.FILES) if not form.is_valid(): return respond(errors="Please provide an SLD file.") data = form.cleaned_data layer = _resolve_layer( request, layername, 'base.change_resourcebase', _PERMISSION_MSG_MODIFY) sld = request.FILES['sld'].read() try: dom = etree.XML(sld) except Exception: return respond(errors="The uploaded SLD file is not valid XML") el = dom.findall( "{http://www.opengis.net/sld}NamedLayer/{http://www.opengis.net/sld}Name") if len(el) == 0 and not data.get('name'): return respond( errors="Please provide a name, unable to extract one from the SLD.") name = data.get('name') or el[0].text if data['update']: match = None styles = list(layer.styles) + [layer.default_style] for style in styles: if style.sld_name == name: match = style break if match is None: return respond(errors="Cannot locate style : " + name) match.update_body(sld) else: try: cat = gs_catalog cat.create_style(name, sld) layer.styles = layer.styles + \ [type('style', (object,), {'name': name})] cat.save(layer.publishing) except ConflictingDataError: return respond(errors="""A layer with this name exists. Select the update option if you want to update.""") return respond( body={ 'success': True, 'style': name, 'updated': data['update']})
def _change_published_status(request, layername, published): layer = _resolve_layer( request, layername, 'base.change_resourcebase_metadata', _PERMISSION_MSG_METADATA) # let's restrict auth to superuser only if not request.user.is_superuser: return HttpResponse("Not allowed", status=403) Layer.objects.filter(id=layer.id).update(is_published=published) return layer_detail(request, layername)
def get_remote_url(request, layername): layer = _resolve_layer( request, layername, 'base.view_resourcebase', _PERMISSION_MSG_DELETE) url = None if layer.remote_service is not None: service = layer.remote_service url = service.online_resource return HttpResponse(url)
def feature_edit_check(request, layername): """ If the layer is not a raster and the user has edit permission, return a status of 200 (OK). Otherwise, return a status of 401 (unauthorized). """ layer = _resolve_layer(request, layername) datastore = ogc_server_settings.DATASTORE feature_edit = getattr(settings, "GEOGIT_DATASTORE", None) or datastore if request.user.has_perm( 'base.change_resourcebase', obj=layer.resourcebase_ptr) and layer.storeType == 'dataStore' and feature_edit: return HttpResponse( json.dumps({'authorized': True}), mimetype="application/json") else: return HttpResponse( json.dumps({'authorized': False}), mimetype="application/json")
def layer_remove(request, layername, template='layers/layer_remove.html'): layer = _resolve_layer( request, layername, 'base.delete_resourcebase', _PERMISSION_MSG_DELETE) if (request.method == 'GET'): return render(request, template, context={ "layer": layer }) if (request.method == 'POST'): try: with transaction.atomic(): # Using Tastypie # from geonode.api.resourcebase_api import LayerResource # res = LayerResource() # request_bundle = res.build_bundle(request=request) # layer_bundle = res.build_bundle(request=request, obj=layer) # layer_json = res.serialize(None, # res.full_dehydrate(layer_bundle), # "application/json") # delete_layer.delay(instance=layer_json) result = delete_layer.delay(layer_id=layer.id) result.wait(10) except TimeoutError: # traceback.print_exc() pass except Exception as e: traceback.print_exc() message = '{0}: {1}.'.format( _('Unable to delete layer'), layer.alternate) if 'referenced by layer group' in getattr(e, 'message', ''): message = _( 'This layer is a member of a layer group, you must remove the layer from the group ' 'before deleting.') messages.error(request, message) return render( request, template, context={"layer": layer}) # MapStory Specific Change return HttpResponseRedirect(reverse("profile_detail", kwargs={'slug': layer.owner})) # End MapStory Specific Change else: return HttpResponse("Not allowed", status=403)
def layer_style_upload(req, layername): def respond(*args,**kw): kw['content_type'] = 'text/html' return json_response(*args, **kw) form = LayerStyleUploadForm(req.POST, req.FILES) if not form.is_valid(): return respond(errors="Please provide an SLD file.") data = form.cleaned_data layer = _resolve_layer(req, layername, 'base.change_resourcebase', _PERMISSION_MSG_MODIFY) sld = req.FILES['sld'].read() try: dom = etree.XML(sld) except Exception, ex: return respond(errors="The uploaded SLD file is not valid XML")
def importrndt(request, template='mdtools/upload_metadata.html'): if request.method == 'POST': form = UploadMetadataFileForm(request.POST, request.FILES) if form.is_valid(): layername = Layer.objects.get(pk=form.cleaned_data['layer']).typename layer = _resolve_layer(request, layername, 'base.change_layer', _PERMISSION_MSG_METADATA) rndt = request.FILES['file'].read() try: _savelayermd(layer, rndt, None) messages.add_message(request, messages.SUCCESS, 'Metadata Uploaded') except Exception as e: messages.add_message(request, messages.ERROR, e) else: form = UploadMetadataFileForm() return render_to_response(template, RequestContext(request, {'form': form}))
def importediml(request, template='mdtools/upload_metadata.html'): if request.method == 'POST': form = UploadMetadataFileForm(request.POST, request.FILES) if form.is_valid(): layername = Layer.objects.get(pk=form.cleaned_data['layer']).typename layer = _resolve_layer(request, layername, 'base.change_layer', _PERMISSION_MSG_METADATA) ediml = request.FILES['file'].read() try: rndt = _ediml2rndt(ediml) except UnregisteredSKException, e: messages.add_message(request, messages.ERROR, e) if not rndt: messages.add_message(request, messages.ERROR, 'Cannot get RNDT.') try: _savelayermd(layer, rndt, ediml) messages.add_message(request, messages.SUCCESS, 'Metadata Uploaded') except Exception as e: messages.add_message(request, messages.ERROR, e)
def layer_metadata_detail(request, layername, template='layers/metadata_detail.html'): layer = _resolve_layer(request, layername, 'view_resourcebase', _PERMISSION_MSG_METADATA) thumbnail_dir = os.path.join(settings.MEDIA_ROOT, 'thumbs') default_thumbnail_array = layer.get_thumbnail_url().split('/') default_thumbnail_name = default_thumbnail_array[ len(default_thumbnail_array) - 1 ] default_thumbnail = os.path.join(thumbnail_dir, default_thumbnail_name) if request.method == 'POST': thumb_form = ThumbnailImageForm(request.POST, request.FILES) if thumb_form.is_valid(): new_img = ThumbnailImage( thumbnail_image=request.FILES['thumbnail_image'] ) new_img.save() user_upload_thumbnail = ThumbnailImage.objects.all()[0] user_upload_thumbnail_filepath = str( user_upload_thumbnail.thumbnail_image ) # only create backup for original thumbnail if os.path.isfile(default_thumbnail + '.bak') is False: os.rename(default_thumbnail, default_thumbnail + '.bak') os.rename(user_upload_thumbnail_filepath, default_thumbnail) return HttpResponseRedirect( reverse('layer_metadata_detail', args=[layername]) ) else: thumb_form = ThumbnailImageForm() thumbnail = layer.get_thumbnail_url return render_to_response(template, RequestContext(request, { "layer": layer, 'SITEURL': settings.SITEURL[:-1], "thumbnail": thumbnail, "thumb_form": thumb_form }))
def rndtproxy(request, layername): layer = _resolve_layer(request, layername, 'layers.change_layer', _PERMISSION_MSG_METADATA) service = settings.RITMARE['MDSERVICE'] + 'postMetadata' headers = {'api_key': get_key(), 'Content-Type': 'application/xml', } r = requests.post(service, data=request.raw_post_data, headers=headers, verify=False) if r.status_code == 200: rndt = r.text.encode('utf8') # extract fileid ediml = etree.fromstring(request.raw_post_data) fileid = ediml.find('fileId').text # new fileid must be equal to the old one if layer.mdextension.fileid is not None: if int(layer.mdextension.fileid) != int(fileid): return json_response(errors='New fileid (%s) is different from the old one (%s)' % (fileid, layer.mdextension.fileid), status=500) else: layer.mdextension.fileid = fileid else: return json_response(errors='Cannot create RNDT', status=500) try: vals, keywords = rndt2dict(etree.fromstring(rndt)) errors = _post_validate(vals) if len(errors) > 0: return json_response(exception=errors, status=500) _mdimport(layer, vals, keywords, rndt) except Exception as e: return json_response(exception=e, status=500) # save rndt & edi xml layer.mdextension.md_date = vals['md_language'] layer.mdextension.md_date = vals['md_date'] layer.mdextension.rndt_xml = rndt layer.mdextension.elements_xml = request.raw_post_data layer.mdextension.save() return json_response(body={'success':True,'redirect': reverse('layer_detail', args=(layer.typename,))})
def get_project_definitions(request): """ Given a layer name, read the corresponding project definitions from the layer's metadata and return them as a json :param request: A "GET" :class:`django.http.HttpRequest` object containing the following parameter: * 'layer_name': the layer identifier :return: A JSON containing the layer's project definitions """ layer_name = request.GET.get('layer_name') if not layer_name: return HttpResponseBadRequest( 'Please provide the layer_name parameter') try: layer = _resolve_layer( request, layer_name, 'layers.view_layer', _PERMISSION_MSG_VIEW) except PermissionDenied: return HttpResponse( 'You are not allowed to view this layer', mimetype='text/plain', status=401) supplemental_information_str = layer.supplemental_information try: supplemental_information = json.loads(supplemental_information_str) except Exception as e: return HttpResponseBadRequest( "The layer's supplemental information is not in a valid" "json format: %s", str(e)) if 'project_definitions' in supplemental_information: project_definitions = supplemental_information['project_definitions'] else: # if this is an old project, the project definitions are not nested # into the 'project_definitions' key project_definitions = supplemental_information return HttpResponse(json.dumps(project_definitions, sort_keys=False, indent=2, separators=(',', ': ')), content_type="application/json")
def layer_style_upload(request, layername): def respond(*args, **kw): kw['content_type'] = 'text/html' return json_response(*args, **kw) form = LayerStyleUploadForm(request.POST, request.FILES) if not form.is_valid(): return respond(errors="Please provide an SLD file.") data = form.cleaned_data layer = _resolve_layer( request, layername, 'base.change_resourcebase', _PERMISSION_MSG_MODIFY) sld = request.FILES['sld'].read() sld_name = None try: # Check SLD is valid try: if sld: if isfile(sld): sld = open(sld, "r").read() etree.XML(sld) except Exception: logger.exception("The uploaded SLD file is not valid XML") raise Exception( "The uploaded SLD file is not valid XML") sld_name = extract_name_from_sld( gs_catalog, sld, sld_file=request.FILES['sld']) except Exception as e: respond(errors="The uploaded SLD file is not valid XML: {}".format(e)) name = data.get('name') or sld_name set_layer_style(layer, data.get('title') or name, sld) return respond( body={ 'success': True, 'style': data.get('title') or name, 'updated': data['update']})
def layer_searchable_fields( request, layername): """ Manage the layer in the gazetteer. """ layer = _resolve_layer( request, layername, 'base.change_resourcebase_metadata', 'permissions message from searchable layers') status_message = None if request.method == 'POST': attributes_list = request.POST.getlist('attributes') status_message = '' for attribute in layer.attributes: ext_att, created = ExtLayerAttribute.objects.get_or_create(attribute=attribute) ext_att.searchable = False if attribute.attribute in attributes_list and attribute.attribute_type == 'xsd:string': ext_att.searchable = True status_message += ' %s' % attribute.attribute ext_att.save() searchable_attributes = [] for attribute in layer.attributes: if attribute.attribute_type == 'xsd:string': if hasattr(attribute, 'extlayerattribute'): attribute.searchable = attribute.extlayerattribute.searchable else: attribute.searchable = False searchable_attributes.append(attribute) template = 'wm_extra/layers/edit_searchable_fields.html' return render(request, template, { "layer": layer, "searchable_attributes": searchable_attributes, "status_message": status_message, })
def layer_style_upload(request, layername): def respond(*args, **kw): kw['content_type'] = 'text/html' return json_response(*args, **kw) form = LayerStyleUploadForm(request.POST, request.FILES) if not form.is_valid(): return respond(errors="Please provide an SLD file.") data = form.cleaned_data layer = _resolve_layer( request, layername, 'base.change_resourcebase', _PERMISSION_MSG_MODIFY) sld = request.FILES['sld'].read() sld_name = None try: # Check SLD is valid sld_name = extract_name_from_sld(gs_catalog, sld, sld_file=request.FILES['sld']) except Exception, e: respond(errors="The uploaded SLD file is not valid XML: {}".format(e))
def layer_style_manage(request, layername): layer = _resolve_layer( request, layername, 'layers.change_layer_style', _PERMISSION_MSG_MODIFY) if request.method == 'GET': try: cat = gs_catalog # First update the layer style info from GS to GeoNode's DB # The try/except is try: set_styles(layer, cat) except AttributeError: logger.warn( 'Unable to set the default style. Ensure Geoserver is running and that this layer exists.') all_available_gs_styles = cat.get_styles() gs_styles = [] for style in all_available_gs_styles: gs_styles.append((style.name, style.sld_title)) current_layer_styles = layer.styles.all() layer_styles = [] for style in current_layer_styles: layer_styles.append((style.name, style.sld_title)) # Render the form return render_to_response( 'layers/layer_style_manage.html', RequestContext(request, { "layer": layer, "gs_styles": gs_styles, "layer_styles": layer_styles, "default_style": (layer.default_style.name, layer.default_style.sld_title) } ) ) except (FailedRequestError, EnvironmentError) as e: msg = ('Could not connect to geoserver at "%s"' 'to manage style information for layer "%s"' % ( ogc_server_settings.LOCATION, layer.name) ) logger.warn(msg, e) # If geoserver is not online, return an error return render_to_response( 'layers/layer_style_manage.html', RequestContext(request, { "layer": layer, "error": msg } ) ) elif request.method == 'POST': try: selected_styles = request.POST.getlist('style-select') default_style = request.POST['default_style'] # Save to GeoServer cat = gs_catalog gs_layer = cat.get_layer(layer.name) gs_layer.default_style = default_style styles = [] for style in selected_styles: styles.append(style) gs_layer.styles = styles cat.save(gs_layer) # Save to Django layer = set_styles(layer, cat) layer.save() return HttpResponseRedirect( reverse( 'layer_detail', args=( layer.service_typename, ))) except (FailedRequestError, EnvironmentError, MultiValueDictKeyError) as e: msg = ('Error Saving Styles for Layer "%s"' % (layer.name) ) logger.warn(msg, e) return render_to_response( 'layers/layer_style_manage.html', RequestContext(request, { "layer": layer, "error": msg } ) )
def layer_metadata(request, layername, template='upload/layer_upload_metadata.html'): layer = _resolve_layer(request, layername, 'base.change_resourcebase_metadata', _PERMISSION_MSG_METADATA) topic_category = layer.category poc = layer.poc or layer.owner metadata_author = layer.metadata_author if request.method == "POST": layer_form = UploadLayerForm(request.POST, instance=layer, prefix="resource") category_form = CategoryForm( request.POST, prefix="category_choice_field", initial=int(request.POST["category_choice_field"]) if "category_choice_field" in request.POST else None) else: layer_form = UploadLayerForm(instance=layer, prefix="resource") category_form = CategoryForm( prefix="category_choice_field", initial=topic_category.id if topic_category else None) if request.method == "POST" and layer_form.is_valid( ) and category_form.is_valid(): new_poc = layer_form.cleaned_data['poc'] new_author = layer_form.cleaned_data['metadata_author'] new_keywords = layer_form.cleaned_data['keywords'] if new_poc is None: if poc is None: poc_form = ProfileForm(request.POST, prefix="poc", instance=poc) else: poc_form = ProfileForm(request.POST, prefix="poc") if poc_form.has_changed and poc_form.is_valid(): new_poc = poc_form.save() else: if not isinstance(new_poc, Profile): new_poc = Profile.objects.get(id=new_poc) if new_author is None: if metadata_author is None: author_form = ProfileForm(request.POST, prefix="author", instance=metadata_author) else: author_form = ProfileForm(request.POST, prefix="author") if author_form.has_changed and author_form.is_valid(): new_author = author_form.save() else: if not isinstance(new_author, Profile): new_author = Profile.objects.get(id=new_author) new_category = TopicCategory.objects.get( id=category_form.cleaned_data['category_choice_field']) if new_poc is not None and new_author is not None: new_keywords = layer_form.cleaned_data['keywords'] layer.keywords.clear() layer.keywords.add(*new_keywords) the_layer = layer_form.save() the_layer.poc = new_poc the_layer.metadata_author = new_author Layer.objects.filter(id=the_layer.id).update(category=new_category) return HttpResponseRedirect( reverse('layer_detail', args=(layer.service_typename, ))) if poc is None: poc_form = ProfileForm(instance=poc, prefix="poc") else: layer_form.fields['poc'].initial = poc.id poc_form = ProfileForm(prefix="poc") poc_form.hidden = True if metadata_author is None: author_form = ProfileForm(instance=metadata_author, prefix="author") else: layer_form.fields['metadata_author'].initial = metadata_author.id author_form = ProfileForm(prefix="author") author_form.hidden = True return render_to_response( template, RequestContext( request, { "layer": layer, "layer_form": layer_form, "poc_form": poc_form, "author_form": author_form, "category_form": category_form, }))
def new_map_config(request): ''' View that creates a new map. If the query argument 'copy' is given, the initial map is a copy of the map with the id specified, otherwise the default map configuration is used. If copy is specified and the map specified does not exist a 404 is returned. ''' DEFAULT_MAP_CONFIG, DEFAULT_BASE_LAYERS = default_map_config() if request.method == 'GET' and 'copy' in request.GET: mapid = request.GET['copy'] if not mapid.isdigit(): map_obj = _resolve_map_custom(request, mapid, 'urlsuffix', 'base.view_resourcebase') else: map_obj = _resolve_map(request, mapid, 'base.view_resourcebase') map_obj.abstract = DEFAULT_ABSTRACT map_obj.title = DEFAULT_TITLE if request.user.is_authenticated(): map_obj.owner = request.user config = map_obj.viewer_json(request.user) del config['id'] else: if request.method == 'GET': params = request.GET elif request.method == 'POST': params = request.POST else: return HttpResponse(status=405) if 'layer' in params: bbox = None map_obj = Map(projection="EPSG:900913") layers = [] for layer_name in params.getlist('layer'): try: layer = _resolve_layer(request, layer_name) except ObjectDoesNotExist: # bad layer, skip continue if not request.user.has_perm('view_resourcebase', obj=layer.get_self_resource()): # invisible layer, skip inclusion continue layer_bbox = layer.bbox # assert False, str(layer_bbox) if bbox is None: bbox = list(layer_bbox[0:4]) else: bbox[0] = min(bbox[0], layer_bbox[0]) bbox[1] = max(bbox[1], layer_bbox[1]) bbox[2] = min(bbox[2], layer_bbox[2]) bbox[3] = max(bbox[3], layer_bbox[3]) config = layer.attribute_config() #Add required parameters for GXP lazy-loading config["srs"] = layer.srid config["title"] = layer.title config["bbox"] = [float(coord) for coord in bbox] \ if layer.srid == "EPSG:4326" else llbbox_to_mercator([float(coord) for coord in bbox]) config["queryable"] = True if layer.storeType == "remoteStore": service = layer.service maplayer = MapLayer(map=map_obj, name=layer.typename, ows_url=layer.ows_url, layer_params=json.dumps(config), visibility=True, source_params=json.dumps({ "ptype": service.ptype, "remote": True, "url": service.base_url, "name": service.name })) else: maplayer = MapLayer(map=map_obj, name=layer.typename, ows_url=layer.ows_url, layer_params=json.dumps(config), visibility=True) layers.append(maplayer) if bbox is not None: minx, miny, maxx, maxy = [float(c) for c in bbox] x = (minx + maxx) / 2 y = (miny + maxy) / 2 center = list(forward_mercator((x, y))) if center[1] == float('-inf'): center[1] = 0 BBOX_DIFFERENCE_THRESHOLD = 1e-5 #Check if the bbox is invalid valid_x = (maxx - minx)**2 > BBOX_DIFFERENCE_THRESHOLD valid_y = (maxy - miny)**2 > BBOX_DIFFERENCE_THRESHOLD if valid_x: width_zoom = math.log(360 / abs(maxx - minx), 2) else: width_zoom = 15 if valid_y: height_zoom = math.log(360 / abs(maxy - miny), 2) else: height_zoom = 15 map_obj.center_x = center[0] map_obj.center_y = center[1] map_obj.zoom = math.ceil(min(width_zoom, height_zoom)) config = map_obj.viewer_json(request.user, *(DEFAULT_BASE_LAYERS + layers)) config['fromLayer'] = True else: config = DEFAULT_MAP_CONFIG return json.dumps(config)
def layer_metadata(request, layername, template='layers/site_layers_metadata.html'): """ Override original layer's metadata view for adding translations """ layer = _resolve_layer(request, layername, 'base.change_resourcebase_metadata', _PERMISSION_MSG_METADATA) layer_attribute_set = inlineformset_factory( Layer, Attribute, extra=0, form=LayerAttributeForm, ) topic_category = layer.category poc = layer.poc metadata_author = layer.metadata_author internationalize_fields() change_abstract(layer) if request.method == "POST": if layer.metadata_uploaded_preserve: # layer metadata cannot be edited out = { 'success': False, 'errors': METADATA_UPLOADED_PRESERVE_ERROR } return HttpResponse(json.dumps(out), content_type='application/json', status=400) layer_form = LayerForm(request.POST, instance=layer, prefix="resource") attribute_form = layer_attribute_set( request.POST, instance=layer, prefix="layer_attribute_set", queryset=Attribute.objects.order_by('display_order')) category_form = CategoryForm( request.POST, prefix="category_choice_field", initial=int(request.POST["category_choice_field"]) if "category_choice_field" in request.POST else None) else: layer_form = LayerForm(instance=layer, prefix="resource") attribute_form = layer_attribute_set( instance=layer, prefix="layer_attribute_set", queryset=Attribute.objects.order_by('display_order')) category_form = CategoryForm( prefix="category_choice_field", initial=topic_category.id if topic_category else None) if request.method == "POST" and layer_form.is_valid( ) and attribute_form.is_valid() and category_form.is_valid(): new_poc = layer_form.cleaned_data['poc'] new_author = layer_form.cleaned_data['metadata_author'] if new_poc is None: if poc is None: poc_form = ProfileForm(request.POST, prefix="poc", instance=poc) else: poc_form = ProfileForm(request.POST, prefix="poc") if poc_form.is_valid(): if len(poc_form.cleaned_data['profile']) == 0: # FIXME use form.add_error in django > 1.7 errors = poc_form._errors.setdefault( 'profile', ErrorList()) errors.append( _('You must set a point of contact for this resource')) poc = None if poc_form.has_changed and poc_form.is_valid(): new_poc = poc_form.save() if new_author is None: if metadata_author is None: author_form = ProfileForm(request.POST, prefix="author", instance=metadata_author) else: author_form = ProfileForm(request.POST, prefix="author") if author_form.is_valid(): if len(author_form.cleaned_data['profile']) == 0: # FIXME use form.add_error in django > 1.7 errors = author_form._errors.setdefault( 'profile', ErrorList()) errors.append( _('You must set an author for this resource')) metadata_author = None if author_form.has_changed and author_form.is_valid(): new_author = author_form.save() new_category = TopicCategory.objects.get( id=category_form.cleaned_data['category_choice_field']) for form in attribute_form.cleaned_data: la = Attribute.objects.get(id=int(form['id'].id)) la.description = form["description"] la.attribute_label = form["attribute_label"] la.visible = form["visible"] la.display_order = form["display_order"] la.save() if new_poc is not None and new_author is not None: new_keywords = [ x.strip() for x in layer_form.cleaned_data['keywords'] ] layer.keywords.clear() layer.keywords.add(*new_keywords) the_layer = layer_form.save() up_sessions = UploadSession.objects.filter(layer=the_layer.id) if up_sessions.count( ) > 0 and up_sessions[0].user != the_layer.owner: up_sessions.update(user=the_layer.owner) the_layer.poc = new_poc the_layer.metadata_author = new_author Layer.objects.filter(id=the_layer.id).update(category=new_category) if getattr(settings, 'SLACK_ENABLED', False): try: from geonode.contrib.slack.utils import build_slack_message_layer, send_slack_messages send_slack_messages( build_slack_message_layer("layer_edit", the_layer)) except: print "Could not send slack message." return HttpResponseRedirect( reverse('layer_detail', args=(layer.service_typename, ))) if poc is not None: layer_form.fields['poc'].initial = poc.id poc_form = ProfileForm(prefix="poc") poc_form.hidden = True else: poc_form = ProfileForm(prefix="poc") poc_form.hidden = False if metadata_author is not None: layer_form.fields['metadata_author'].initial = metadata_author.id author_form = ProfileForm(prefix="author") author_form.hidden = True else: author_form = ProfileForm(prefix="author") author_form.hidden = False return render_to_response( template, RequestContext( request, { "layer": layer, "layer_form": layer_form, "poc_form": poc_form, "author_form": author_form, "attribute_form": attribute_form, "category_form": category_form, }))
def layer_detail(request, layername, template='layers/layer_detail.html'): layer = _resolve_layer(request, layername, 'base.view_resourcebase', _("You are not permitted to view this layer")) # assert False, str(layer_bbox) config = layer.attribute_config() # Add required parameters for GXP lazy-loading layer_bbox = layer.bbox bbox = [float(coord) for coord in list(layer_bbox[0:4])] config["srs"] = getattr(settings, 'DEFAULT_MAP_CRS', 'EPSG:900913') config["bbox"] = bbox if config["srs"] != 'EPSG:900913' \ else llbbox_to_mercator([float(coord) for coord in bbox]) config["title"] = layer.title config["queryable"] = True if layer.default_style: config["styles"] = layer.default_style.name if layer.storeType == "remoteStore": source_srid = None # Only grab the service proj/bbox if it is valid if None not in layer.service.bbox[0:4]: bbox = [float(coord) for coord in list(layer.service.bbox[0:4])] source_srid = layer.service.srid # Otherwise try the service directly # This is needed since previous services registered # did not store the bbox/srid in the model else: try: service_handler = get_service_handler( base_url=layer.service.base_url, service_type=layer.service.type) if getattr(service_handler.parsed_service, 'initialExtent', None): bbox[0] = service_handler.parsed_service.initialExtent[ 'xmin'] bbox[1] = service_handler.parsed_service.initialExtent[ 'ymin'] bbox[2] = service_handler.parsed_service.initialExtent[ 'xmax'] bbox[3] = service_handler.parsed_service.initialExtent[ 'ymax'] else: logger.info( 'Could not retrieve extent from service: {0}'.format( layer.service)) if getattr(service_handler.parsed_service, 'spatialReference', None): source_srid = \ service_handler.parsed_service.spatialReference[ 'latestWkid'] else: logger.info( 'Could not retrieve srid from service: {0}'.format( layer.service)) except Exception as e: logger.info('Failed to access service endpoint: {0}'.format( layer.service.base_url)) logger.info('Caught error: {0}'.format(e)) if source_srid is None: source_srid = layer.srid target_srid = 3857 if config["srs"] == 'EPSG:900913' else config["srs"] reprojected_bbox = bbox_to_projection(bbox, source_srid=source_srid, target_srid=target_srid) bbox = reprojected_bbox[:4] config['bbox'] = [float(coord) for coord in bbox] service = layer.service source_url = service.base_url use_proxy = (callable(uses_proxy_route) and uses_proxy_route(service.base_url)) components = urlsplit(service.base_url) query_params = None if components.query: query_params = OrderedDict( parse_qsl(components.query, keep_blank_values=True)) removed_query = [ components.scheme, components.netloc, components.path, None, components.fragment ] source_url = urlunsplit(removed_query) source_params = { "ptype": service.ptype, "remote": True, "url": source_url, "name": service.name, "use_proxy": use_proxy } if query_params is not None: source_params["params"] = query_params if layer.alternate is not None: config["layerid"] = layer.alternate maplayer = GXPLayer(name=layer.typename, ows_url=layer.ows_url, layer_params=json.dumps(config), source_params=json.dumps(source_params)) else: maplayer = GXPLayer(name=layer.typename, ows_url=layer.ows_url, layer_params=json.dumps(config)) # Update count for popularity ranking, # but do not includes admins or resource owners if request.user != layer.owner and not request.user.is_superuser: Layer.objects.filter(id=layer.id).update( popular_count=F('popular_count') + 1) # center/zoom don't matter; the viewer will center on the layer bounds map_obj = GXPMap( projection=getattr(settings, 'DEFAULT_MAP_CRS', 'EPSG:900913')) metadata = layer.link_set.metadata().filter( name__in=settings.DOWNLOAD_FORMATS_METADATA) granules = None all_granules = None filter = None if layer.is_mosaic: try: cat = gs_catalog cat._cache.clear() store = cat.get_store(layer.name) coverages = cat.mosaic_coverages(store) filter = None try: if request.GET["filter"]: filter = request.GET["filter"] except: pass offset = 10 * (request.page - 1) granules = cat.mosaic_granules( coverages['coverages']['coverage'][0]['name'], store, limit=10, offset=offset, filter=filter) all_granules = cat.mosaic_granules( coverages['coverages']['coverage'][0]['name'], store, filter=filter) except: granules = {"features": []} all_granules = {"features": []} context_dict = { "resource": layer, 'perms_list': get_perms(request.user, layer.get_self_resource()), "permissions_json": _perms_info_json(layer), "documents": get_related_documents(layer), "metadata": metadata, "is_layer": True, "wps_enabled": settings.OGC_SERVER['default']['WPS_ENABLED'], "granules": granules, "all_granules": all_granules, "filter": filter, } if 'access_token' in request.session: access_token = request.session['access_token'] else: u = uuid.uuid1() access_token = u.hex if bbox is not None: minx, miny, maxx, maxy = [float(coord) for coord in bbox] x = (minx + maxx) / 2 y = (miny + maxy) / 2 if layer.is_remote or getattr(settings, 'DEFAULT_MAP_CRS', 'EPSG:900913') == "EPSG:4326": center = list((x, y)) else: center = list(forward_mercator((x, y))) if center[1] == float('-inf'): center[1] = 0 BBOX_DIFFERENCE_THRESHOLD = 1e-5 # Check if the bbox is invalid valid_x = (maxx - minx)**2 > BBOX_DIFFERENCE_THRESHOLD valid_y = (maxy - miny)**2 > BBOX_DIFFERENCE_THRESHOLD if valid_x: width_zoom = math.log(360 / abs(maxx - minx), 2) else: width_zoom = 15 if valid_y: height_zoom = math.log(360 / abs(maxy - miny), 2) else: height_zoom = 15 map_obj.center_x = center[0] map_obj.center_y = center[1] map_obj.zoom = math.ceil(min(width_zoom, height_zoom)) context_dict["viewer"] = json.dumps( map_obj.viewer_json(request.user, access_token, *(default_map_config(request)[1] + [maplayer]))) context_dict["preview"] = getattr(settings, 'LAYER_PREVIEW_LIBRARY', 'leaflet') context_dict["crs"] = getattr(settings, 'DEFAULT_MAP_CRS', 'EPSG:900913') if layer.storeType == 'dataStore': links = layer.link_set.download().filter( name__in=settings.DOWNLOAD_FORMATS_VECTOR) else: links = layer.link_set.download().filter( name__in=settings.DOWNLOAD_FORMATS_RASTER) links_view = [ item for idx, item in enumerate(links) if item.url and 'wms' in item.url or 'gwc' in item.url ] links_download = [ item for idx, item in enumerate(links) if item.url and 'wms' not in item.url and 'gwc' not in item.url ] for item in links_view: if item.url and access_token: item.url = "%s&access_token=%s&time=%s" % \ (item.url, access_token, "0/9999") for item in links_download: if item.url and access_token: item.url = "%s&access_token=%s" % (item.url, access_token) if request.user.has_perm('view_resourcebase', layer.get_self_resource()): context_dict["links"] = links_view if request.user.has_perm('download_resourcebase', layer.get_self_resource()): if layer.storeType == 'dataStore': links = layer.link_set.download().filter( name__in=settings.DOWNLOAD_FORMATS_VECTOR) else: links = layer.link_set.download().filter( name__in=settings.DOWNLOAD_FORMATS_RASTER) context_dict["links_download"] = links_download if settings.SOCIAL_ORIGINS: context_dict["social_links"] = build_social_links(request, layer) return render_to_response(template, RequestContext(request, context_dict))
def rndt(request, layername): layer = _resolve_layer(request, layername, 'layers.view_layer', _PERMISSION_MSG_METADATA) rndt = layer.mdextension.rndt_xml return HttpResponse(rndt, mimetype="text/xml")
def ediml(request, layername): layer = _resolve_layer(request, layername, 'layers.view_layer', _PERMISSION_MSG_METADATA) ediml = layer.mdextension.elements_xml return HttpResponse(ediml, mimetype="text/xml")
def clip_layer(request, layername): """Clipping raster layer and save to temp folder. Clipping layer by bbox or by geojson. :param layername: The layer name in Geonode. :type layername: basestring :return: file size """ # PREPARATION try: layer = _resolve_layer(request, layername, 'base.view_resourcebase', _PERMISSION_MSG_VIEW) except Http404 as e: response = JsonResponse({ 'error': '%s. ' 'Please do ' '<i>python manage.py updatelayers</i> ' 'to retrieve it from geoserver.' % e }) response.status_code = 404 return response download_from_wcs = False query = request.GET or request.POST params = {param.upper(): value for param, value in query.iteritems()} bbox_string = params.get('BBOX', '') geojson = params.get('GEOJSON', '') current_date = datetime.datetime.today().strftime('%Y-%m-%d_%H-%M-%S') # create temp folder temporary_folder = os.path.join(tempfile.gettempdir(), 'clipped') try: os.mkdir(temporary_folder) except OSError as e: pass # get file for raster raster_filepath = None extention = '' # get file for raster try: if not raster_filepath: file_names = [] for layerfile in layer.upload_session.layerfile_set.all(): file_names.append(layerfile.file.path) for target_file in file_names: if '.tif' in target_file: raster_filepath = target_file extention = 'tif' break bbox_array = bbox_string.split(',') southwest_lat = bbox_array[1] bbox_array[1] = bbox_array[3] bbox_array[3] = southwest_lat bbox_string = ','.join(bbox_array) except AttributeError: # Call wcs command bbox_array = bbox_string.split(',') offset = 50 x = float(bbox_array[2]) - float(bbox_array[0]) width = int(x * 43260) + offset y = float(bbox_array[3]) - float(bbox_array[1]) height = int(y * 43260) + offset width = int(width * settings.WCS_DOWNLOADED_RATIO_SIZE) height = int(height * settings.WCS_DOWNLOADED_RATIO_SIZE) extention = 'tif' # checking file size of wcs download # it is done by assumption by getting sample # 1. getting part 10x10 through wcs # 2. get the filesize # 3. times filesize by width/10 * height/10, as assumption for actual filesize # ------------------------------------------------- number_tile_in_width = int(width / TILE_SAMPLE_SIZE) number_tile_in_height = int(height / TILE_SAMPLE_SIZE) sample_filepath = os.path.join(temporary_folder, layer.title + '.sample.' + extention) download_wcs(layername, bbox_string, TILE_SAMPLE_SIZE, TILE_SAMPLE_SIZE, sample_filepath) expected_clip_size = os.path.getsize(sample_filepath) # size of 10x10 times width_sample * height_sample expected_clip_size = expected_clip_size * (number_tile_in_width * number_tile_in_height) if not check_file_size(expected_clip_size): response = JsonResponse({ 'error': 'Clipped file size is ' 'bigger than %s mb' % (int(MAX_CLIP_SIZE) / 1000000) }) response.status_code = 403 return response # ------------------------------------------------- # download actual wcs clipped raster_filepath = os.path.join(temporary_folder, layer.title + '.' + extention) x1, x2 = bbox_array[0], bbox_array[2] y1, y2 = bbox_array[1], bbox_array[3] inProj = Proj(init='epsg:4326') outProj = Proj(init='epsg:32618') x1, y1 = transform(inProj, outProj, x1, y1) x2, y2 = transform(inProj, outProj, x2, y2) download_wcs_v2(layername, x1, x2, y1, y2, raster_filepath) if not geojson: response = JsonResponse({ 'success': 'Successfully clipping layer', 'clip_filename': os.path.basename(raster_filepath) }) response.status_code = 200 return response download_from_wcs = True # get temp filename for output filename = os.path.basename(raster_filepath) if len(filename.split('.')) >= 3: filename = filename.split('.')[0] clip_filename = filename + '.' + current_date + '.' + extention if bbox_string and not download_from_wcs and not geojson: output = os.path.join(temporary_folder, clip_filename) clipping = ('gdal_translate -projwin ' + '%(CLIP)s %(PROJECT)s %(OUTPUT)s') request_process = clipping % { 'CLIP': bbox_string.replace(',', ' '), 'PROJECT': raster_filepath, 'OUTPUT': output, } elif geojson: output = os.path.join(temporary_folder, clip_filename) mask_file = os.path.join(temporary_folder, filename + '.' + current_date + '.geojson') _file = open(mask_file, 'w+') _file.write(geojson) _file.close() masking = ("gdalwarp -dstnodata 0 -q -cutline '%(MASK)s' " + "-crop_to_cutline " + "-dstalpha -of " + "GTiff '%(PROJECT)s' '%(OUTPUT)s'") request_process = masking % { 'MASK': mask_file, 'PROJECT': raster_filepath, 'OUTPUT': output, } else: raise Http404('No bbox or geojson in parameters.') # generate if output is not created if not os.path.exists(output): if raster_filepath: subprocess.call(request_process, shell=True) if os.path.exists(output): # Check size clipped_size = os.path.getsize(output) if not check_file_size(clipped_size): response = JsonResponse({ 'error': 'Clipped file size is ' 'bigger than %s mb' % (int(MAX_CLIP_SIZE) / 1000000) }) response.status_code = 403 return response response = JsonResponse({ 'success': 'Successfully clipping layer', 'clip_filename': clip_filename }) response.status_code = 200 return response else: raise Http404('Project can not be clipped or masked.')
def new_map_config(request): ''' View that creates a new map. If the query argument 'copy' is given, the initial map is a copy of the map with the id specified, otherwise the default map configuration is used. If copy is specified and the map specified does not exist a 404 is returned. ''' DEFAULT_MAP_CONFIG, DEFAULT_BASE_LAYERS = default_map_config(request) if 'access_token' in request.session: access_token = request.session['access_token'] else: access_token = None if request.method == 'GET' and 'copy' in request.GET: mapid = request.GET['copy'] map_obj = _resolve_map(request, mapid, 'base.view_resourcebase') map_obj.abstract = DEFAULT_ABSTRACT map_obj.title = DEFAULT_TITLE if request.user.is_authenticated(): map_obj.owner = request.user config = map_obj.viewer_json(request.user, access_token) del config['id'] else: if request.method == 'GET': params = request.GET elif request.method == 'POST': params = request.POST else: return HttpResponse(status=405) if 'layer' in params: bbox = None map_obj = Map(projection=getattr(settings, 'DEFAULT_MAP_CRS', 'EPSG:900913')) layers = [] for layer_name in params.getlist('layer'): try: layer = _resolve_layer(request, layer_name) except ObjectDoesNotExist: # bad layer, skip continue if not request.user.has_perm( 'view_resourcebase', obj=layer.get_self_resource()): # invisible layer, skip inclusion continue layer_bbox = layer.bbox # assert False, str(layer_bbox) if bbox is None: bbox = list(layer_bbox[0:4]) else: bbox[0] = min(bbox[0], layer_bbox[0]) bbox[1] = max(bbox[1], layer_bbox[1]) bbox[2] = min(bbox[2], layer_bbox[2]) bbox[3] = max(bbox[3], layer_bbox[3]) config = layer.attribute_config() # Add required parameters for GXP lazy-loading config["title"] = layer.title config["queryable"] = True config["srs"] = getattr(settings, 'DEFAULT_MAP_CRS', 'EPSG:900913') config["bbox"] = bbox if config["srs"] != 'EPSG:900913' \ else llbbox_to_mercator([float(coord) for coord in bbox]) if layer.storeType == "remoteStore": service = layer.service # Probably not a good idea to send the access token to every remote service. # This should never match, so no access token should be sent to remote services. ogc_server_url = urlparse.urlsplit(ogc_server_settings.PUBLIC_LOCATION).netloc service_url = urlparse.urlsplit(service.base_url).netloc if access_token and ogc_server_url == service_url and 'access_token' not in service.base_url: url = service.base_url+'?access_token='+access_token else: url = service.base_url maplayer = MapLayer(map=map_obj, name=layer.typename, ows_url=layer.ows_url, layer_params=json.dumps(config), visibility=True, source_params=json.dumps({ "ptype": service.ptype, "remote": True, "url": url, "name": service.name})) else: ogc_server_url = urlparse.urlsplit(ogc_server_settings.PUBLIC_LOCATION).netloc layer_url = urlparse.urlsplit(layer.ows_url).netloc if access_token and ogc_server_url == layer_url and 'access_token' not in layer.ows_url: url = layer.ows_url+'?access_token='+access_token else: url = layer.ows_url maplayer = MapLayer( map=map_obj, name=layer.typename, ows_url=url, # use DjangoJSONEncoder to handle Decimal values layer_params=json.dumps(config, cls=DjangoJSONEncoder), visibility=True ) layers.append(maplayer) if bbox is not None: minx, miny, maxx, maxy = [float(c) for c in bbox] x = (minx + maxx) / 2 y = (miny + maxy) / 2 if getattr(settings, 'DEFAULT_MAP_CRS', 'EPSG:900913') == "EPSG:4326": center = list((x, y)) else: center = list(forward_mercator((x, y))) if center[1] == float('-inf'): center[1] = 0 BBOX_DIFFERENCE_THRESHOLD = 1e-5 # Check if the bbox is invalid valid_x = (maxx - minx) ** 2 > BBOX_DIFFERENCE_THRESHOLD valid_y = (maxy - miny) ** 2 > BBOX_DIFFERENCE_THRESHOLD if valid_x: width_zoom = math.log(360 / abs(maxx - minx), 2) else: width_zoom = 15 if valid_y: height_zoom = math.log(360 / abs(maxy - miny), 2) else: height_zoom = 15 map_obj.center_x = center[0] map_obj.center_y = center[1] map_obj.zoom = math.ceil(min(width_zoom, height_zoom)) config = map_obj.viewer_json( request.user, access_token, *(DEFAULT_BASE_LAYERS + layers)) config['fromLayer'] = True else: config = DEFAULT_MAP_CONFIG return json.dumps(config)
def layer_detail(request, layername, template='layers/layer_detail.html'): layer = _resolve_layer(request, layername, 'base.view_resourcebase', _PERMISSION_MSG_VIEW) # assert False, str(layer_bbox) config = layer.attribute_config() # only owners and admins can view unpublished layers if not layer.is_published: if request.user != layer.owner and not request.user.is_superuser: return HttpResponse(_PERMISSION_MSG_VIEW, status=403, content_type="text/plain") # TODO (Mapstory): This has been commented out to force the client to make a getCapabilities request in order # to pull in the time dimension data. Ideally we would cache time data just like the srs and bbox data to prevent # making the getCapabilities request. # Add required parameters for GXP lazy-loading #layer_bbox = layer.bbox #bbox = [float(coord) for coord in list(layer_bbox[0:4])] #srid = layer.srid # Transform WGS84 to Mercator. #config["srs"] = srid if srid != "EPSG:4326" else "EPSG:900913" #config["bbox"] = llbbox_to_mercator([float(coord) for coord in bbox]) #config["title"] = layer.title #config["queryable"] = True if layer.storeType == "remoteStore": service = layer.service source_params = { "ptype": service.ptype, "remote": True, "url": service.base_url, "name": service.name } maplayer = GXPLayer(name=layer.typename, ows_url=layer.ows_url, layer_params=json.dumps(config), source_params=json.dumps(source_params)) else: maplayer = GXPLayer(name=layer.name, ows_url=layer.ows_url, layer_params=json.dumps(config)) # Update count for popularity ranking, # but do not includes admins or resource owners if request.user != layer.owner and not request.user.is_superuser: Layer.objects.filter(id=layer.id).update( popular_count=F('popular_count') + 1) # center/zoom don't matter; the viewer will center on the layer bounds map_obj = GXPMap(projection="EPSG:900913") NON_WMS_BASE_LAYERS = [ la for la in default_map_config()[1] if la.ows_url is None ] metadata = layer.link_set.metadata().filter( name__in=settings.DOWNLOAD_FORMATS_METADATA) keywords = json.dumps([tag.name for tag in layer.keywords.all()]) if request.method == "POST": keywords_form = KeywordsForm(request.POST, instance=layer) metadata_form = MetadataForm(instance=layer) if 'keywords' in request.POST: if keywords_form.is_valid(): keywords_form.save() new_keywords = keywords_form.cleaned_data['keywords'] layer.keywords.set(*new_keywords) layer.save() metadata_form = MetadataForm(instance=layer) published_form = PublishStatusForm(instance=layer) elif 'title' in request.POST: metadata_form = MetadataForm(request.POST, instance=layer) if metadata_form.is_valid(): metadata_form.save() # update all the metadata if metadata_form.cleaned_data['category'] is not None: new_category = TopicCategory.objects.get( id=metadata_form.cleaned_data['category'].id) Layer.objects.filter(id=layer.id).update( category=new_category) layer.title = metadata_form.cleaned_data['title'] layer.language = metadata_form.cleaned_data['language'] layer.distribution_url = metadata_form.cleaned_data[ 'distribution_url'] layer.data_quality_statement = metadata_form.cleaned_data[ 'data_quality_statement'] layer.purpose = metadata_form.cleaned_data['purpose'] layer.is_published = metadata_form.cleaned_data['is_published'] layer.save() keywords_form = KeywordsForm(instance=layer) elif 'add_keyword' in request.POST: layer.keywords.add(request.POST['add_keyword']) layer.save() elif 'remove_keyword' in request.POST: layer.keywords.remove(request.POST['remove_keyword']) layer.save() else: keywords_form = KeywordsForm(instance=layer) metadata_form = MetadataForm(instance=layer) content_moderators = Group.objects.filter(name='content_moderator').first() thumbnail_dir = os.path.join(settings.MEDIA_ROOT, 'thumbs') default_thumbnail_array = layer.get_thumbnail_url().split('/') default_thumbnail_name = default_thumbnail_array[ len(default_thumbnail_array) - 1] default_thumbnail = os.path.join(thumbnail_dir, default_thumbnail_name) if request.method == 'POST': thumb_form = ThumbnailImageForm(request.POST, request.FILES) if thumb_form.is_valid(): new_img = ThumbnailImage( thumbnail_image=request.FILES['thumbnail_image']) new_img.save() user_upload_thumbnail = ThumbnailImage.objects.all()[0] user_upload_thumbnail_filepath = str( user_upload_thumbnail.thumbnail_image) # only create backup for original thumbnail if os.path.isfile(default_thumbnail + '.bak') is False: os.rename(default_thumbnail, default_thumbnail + '.bak') os.rename(user_upload_thumbnail_filepath, default_thumbnail) else: thumb_form = ThumbnailImageForm() thumbnail = layer.get_thumbnail_url context_dict = { "resource": layer, "permissions_json": _perms_info_json(layer), "documents": get_related_documents(layer), "metadata": metadata, "keywords": keywords, "is_layer": True, "wps_enabled": settings.OGC_SERVER['default']['WPS_ENABLED'], "keywords_form": keywords_form, "metadata_form": metadata_form, "content_moderators": content_moderators, "thumbnail": thumbnail, "thumb_form": thumb_form } context_dict["viewer"] = json.dumps( map_obj.viewer_json(request.user, *(NON_WMS_BASE_LAYERS + [maplayer]))) context_dict["preview"] = getattr(settings, 'LAYER_PREVIEW_LIBRARY') if request.user.has_perm('download_resourcebase', layer.get_self_resource()): if layer.storeType == 'dataStore': links = layer.link_set.download().filter( name__in=settings.DOWNLOAD_FORMATS_VECTOR) else: links = layer.link_set.download().filter( name__in=settings.DOWNLOAD_FORMATS_RASTER) context_dict["links"] = links layer_property_names = [] for attrib in layer.attributes: if attrib.attribute not in settings.SCHEMA_DOWNLOAD_EXCLUDE and not ( attrib.attribute.endswith('_xd') or attrib.attribute.endswith('_parsed')): layer_property_names.append(attrib.attribute) layer_attrib_string = ','.join(layer_property_names) shapefile_link = layer.link_set.download().filter(mime='SHAPE-ZIP').first() if shapefile_link is not None: shapefile_link = shapefile_link.url + '&featureID=fakeID' + '&propertyName=' + layer_attrib_string context_dict["shapefile_link"] = shapefile_link csv_link = layer.link_set.download().filter(mime='csv').first() if csv_link is not None: csv_link = csv_link.url + '&featureID=fakeID' + '&propertyName=' + layer_attrib_string context_dict["csv_link"] = csv_link if settings.SOCIAL_ORIGINS: context_dict["social_links"] = build_social_links(request, layer) return render_to_response(template, RequestContext(request, context_dict))
def ediml(request, layername): layer = _resolve_layer(request, layername, 'base.view_layer', _PERMISSION_MSG_METADATA) ediml = layer.mdextension.elements_xml return HttpResponse(ediml, content_type="text/xml")
def layer_style_manage(request, layername): layer = _resolve_layer(request, layername, 'layers.change_layer_style', _PERMISSION_MSG_MODIFY) if request.method == 'GET': try: cat = gs_catalog # First update the layer style info from GS to GeoNode's DB # The try/except is try: set_styles(layer, cat) except AttributeError: logger.warn( 'Unable to set the default style. Ensure Geoserver is running and that this layer exists.' ) # Ahmed Nour: # Get public styles also all_available_gs_styles = cat.get_styles( settings.DEFAULT_WORKSPACE) all_available_gs_styles += cat.get_styles() gs_styles = [] for style in all_available_gs_styles: sld_title = style.name try: if style.sld_title: sld_title = style.sld_title except BaseException: pass gs_styles.append((style.name, sld_title)) current_layer_styles = layer.styles.all() layer_styles = [] for style in current_layer_styles: sld_title = style.name try: if style.sld_title: sld_title = style.sld_title except BaseException: pass layer_styles.append((style.name, sld_title)) # Render the form sld_title = layer.default_style.name try: if layer.default_style.sld_title: sld_title = layer.default_style.sld_title except BaseException: pass default_style = (layer.default_style.name, sld_title) return render(request, 'layers/layer_style_manage.html', context={ "layer": layer, "gs_styles": gs_styles, "layer_styles": layer_styles, "default_style": default_style }) except (FailedRequestError, EnvironmentError): tb = traceback.format_exc() logger.debug(tb) msg = ('Could not connect to geoserver at "%s"' 'to manage style information for layer "%s"' % (ogc_server_settings.LOCATION, layer.name)) logger.warn(msg) # If geoserver is not online, return an error return render(request, 'layers/layer_style_manage.html', context={ "layer": layer, "error": msg }) elif request.method == 'POST': try: selected_styles = request.POST.getlist('style-select') default_style = request.POST['default_style'] # Save to GeoServer cat = gs_catalog gs_layer = cat.get_layer(layer.name) if gs_layer: gs_layer.default_style = cat.get_style(default_style, workspace=settings.DEFAULT_WORKSPACE) or \ cat.get_style(default_style) styles = [] for style in selected_styles: styles.append( cat.get_style(style, workspace=settings.DEFAULT_WORKSPACE) or cat.get_style(style)) gs_layer.styles = styles cat.save(gs_layer) # Save to Django layer = set_styles(layer, cat) layer.save() # Invalidate GeoWebCache for the updated resource _invalidate_geowebcache_layer(layer.alternate) return HttpResponseRedirect( reverse('layer_detail', args=(layer.service_typename, ))) except (FailedRequestError, EnvironmentError, MultiValueDictKeyError): tb = traceback.format_exc() logger.debug(tb) msg = ('Error Saving Styles for Layer "%s"' % (layer.name)) logger.warn(msg) return render(request, 'layers/layer_style_manage.html', context={ "layer": layer, "error": msg })
def layer_style_upload(request, layername): def respond(*args, **kw): kw['content_type'] = 'text/html' return json_response(*args, **kw) form = LayerStyleUploadForm(request.POST, request.FILES) if not form.is_valid(): return respond(errors="Please provide an SLD file.") data = form.cleaned_data layer = _resolve_layer(request, layername, 'base.change_resourcebase', _PERMISSION_MSG_MODIFY) sld = request.FILES['sld'].read() sld_name = None try: # Check SLD is valid try: if sld: if isfile(sld): sld = open(sld, "r").read() etree.XML(sld) except Exception: logger.exception("The uploaded SLD file is not valid XML") raise Exception("The uploaded SLD file is not valid XML") sld_name = extract_name_from_sld(gs_catalog, sld, sld_file=request.FILES['sld']) except Exception as e: respond(errors="The uploaded SLD file is not valid XML: {}".format(e)) name = data.get('name') or sld_name if data['update']: match = None styles = list(layer.styles) + [layer.default_style] for style in styles: if style.sld_name == name: match = style break if match is None: return respond(errors="Cannot locate style : " + name) match.update_body(sld) else: try: cat = gs_catalog cat.create_style(name, sld, raw=True, workspace=settings.DEFAULT_WORKSPACE) layer.styles = layer.styles + \ [type('style', (object,), {'name': name})] cat.save(layer.publishing) except ConflictingDataError: return respond(errors="""A layer with this name exists. Select the update option if you want to update.""" ) # Invalidate GeoWebCache for the updated resource _invalidate_geowebcache_layer(layer.alternate) return respond(body={ 'success': True, 'style': name, 'updated': data['update'] })
def add_layers_to_map_config(request, map_obj, layer_names, add_base_layers=True): DEFAULT_MAP_CONFIG, DEFAULT_BASE_LAYERS = default_map_config(request) if 'access_token' in request.session: access_token = request.session['access_token'] else: access_token = None bbox = None layers = [] for layer_name in layer_names: try: layer = _resolve_layer(request, layer_name) except ObjectDoesNotExist: # bad layer, skip continue if not layer.is_published: # invisible layer, skip inclusion continue if not request.user.has_perm('view_resourcebase', obj=layer.get_self_resource()): # invisible layer, skip inclusion continue layer_bbox = layer.bbox # assert False, str(layer_bbox) if bbox is None: bbox = list(layer_bbox[0:4]) else: bbox[0] = min(bbox[0], layer_bbox[0]) bbox[1] = max(bbox[1], layer_bbox[1]) bbox[2] = min(bbox[2], layer_bbox[2]) bbox[3] = max(bbox[3], layer_bbox[3]) config = layer.attribute_config() if hasattr(layer, 'srid'): config['crs'] = {'type': 'name', 'properties': layer.srid} # Add required parameters for GXP lazy-loading config["title"] = layer.title config["queryable"] = True config["wrapDateLine"] = True config["srs"] = getattr(settings, 'DEFAULT_MAP_CRS', 'EPSG:900913') config["bbox"] = bbox if config["srs"] != 'EPSG:900913' \ else llbbox_to_mercator([float(coord) for coord in bbox]) if layer.storeType == "remoteStore": service = layer.service # Probably not a good idea to send the access token to every remote service. # This should never match, so no access token should be # sent to remote services. ogc_server_url = urlparse.urlsplit( ogc_server_settings.PUBLIC_LOCATION).netloc service_url = urlparse.urlsplit(service.base_url).netloc if access_token and ogc_server_url == service_url and 'access_token' not in service.base_url: url = service.base_url + '?access_token=' + access_token else: url = service.base_url maplayer = MapLayer(map=map_obj, name=layer.alternate, ows_url=layer.ows_url, layer_params=json.dumps(config), visibility=True, source_params=json.dumps({ "ptype": service.ptype, "remote": True, "url": url, "name": service.name })) else: ogc_server_url = urlparse.urlsplit( ogc_server_settings.PUBLIC_LOCATION).netloc layer_url = urlparse.urlsplit(layer.ows_url).netloc if access_token and ogc_server_url == layer_url and 'access_token' not in layer.ows_url: url = layer.ows_url + '?access_token=' + access_token else: url = layer.ows_url maplayer = MapLayer( map=map_obj, name=layer.alternate, ows_url=url, # use DjangoJSONEncoder to handle Decimal values layer_params=json.dumps(config, cls=DjangoJSONEncoder), visibility=True) layers.append(maplayer) if bbox is not None: minx, maxx, miny, maxy = [float(coord) for coord in bbox] x = (minx + maxx) / 2 y = (miny + maxy) / 2 if getattr(settings, 'DEFAULT_MAP_CRS', 'EPSG:900913') == "EPSG:4326": center = list((x, y)) else: center = list(forward_mercator((x, y))) if center[1] == float('-inf'): center[1] = 0 BBOX_DIFFERENCE_THRESHOLD = 1e-5 # Check if the bbox is invalid valid_x = (maxx - minx)**2 > BBOX_DIFFERENCE_THRESHOLD valid_y = (maxy - miny)**2 > BBOX_DIFFERENCE_THRESHOLD if valid_x: width_zoom = math.log(360 / abs(maxx - minx), 2) else: width_zoom = 15 if valid_y: height_zoom = math.log(360 / abs(maxy - miny), 2) else: height_zoom = 15 map_obj.center_x = center[0] map_obj.center_y = center[1] map_obj.zoom = math.ceil(min(width_zoom, height_zoom)) map_obj.handle_moderated_uploads() if add_base_layers: layers_to_add = DEFAULT_BASE_LAYERS + layers else: layers_to_add = layers config = map_obj.viewer_json(request.user, access_token, *layers_to_add) config['fromLayer'] = True return config
def layer_style_manage(req, layername): layer = _resolve_layer(req, layername, 'layers.change_layer', _PERMISSION_MSG_MODIFY) if req.method == 'GET': try: cat = gs_catalog # First update the layer style info from GS to GeoNode's DB # The try/except is try: set_styles(layer, cat) except AttributeError: logger.warn('Unable to set the default style. Ensure Geoserver is running and that this layer exists.') all_available_gs_styles = cat.get_styles() gs_styles = [] for style in all_available_gs_styles: gs_styles.append(style.name) current_layer_styles = layer.styles.all() layer_styles = [] for style in current_layer_styles: layer_styles.append(style.name) # Render the form return render_to_response( 'layers/layer_style_manage.html', RequestContext(req, { "layer": layer, "gs_styles": gs_styles, "layer_styles": layer_styles, "default_style": layer.default_style.name } ) ) except (FailedRequestError, EnvironmentError) as e: msg = ('Could not connect to geoserver at "%s"' 'to manage style information for layer "%s"' % ( ogc_server_settings.LOCATION, layer.name) ) logger.warn(msg, e) # If geoserver is not online, return an error return render_to_response( 'layers/layer_style_manage.html', RequestContext(req, { "layer": layer, "error": msg } ) ) elif req.method == 'POST': try: selected_styles = req.POST.getlist('style-select') default_style = req.POST['default_style'] # Save to GeoServer cat = gs_catalog gs_layer = cat.get_layer(layer.name) gs_layer.default_style = default_style styles = [] for style in selected_styles: styles.append(style) gs_layer.styles = styles cat.save(gs_layer) # Save to Django layer = set_styles(layer, cat) layer.save() return HttpResponseRedirect(reverse('layer_detail', args=(layer.typename,))) except (FailedRequestError, EnvironmentError, MultiValueDictKeyError) as e: msg = ('Error Saving Styles for Layer "%s"' % (layer.name) ) logger.warn(msg, e) return render_to_response( 'layers/layer_style_manage.html', RequestContext(req, { "layer": layer, "error": msg } ) )
def convert(self, viewer, request): """ input: GeoNode JSON Gxp Config output: MapStore2 compliant str(config) """ # Initialization viewer_obj = json.loads(viewer) map_id = None if 'id' in viewer_obj and viewer_obj['id']: try: map_id = int(viewer_obj['id']) except Exception: pass data = {} data['version'] = 2 # Map Definition try: # Map Definition ms2_map = {} ms2_map['projection'] = viewer_obj['map']['projection'] ms2_map['units'] = viewer_obj['map']['units'] ms2_map['zoom'] = viewer_obj['map'][ 'zoom'] if viewer_obj['map']['zoom'] > 0 else 2 ms2_map['maxExtent'] = viewer_obj['map']['maxExtent'] ms2_map['maxResolution'] = viewer_obj['map']['maxResolution'] # Backgrouns backgrounds = self.getBackgrounds(viewer, MAP_BASELAYERS) if backgrounds: ms2_map['layers'] = backgrounds else: ms2_map['layers'] = MAP_BASELAYERS + [ # TODO: covnert Viewer Background Layers # Add here more backgrounds e.g.: # { # "type": "wms", # "url": "https://demo.geo-solutions.it/geoserver/wms", # "visibility": True, # "opacity": 0.5, # "title": "Weather data", # "name": "nurc:Arc_Sample", # "group": "Meteo", # "format": "image/png", # "bbox": { # "bounds": { # "minx": -25.6640625, # "miny": 26.194876675795218, # "maxx": 48.1640625, # "maxy": 56.80087831233043 # }, # "crs": "EPSG:4326" # } # }, ... ] if settings.BING_API_KEY: ms2_map['bingApiKey'] = settings.BING_API_KEY # Security Info info = {} info['canDelete'] = False info['canEdit'] = False info['description'] = viewer_obj['about']['abstract'] info['id'] = map_id info['name'] = viewer_obj['about']['title'] ms2_map['info'] = info # Overlays overlays, selected = self.get_overlays(viewer, request=request) if selected and 'name' in selected and selected[ 'name'] and not map_id: # We are generating a Layer Details View center, zoom = self.get_center_and_zoom( viewer_obj['map'], selected) ms2_map['center'] = center ms2_map['zoom'] = zoom try: # - extract from GeoNode guardian from geonode.layers.views import (_resolve_layer, _PERMISSION_MSG_MODIFY, _PERMISSION_MSG_DELETE) if _resolve_layer(request, selected['name'], 'base.change_resourcebase', _PERMISSION_MSG_MODIFY): info['canEdit'] = True if _resolve_layer(request, selected['name'], 'base.delete_resourcebase', _PERMISSION_MSG_DELETE): info['canDelete'] = True except Exception: tb = traceback.format_exc() logger.debug(tb) else: # We are getting the configuration of a Map # On GeoNode model the Map Center is always saved in 4326 _x = get_valid_number(viewer_obj['map']['center'][0]) _y = get_valid_number(viewer_obj['map']['center'][1]) _crs = 'EPSG:4326' if _x > 360.0 or _x < -360.0: _crs = viewer_obj['map']['projection'] ms2_map['center'] = {'x': _x, 'y': _y, 'crs': _crs} try: # - extract from GeoNode guardian from geonode.maps.views import (_resolve_map, _PERMISSION_MSG_SAVE, _PERMISSION_MSG_DELETE) if _resolve_map(request, str(map_id), 'base.change_resourcebase', _PERMISSION_MSG_SAVE): info['canEdit'] = True if _resolve_map(request, str(map_id), 'base.delete_resourcebase', _PERMISSION_MSG_DELETE): info['canDelete'] = True except Exception: tb = traceback.format_exc() logger.debug(tb) for overlay in overlays: if 'name' in overlay and overlay['name']: ms2_map['layers'].append(overlay) data['map'] = ms2_map except Exception: # traceback.print_exc() tb = traceback.format_exc() logger.debug(tb) # Additional Configurations if map_id: from mapstore2_adapter import fixup_map from mapstore2_adapter.api.models import MapStoreResource try: fixup_map(map_id) ms2_resource = MapStoreResource.objects.get(id=map_id) ms2_map_data = ms2_resource.data.blob if isinstance(ms2_map_data, string_types): ms2_map_data = json.loads(ms2_map_data) if 'map' in ms2_map_data: for _k, _v in ms2_map_data['map'].items(): if _k not in data['map']: data['map'][_k] = ms2_map_data['map'][_k] del ms2_map_data['map'] data.update(ms2_map_data) except Exception: # traceback.print_exc() tb = traceback.format_exc() logger.debug(tb) # Default Catalogue Services Definition try: ms2_catalogue = {} ms2_catalogue['selectedService'] = CATALOGUE_SELECTED_SERVICE ms2_catalogue['services'] = CATALOGUE_SERVICES data['catalogServices'] = ms2_catalogue except Exception: # traceback.print_exc() tb = traceback.format_exc() logger.debug(tb) json_str = json.dumps(data, cls=DjangoJSONEncoder, sort_keys=True) for (c, d) in unsafe_chars.items(): json_str = json_str.replace(c, d) return json_str
def download_clip(request, layername, clip_filename): """Download clipped file. Clipping layer by bbox or by geojson. :param layername: The layer name in Geonode. :type layername: basestring :param clip_filename: clipped filename :type clip_filename: basestring :return: The HTTPResponse with a file. """ # PREPARATION layer = _resolve_layer(request, layername, 'base.view_resourcebase', _PERMISSION_MSG_VIEW) query = request.GET or request.POST params = {param.upper(): value for param, value in query.iteritems()} current_date = datetime.datetime.today().strftime('%Y-%m-%d_%H-%M-%S') # create temp folder temporary_folder = os.path.join(tempfile.gettempdir(), 'clipped') try: os.mkdir(temporary_folder) except OSError as e: pass # get file for raster raster_filepath = None extention = '' file_names = [] try: for layerfile in layer.upload_session.layerfile_set.all(): file_names.append(layerfile.file.path) for target_file in file_names: if '.tif' in target_file: raster_filepath = target_file target_filename, extention = os.path.splitext(target_file) break except AttributeError: raster_filepath = layername pass # get temp filename for output filename = os.path.basename(clip_filename) output = os.path.join(temporary_folder, clip_filename) if os.path.exists(output): # Create zip file s = StringIO.StringIO() zf = zipfile.ZipFile(s, "w") zip_subdir = layer.name + '_clipped' zip_filename = "%s.zip" % zip_subdir files_to_zipped = [] for filename in file_names: if not filename.endswith('.qgs') and \ not filename.endswith(extention): files_to_zipped.append(filename) for fpath in files_to_zipped: # Calculate path for file in zip fdir, fname = os.path.split(fpath) fnames = fname.split('.') fname = fnames[0] + '.' + current_date + '.' + fnames[1] zip_path = os.path.join(zip_subdir, fname) zf.write(fpath, zip_path) # Add clipped raster opath, oname = os.path.split(output) zip_path = os.path.join(zip_subdir, oname) zf.write(output, zip_path) # Must close zip for all contents to be written zf.close() resp = HttpResponse(s.getvalue(), content_type="application/x-zip-compressed") resp['Content-Disposition'] = 'attachment; filename=%s' % zip_filename return resp else: raise Http404('Project can not be clipped or masked.')
def layer_detail(request, layername, template='layers/layer_detail.html'): #if template: #logger.warning('Template param not expected: %s', template) layer = _resolve_layer(request, layername, 'base.view_resourcebase', _PERMISSION_MSG_VIEW) # assert False, str(layer_bbox) config = layer.attribute_config() # Add required parameters for GXP lazy-loading layer_bbox = layer.bbox bbox = [float(coord) for coord in list(layer_bbox[0:4])] srid = layer.srid # Transform WGS84 to Mercator. config["srs"] = srid if srid != "EPSG:4326" else "EPSG:900913" config["bbox"] = llbbox_to_mercator([float(coord) for coord in bbox]) config["title"] = layer.title config["queryable"] = True if layer.storeType == "remoteStore": service = layer.service source_params = { "ptype": service.ptype, "remote": True, "url": service.base_url, "name": service.name } maplayer = GXPLayer(name=layer.typename, ows_url=layer.ows_url, layer_params=json.dumps(config), source_params=json.dumps(source_params)) else: maplayer = GXPLayer(name=layer.typename, ows_url=layer.ows_url, layer_params=json.dumps(config)) # Update count for popularity ranking, # but do not includes admins or resource owners if request.user != layer.owner and not request.user.is_superuser: Layer.objects.filter(id=layer.id).update( popular_count=F('popular_count') + 1) # center/zoom don't matter; the viewer will center on the layer bounds map_obj = GXPMap(projection="EPSG:900913") NON_WMS_BASE_LAYERS = [ la for la in default_map_config()[1] if la.ows_url is None ] metadata = layer.link_set.metadata().filter( name__in=settings.DOWNLOAD_FORMATS_METADATA) granules = None all_granules = None granule_filter = None if layer.is_mosaic: try: cat = gs_catalog cat._cache.clear() store = cat.get_store(layer.name) coverages = cat.mosaic_coverages(store) granule_filter = None try: if request.GET["filter"]: granule_filter = request.GET["filter"] except: pass schema = cat.mosaic_coverage_schema( coverages['coverages']['coverage'][0]['name'], store) offset = 10 * (request.page - 1) granules = cat.mosaic_granules( coverages['coverages']['coverage'][0]['name'], store, limit=10, offset=offset, filter=granule_filter) all_granules = cat.mosaic_granules( coverages['coverages']['coverage'][0]['name'], store, filter=granule_filter) except: granules = {"features": []} all_granules = {"features": []} import traceback traceback.print_exc() #print (' +++++++++++++++++++++++++++++++++++++++++ \n' + str(granules) + '\n +++++++++++++++++++++++++++++++++++++++++ ') context_dict = { "resource": layer, 'perms_list': get_perms(request.user, layer.get_self_resource()), "permissions_json": _perms_info_json(layer), "documents": get_related_documents(layer), "metadata": metadata, "is_layer": True, "wps_enabled": settings.OGC_SERVER['default']['WPS_ENABLED'], "is_owner": request.user == layer.owner, "is_superuser": request.user.is_superuser, "granules": granules, "all_granules": all_granules, "filter": granule_filter, } context_dict["viewer"] = json.dumps( map_obj.viewer_json(request.user, *(NON_WMS_BASE_LAYERS + [maplayer]))) context_dict["preview"] = getattr(settings, 'LAYER_PREVIEW_LIBRARY', 'leaflet') if request.user.has_perm('download_resourcebase', layer.get_self_resource()): if layer.storeType == 'dataStore': links = layer.link_set.download().filter( name__in=settings.DOWNLOAD_FORMATS_VECTOR) else: links = layer.link_set.download().filter( name__in=settings.DOWNLOAD_FORMATS_RASTER) context_dict["links"] = links if settings.SOCIAL_ORIGINS: context_dict["social_links"] = build_social_links(request, layer) #if request.user.is_superuser: #logger.debug("Dispatching to admin page") #else: #logger.debug("Dispatching to user page") #template = 'layers/layer_detail_admin.html' if request.user.is_superuser else 'layers/layer_detail_user.html' return render_to_response(template, RequestContext(request, context_dict))
def rndt(request, layername): layer = _resolve_layer(request, layername, 'base.view_layer', _PERMISSION_MSG_METADATA) rndt = layer.mdextension.rndt_xml return HttpResponse(rndt, content_type="text/xml")
def layer_metadata_create(request, layername, template='layers/cread_layer_metadata.html', publish=False): logger.debug("*** ENTER CREAD:layer_metadata_create (pub=%s)", publish) layer = _resolve_layer(request, layername, 'base.change_resourcebase_metadata', _PERMISSION_MSG_METADATA) clayerqs = CReadResource.objects.filter(resource=layer) if len(clayerqs) == 0: logger.info('cread_resource does not exist for layer %r', layer) cread_resource = None else: logger.debug('cread_resource found for layer %r (%d)', layer, len(clayerqs)) cread_resource = clayerqs[0] layer_attribute_set = inlineformset_factory( Layer, Attribute, extra=0, form=LayerAttributeForm, ) topic_category = layer.category cread_subcategory = cread_resource.subcategory if cread_resource else None poc = layer.poc metadata_author = layer.metadata_author if request.method == "POST": baseinfo_form = CReadBaseInfoForm(request.POST, prefix="baseinfo") layer_form = CReadLayerForm(request.POST, instance=layer, prefix="resource") attribute_form = layer_attribute_set( request.POST, instance=layer, prefix="layer_attribute_set", queryset=Attribute.objects.order_by('display_order')) category_form = CategoryForm( request.POST, prefix="category_choice_field", initial=int(request.POST["category_choice_field"]) if "category_choice_field" in request.POST else None) #cread_category_form = CReadCategoryForm( #request.POST, #prefix="cread_category_choice_field", #initial=int( #request.POST["cread_category_choice_field"]) if "cread_category_choice_field" in request.POST else None) cread_subcategory_form = CReadSubCategoryForm( request.POST, prefix="cread_subcategory_choice_field", initial=int(request.POST["cread_subcategory_choice_field"]) if "cread_subcategory_choice_field" in request.POST else None) else: baseinfo_form = CReadBaseInfoForm(prefix="baseinfo", initial={ 'title': layer.title, 'abstract': layer.abstract }) layer_form = CReadLayerForm(instance=layer, prefix="resource") #_preprocess_fields(layer_form) attribute_form = layer_attribute_set( instance=layer, prefix="layer_attribute_set", queryset=Attribute.objects.order_by('display_order')) category_form = CategoryForm( prefix="category_choice_field", initial=topic_category.id if topic_category else None) #cread_category_form = CReadCategoryForm( #prefix="cread_category_choice_field", #initial=cread_category.id if cread_category else None) cread_subcategory_form = CReadSubCategoryForm( prefix="cread_subcategory_choice_field", initial=cread_subcategory.id if cread_subcategory else None) if request.method == "POST" \ and baseinfo_form.is_valid() \ and layer_form.is_valid() \ and attribute_form.is_valid() \ and cread_subcategory_form.is_valid(): new_poc = layer_form.cleaned_data['poc'] new_author = layer_form.cleaned_data['metadata_author'] new_keywords = layer_form.cleaned_data['keywords'] if new_poc is None: if poc is None: poc_form = ProfileForm(request.POST, prefix="poc", instance=poc) else: poc_form = ProfileForm(request.POST, prefix="poc") if poc_form.has_changed and poc_form.is_valid(): new_poc = poc_form.save() if new_author is None: if metadata_author is None: author_form = ProfileForm(request.POST, prefix="author", instance=metadata_author) else: author_form = ProfileForm(request.POST, prefix="author") if author_form.has_changed and author_form.is_valid(): new_author = author_form.save() # CRead category # note: call to is_valid is needed to compute the cleaned data if (cread_subcategory_form.is_valid()): logger.info("Checking CReadLayer record %r ", cread_subcategory_form.is_valid()) #cread_cat_id = cread_category_form.cleaned_data['cread_category_choice_field'] #cread_cat_id = cread_cat_id if cread_cat_id else 1 #new_creadcategory = CReadCategory.objects.get(id=cread_cat_id) cread_subcat_id = cread_subcategory_form.cleaned_data[ 'cread_subcategory_choice_field'] new_creadsubcategory = CReadSubCategory.objects.get( id=cread_subcat_id) new_creadcategory = new_creadsubcategory.category logger.debug("Selected cread cat/subcat: %s : %s / %s", new_creadcategory.identifier, new_creadcategory.name, new_creadsubcategory.identifier) if cread_resource: logger.info("Update CReadResource record") else: logger.info("Create new CReadResource record") cread_resource = CReadResource() cread_resource.resource = layer cread_resource.category = new_creadcategory cread_resource.subcategory = new_creadsubcategory cread_resource.save() # End cread category else: new_creadsubcategory = None logger.info("CRead subcategory form is not valid") if category_form.is_valid(): new_category = TopicCategory.objects.get( id=category_form.cleaned_data['category_choice_field']) elif new_creadsubcategory: logger.debug("Assigning default ISO category") new_category = TopicCategory.objects.get( id=new_creadsubcategory.relatedtopic.id) for form in attribute_form.cleaned_data: la = Attribute.objects.get(id=int(form['id'].id)) la.description = form["description"] la.attribute_label = form["attribute_label"] la.visible = form["visible"] la.display_order = form["display_order"] la.save() if new_poc is not None and new_author is not None: new_keywords = layer_form.cleaned_data['keywords'] layer.keywords.clear() layer.keywords.add(*new_keywords) the_layer = layer_form.save() the_layer.poc = new_poc the_layer.metadata_author = new_author Layer.objects.filter(id=the_layer.id).update( category=new_category, title=baseinfo_form.cleaned_data['title'], abstract=baseinfo_form.cleaned_data['abstract']) if publish is not None: logger.debug("Setting publish status to %s for layer %s", publish, layername) Layer.objects.filter(id=the_layer.id).update( is_published=publish) return HttpResponseRedirect( reverse('layer_detail', args=(layer.service_typename, ))) logger.debug("baseinfo valid %s ", baseinfo_form.is_valid()) logger.debug("layer valid %s ", layer_form.is_valid()) logger.debug("attribute valid %s ", attribute_form.is_valid()) logger.debug("subcat valid %s ", cread_subcategory_form.is_valid()) if poc is None: poc_form = ProfileForm(instance=poc, prefix="poc") else: layer_form.fields['poc'].initial = poc.id poc_form = ProfileForm(prefix="poc") poc_form.hidden = True if metadata_author is None: author_form = ProfileForm(instance=metadata_author, prefix="author") else: layer_form.fields['metadata_author'].initial = metadata_author.id author_form = ProfileForm(prefix="author") author_form.hidden = True # creates cat - subcat association categories_struct = [] for category in CReadCategory.objects.all(): subcats = [] for subcat in CReadSubCategory.objects.filter(category=category): subcats.append(subcat.id) categories_struct.append((category.id, category.description, subcats)) return render_to_response( template, RequestContext( request, { "layer": layer, "baseinfo_form": baseinfo_form, "layer_form": layer_form, "poc_form": poc_form, "author_form": author_form, "attribute_form": attribute_form, "category_form": category_form, "cread_form": None, # read_category_form, "cread_sub_form": cread_subcategory_form, "cread_categories": categories_struct }))
def layer_detail(request, layername, template='layers/layer_detail.html'): layer = _resolve_layer(request, layername, 'base.view_resourcebase', _PERMISSION_MSG_VIEW) # assert False, str(layer_bbox) config = layer.attribute_config() # TODO (Mapstory): This has been commented out to force the client to make a getCapabilities request in order # to pull in the time dimension data. Ideally we would cache time data just like the srs and bbox data to prevent # making the getCapabilities request. # Add required parameters for GXP lazy-loading #layer_bbox = layer.bbox #bbox = [float(coord) for coord in list(layer_bbox[0:4])] #srid = layer.srid # Transform WGS84 to Mercator. #config["srs"] = srid if srid != "EPSG:4326" else "EPSG:900913" #config["bbox"] = llbbox_to_mercator([float(coord) for coord in bbox]) #config["title"] = layer.title #config["queryable"] = True if layer.storeType == "remoteStore": service = layer.service source_params = { "ptype": service.ptype, "remote": True, "url": service.base_url, "name": service.name } maplayer = GXPLayer(name=layer.typename, ows_url=layer.ows_url, layer_params=json.dumps(config), source_params=json.dumps(source_params)) else: maplayer = GXPLayer(name=layer.name, ows_url=layer.ows_url, layer_params=json.dumps(config)) # Update count for popularity ranking, # but do not includes admins or resource owners if request.user != layer.owner and not request.user.is_superuser: Layer.objects.filter(id=layer.id).update( popular_count=F('popular_count') + 1) # center/zoom don't matter; the viewer will center on the layer bounds map_obj = GXPMap(projection="EPSG:900913") NON_WMS_BASE_LAYERS = [ la for la in default_map_config()[1] if la.ows_url is None ] metadata = layer.link_set.metadata().filter( name__in=settings.DOWNLOAD_FORMATS_METADATA) if request.method == "POST": keywords_form = KeywordsForm(request.POST, instance=layer) metadata_form = MetadataForm(request.POST, instance=layer) published_form = PublishStatusForm(request.POST, instance=layer) if keywords_form.is_valid(): new_keywords = keywords_form.cleaned_data['keywords'] layer.keywords.clear() layer.keywords.add(*new_keywords) if metadata_form.is_valid(): # update all the metadata if metadata_form.cleaned_data['category'] is not None: new_category = TopicCategory.objects.get( id=metadata_form.cleaned_data['category'].id) Layer.objects.filter(id=layer.id).update(category=new_category) new_language = metadata_form.cleaned_data['language'] new_distribution_url = metadata_form.cleaned_data[ 'distribution_url'] new_data_quality_statement = metadata_form.cleaned_data[ 'data_quality_statement'] new_purpose = metadata_form.cleaned_data['purpose'] layer.language = new_language layer.distribution_url = new_distribution_url layer.data_quality_statement = new_data_quality_statement layer.purpose = new_purpose layer.save() if published_form.is_valid(): layer.is_published = published_form.cleaned_data['is_published'] layer.save() else: keywords_form = KeywordsForm(instance=layer) metadata_form = MetadataForm(instance=layer) published_form = PublishStatusForm(instance=layer) content_moderators = Group.objects.filter(name='content_moderator').first() context_dict = { "resource": layer, "permissions_json": _perms_info_json(layer), "documents": get_related_documents(layer), "metadata": metadata, "is_layer": True, "wps_enabled": settings.OGC_SERVER['default']['WPS_ENABLED'], "keywords_form": keywords_form, "metadata_form": metadata_form, "published_form": published_form, "content_moderators": content_moderators, } context_dict["viewer"] = json.dumps( map_obj.viewer_json(request.user, *(NON_WMS_BASE_LAYERS + [maplayer]))) context_dict["preview"] = getattr(settings, 'LAYER_PREVIEW_LIBRARY', 'leaflet') if request.user.has_perm('download_resourcebase', layer.get_self_resource()): if layer.storeType == 'dataStore': links = layer.link_set.download().filter( name__in=settings.DOWNLOAD_FORMATS_VECTOR) else: links = layer.link_set.download().filter( name__in=settings.DOWNLOAD_FORMATS_RASTER) context_dict["links"] = links if settings.SOCIAL_ORIGINS: context_dict["social_links"] = build_social_links(request, layer) return render_to_response(template, RequestContext(request, context_dict))
def rndteditor(request, layername): layer = _resolve_layer(request, layername, 'layers.change_layer', _PERMISSION_MSG_METADATA) queryStringValues = { 'template': 'RNDT', 'version': '2.00', 'parameters': "{}" } fileid = layer.mdextension.fileid pars = {} if fileid is not None: queryStringValues['edit'] = fileid pars = { 'uid': layer.uuid, 'westlon': layer.bbox_x0, 'eastlon': layer.bbox_x1, 'southlat': layer.bbox_y0, 'northlat': layer.bbox_y1, } else: pars = { 'uid': layer.uuid, # inserire data_md 'title': layer.title, 'data_md': layer.mdextension.md_date.date().isoformat(), 'data': layer.date, 'tipo_di_data': layer.date_type, 'abstract': layer.abstract, 'spatialrepresentationtype': (EDI_MAP_SPATIALREPRESENTATIONTYPE).get(layer.storeType), 'westlon': layer.bbox_x0, 'eastlon': layer.bbox_x1, 'southlat': layer.bbox_y0, 'northlat': layer.bbox_y1, 'resource': '%s%s' % (settings.SITEURL[:-1], layer.get_absolute_url()), 'referencesystem': layer.srid, } js_pars = json.dumps(pars, cls=DjangoJSONEncoder) queryStringValues['parameters'] = json.dumps(pars, cls=DjangoJSONEncoder) js_queryStringValues = json.dumps(queryStringValues) return render_to_response( 'mdtools/rndt.html', RequestContext( request, { 'layername': layername, 'queryStringValues': mark_safe(js_queryStringValues) }))
def layer_style_manage(request, layername): layer = _resolve_layer(request, layername, 'layers.change_layer_style', _PERMISSION_MSG_MODIFY) if request.method == 'GET': try: cat = gs_catalog # First update the layer style info from GS to GeoNode's DB try: set_styles(layer, cat) except AttributeError: logger.warn( 'Unable to set the default style. Ensure Geoserver is running and that this layer exists.' ) gs_styles = [] # Temporary Hack to remove GeoServer temp styles from the list Style.objects.filter( name__iregex=r'\w{8}-\w{4}-\w{4}-\w{4}-\w{12}_(ms)_\d{13}' ).delete() for style in Style.objects.values('name', 'sld_title'): gs_styles.append((style['name'], style['sld_title'])) current_layer_styles = layer.styles.all() layer_styles = [] for style in current_layer_styles: sld_title = style.name try: if style.sld_title: sld_title = style.sld_title except Exception: tb = traceback.format_exc() logger.debug(tb) layer_styles.append((style.name, sld_title)) # Render the form def_sld_name = None # noqa def_sld_title = None # noqa default_style = None if layer.default_style: def_sld_name = layer.default_style.name # noqa def_sld_title = layer.default_style.name # noqa try: if layer.default_style.sld_title: def_sld_title = layer.default_style.sld_title except Exception: tb = traceback.format_exc() logger.debug(tb) default_style = (def_sld_name, def_sld_title) return render(request, 'layers/layer_style_manage.html', context={ "layer": layer, "gs_styles": gs_styles, "layer_styles": layer_styles, "layer_style_names": [s[0] for s in layer_styles], "default_style": default_style }) except (FailedRequestError, EnvironmentError): tb = traceback.format_exc() logger.debug(tb) msg = ('Could not connect to geoserver at "%s"' 'to manage style information for layer "%s"' % (ogc_server_settings.LOCATION, layer.name)) logger.debug(msg) # If geoserver is not online, return an error return render(request, 'layers/layer_style_manage.html', context={ "layer": layer, "error": msg }) elif request.method in ('POST', 'PUT', 'DELETE'): try: selected_styles = request.POST.getlist('style-select') default_style = request.POST['default_style'] # Save to GeoServer cat = gs_catalog gs_layer = cat.get_layer(layer.name) if not gs_layer: gs_layer = cat.get_layer(layer.alternate) if gs_layer: gs_layer.default_style = cat.get_style(default_style, workspace=settings.DEFAULT_WORKSPACE) or \ cat.get_style(default_style) styles = [] for style in selected_styles: gs_sld = cat.get_style(style, workspace=settings.DEFAULT_WORKSPACE ) or cat.get_style(style) if gs_sld: styles.append(gs_sld) gs_layer.styles = styles cat.save(gs_layer) # Save to Django set_styles(layer, cat) # Invalidate GeoWebCache for the updated resource try: _stylefilterparams_geowebcache_layer(layer.alternate) _invalidate_geowebcache_layer(layer.alternate) except Exception: pass return HttpResponseRedirect( reverse('layer_detail', args=(layer.service_typename, ))) except (FailedRequestError, EnvironmentError, MultiValueDictKeyError): tb = traceback.format_exc() logger.debug(tb) msg = ('Error Saving Styles for Layer "%s"' % (layer.name)) logger.warn(msg) return render(request, 'layers/layer_style_manage.html', context={ "layer": layer, "error": msg })
def add_layers_to_map_config(request, map_obj, layer_names, add_base_layers=True): DEFAULT_MAP_CONFIG, DEFAULT_BASE_LAYERS = default_map_config(request) if 'access_token' in request.session: access_token = request.session['access_token'] else: access_token = None bbox = [] layers = [] for layer_name in layer_names: try: layer = _resolve_layer(request, layer_name) except ObjectDoesNotExist: # bad layer, skip continue if not request.user.has_perm('view_resourcebase', obj=layer.get_self_resource()): # invisible layer, skip inclusion continue layer_bbox = layer.bbox[0:4] bbox = layer_bbox[:] bbox[0] = layer_bbox[0] bbox[1] = layer_bbox[2] bbox[2] = layer_bbox[1] bbox[3] = layer_bbox[3] # assert False, str(layer_bbox) def decimal_encode(bbox): import decimal _bbox = [] for o in [float(coord) for coord in bbox]: if isinstance(o, decimal.Decimal): o = (str(o) for o in [o]) _bbox.append(o) return _bbox def sld_definition(style): from urllib import quote _sld = { "title": style.sld_title or style.name, "legend": { "height": "40", "width": "22", "href": layer.ows_url + "?service=wms&request=GetLegendGraphic&format=image%2Fpng&width=20&height=20&layer=" + quote(layer.service_typename, safe=''), "format": "image/png" }, "name": style.name } return _sld config = layer.attribute_config() if hasattr(layer, 'srid'): config['crs'] = {'type': 'name', 'properties': layer.srid} # Add required parameters for GXP lazy-loading attribution = "%s %s" % ( layer.owner.first_name, layer.owner.last_name ) if layer.owner.first_name or layer.owner.last_name else str( layer.owner) srs = getattr(settings, 'DEFAULT_MAP_CRS', 'EPSG:3857') srs_srid = int(srs.split(":")[1]) if srs != "EPSG:900913" else 3857 config[ "attribution"] = "<span class='gx-attribution-title'>%s</span>" % attribution config["format"] = getattr(settings, 'DEFAULT_LAYER_FORMAT', 'image/png') config["title"] = layer.title config["wrapDateLine"] = True config["visibility"] = True config["srs"] = srs config["bbox"] = decimal_encode( bbox_to_projection([float(coord) for coord in layer_bbox] + [ layer.srid, ], target_srid=int(srs.split(":")[1]))[:4]) config["capability"] = { "abstract": layer.abstract, "name": layer.alternate, "title": layer.title, "queryable": True, "bbox": { layer.srid: { "srs": layer.srid, "bbox": decimal_encode(bbox) }, srs: { "srs": srs, "bbox": decimal_encode( bbox_to_projection( [float(coord) for coord in layer_bbox] + [ layer.srid, ], target_srid=srs_srid)[:4]) }, "EPSG:4326": { "srs": "EPSG:4326", "bbox": decimal_encode(bbox) if layer.srid == 'EPSG:4326' else decimal_encode( bbox_to_projection( [float(coord) for coord in layer_bbox] + [ layer.srid, ], target_srid=4326)[:4]) }, "EPSG:900913": { "srs": "EPSG:900913", "bbox": decimal_encode(bbox) if layer.srid == 'EPSG:900913' else decimal_encode( bbox_to_projection( [float(coord) for coord in layer_bbox] + [ layer.srid, ], target_srid=3857)[:4]) } }, "srs": { srs: True }, "formats": [ "image/png", "application/atom xml", "application/atom+xml", "application/json;type=utfgrid", "application/openlayers", "application/pdf", "application/rss xml", "application/rss+xml", "application/vnd.google-earth.kml", "application/vnd.google-earth.kml xml", "application/vnd.google-earth.kml+xml", "application/vnd.google-earth.kml+xml;mode=networklink", "application/vnd.google-earth.kmz", "application/vnd.google-earth.kmz xml", "application/vnd.google-earth.kmz+xml", "application/vnd.google-earth.kmz;mode=networklink", "atom", "image/geotiff", "image/geotiff8", "image/gif", "image/gif;subtype=animated", "image/jpeg", "image/png8", "image/png; mode=8bit", "image/svg", "image/svg xml", "image/svg+xml", "image/tiff", "image/tiff8", "image/vnd.jpeg-png", "kml", "kmz", "openlayers", "rss", "text/html; subtype=openlayers", "utfgrid" ], "attribution": { "title": attribution }, "infoFormats": [ "text/plain", "application/vnd.ogc.gml", "text/xml", "application/vnd.ogc.gml/3.1.1", "text/xml; subtype=gml/3.1.1", "text/html", "application/json" ], "styles": [sld_definition(s) for s in layer.styles.all()], "prefix": layer.alternate.split(":")[0] if ":" in layer.alternate else "", "keywords": [k.name for k in layer.keywords.all()] if layer.keywords else [], "llbbox": decimal_encode(bbox) if layer.srid == 'EPSG:4326' else decimal_encode( bbox_to_projection([float(coord) for coord in layer_bbox] + [ layer.srid, ], target_srid=4326)[:4]) } all_times = None if check_ogc_backend(geoserver.BACKEND_PACKAGE): from geonode.geoserver.views import get_capabilities workspace, layername = layer.alternate.split( ":") if ":" in layer.alternate else (None, layer.alternate) # WARNING Please make sure to have enabled DJANGO CACHE as per # https://docs.djangoproject.com/en/2.0/topics/cache/#filesystem-caching wms_capabilities_resp = get_capabilities(request, layer.id, tolerant=True) if wms_capabilities_resp.status_code >= 200 and wms_capabilities_resp.status_code < 400: wms_capabilities = wms_capabilities_resp.getvalue() if wms_capabilities: import xml.etree.ElementTree as ET e = ET.fromstring(wms_capabilities) for atype in e.findall( "./[Name='%s']/Extent[@name='time']" % (layername)): dim_name = atype.get('name') if dim_name: dim_name = str(dim_name).lower() if dim_name == 'time': dim_values = atype.text if dim_values: all_times = dim_values.split(",") break if all_times: config["capability"]["dimensions"] = { "time": { "name": "time", "units": "ISO8601", "unitsymbol": None, "nearestVal": False, "multipleVal": False, "current": False, "default": "current", "values": all_times } } if layer.storeType == "remoteStore": service = layer.remote_service source_params = {} if service.type in ('REST_MAP', 'REST_IMG'): source_params = { "ptype": service.ptype, "remote": True, "url": service.service_url, "name": service.name, "title": "[R] %s" % service.title } maplayer = MapLayer(map=map_obj, name=layer.alternate, ows_url=layer.ows_url, layer_params=json.dumps(config), visibility=True, source_params=json.dumps(source_params)) else: ogc_server_url = urlparse.urlsplit( ogc_server_settings.PUBLIC_LOCATION).netloc layer_url = urlparse.urlsplit(layer.ows_url).netloc if access_token and ogc_server_url == layer_url and 'access_token' not in layer.ows_url: url = layer.ows_url + '?access_token=' + access_token else: url = layer.ows_url maplayer = MapLayer( map=map_obj, name=layer.alternate, ows_url=url, # use DjangoJSONEncoder to handle Decimal values layer_params=json.dumps(config, cls=DjangoJSONEncoder), visibility=True) layers.append(maplayer) if bbox and len(bbox) >= 4: minx, maxx, miny, maxy = [float(coord) for coord in bbox] x = (minx + maxx) / 2 y = (miny + maxy) / 2 if getattr(settings, 'DEFAULT_MAP_CRS', 'EPSG:3857') == "EPSG:4326": center = list((x, y)) else: center = list(forward_mercator((x, y))) if center[1] == float('-inf'): center[1] = 0 BBOX_DIFFERENCE_THRESHOLD = 1e-5 # Check if the bbox is invalid valid_x = (maxx - minx)**2 > BBOX_DIFFERENCE_THRESHOLD valid_y = (maxy - miny)**2 > BBOX_DIFFERENCE_THRESHOLD if valid_x: width_zoom = math.log(360 / abs(maxx - minx), 2) else: width_zoom = 15 if valid_y: height_zoom = math.log(360 / abs(maxy - miny), 2) else: height_zoom = 15 map_obj.center_x = center[0] map_obj.center_y = center[1] map_obj.zoom = math.ceil(min(width_zoom, height_zoom)) map_obj.handle_moderated_uploads() if add_base_layers: layers_to_add = DEFAULT_BASE_LAYERS + layers else: layers_to_add = layers config = map_obj.viewer_json(request.user, access_token, *layers_to_add) config['fromLayer'] = True return config
def new_map_config(request): ''' View that creates a new map. If the query argument 'copy' is given, the initial map is a copy of the map with the id specified, otherwise the default map configuration is used. If copy is specified and the map specified does not exist a 404 is returned. ''' DEFAULT_MAP_CONFIG, DEFAULT_BASE_LAYERS = default_map_config() if request.method == 'GET' and 'copy' in request.GET: mapid = request.GET['copy'] map_obj = _resolve_map(request, mapid, 'base.view_resourcebase') map_obj.abstract = DEFAULT_ABSTRACT map_obj.title = DEFAULT_TITLE if request.user.is_authenticated(): map_obj.owner = request.user config = map_obj.viewer_json(request.user) del config['id'] else: if request.method == 'GET': params = request.GET elif request.method == 'POST': params = request.POST else: return HttpResponse(status=405) if 'layer' in params: bbox = None map_obj = Map(projection="EPSG:900913") layers = [] for layer_name in params.getlist('layer'): try: layer = _resolve_layer(request, layer_name) except ObjectDoesNotExist: # bad layer, skip continue if not request.user.has_perm( 'view_resourcebase', obj=layer.get_self_resource()): # invisible layer, skip inclusion continue layer_bbox = layer.bbox # assert False, str(layer_bbox) if bbox is None: bbox = list(layer_bbox[0:4]) else: bbox[0] = min(bbox[0], layer_bbox[0]) bbox[1] = max(bbox[1], layer_bbox[1]) bbox[2] = min(bbox[2], layer_bbox[2]) bbox[3] = max(bbox[3], layer_bbox[3]) config = layer.attribute_config() # Add required parameters for GXP lazy-loading config["srs"] = layer.srid config["title"] = layer.title config["bbox"] = [ float(coord) for coord in bbox] if layer.srid == "EPSG:4326" else llbbox_to_mercator( [ float(coord) for coord in bbox]) config["queryable"] = True if layer.storeType == "remoteStore": service = layer.service maplayer = MapLayer(map=map_obj, name=layer.typename, ows_url=layer.ows_url, layer_params=json.dumps(config), visibility=True, source_params=json.dumps({ "ptype": service.ptype, "remote": True, "url": service.base_url, "name": service.name})) else: maplayer = MapLayer( map=map_obj, name=layer.typename, ows_url=layer.ows_url, layer_params=json.dumps(config), visibility=True ) layers.append(maplayer) if bbox is not None: minx, miny, maxx, maxy = [float(c) for c in bbox] x = (minx + maxx) / 2 y = (miny + maxy) / 2 center = list(forward_mercator((x, y))) if center[1] == float('-inf'): center[1] = 0 BBOX_DIFFERENCE_THRESHOLD = 1e-5 # Check if the bbox is invalid valid_x = (maxx - minx) ** 2 > BBOX_DIFFERENCE_THRESHOLD valid_y = (maxy - miny) ** 2 > BBOX_DIFFERENCE_THRESHOLD if valid_x: width_zoom = math.log(360 / abs(maxx - minx), 2) else: width_zoom = 15 if valid_y: height_zoom = math.log(360 / abs(maxy - miny), 2) else: height_zoom = 15 map_obj.center_x = center[0] map_obj.center_y = center[1] map_obj.zoom = math.ceil(min(width_zoom, height_zoom)) config = map_obj.viewer_json( request.user, *(DEFAULT_BASE_LAYERS + layers)) config['fromLayer'] = True else: config = DEFAULT_MAP_CONFIG return json.dumps(config)
def edit_layer_gazetteer(request, layername): """ Manage the layer in the gazetteer. """ def set_none_if_empty(str): if len(str) == 0: return None return str layer = _resolve_layer(request, layername, 'base.change_resourcebase_metadata', 'permissions message from grazetteer') status_message = None if request.method == 'POST': status_message = '' gazetteer_name = set_none_if_empty( request.POST.get('gazetteer-name', '')) start_attribute = set_none_if_empty( request.POST.get('start-attribute', '')) end_attribute = set_none_if_empty(request.POST.get( 'end-attribute', '')) sel_start_date_format = set_none_if_empty( request.POST.get('sel-start-date-format', '')) sel_end_date_format = set_none_if_empty( request.POST.get('sel-end-date-format', '')) attributes_list = request.POST.getlist('attributes') for attribute in layer.attributes: if attribute.attribute in attributes_list: logger.debug('Adding %s to gazetteer...' % attribute.attribute) gaz_att, created = GazetteerAttribute.objects.get_or_create( attribute=attribute) gaz_att.in_gazetteer = True if start_attribute == attribute.attribute: gaz_att.is_start_date = True gaz_att.date_format = sel_start_date_format if end_attribute == attribute.attribute: gaz_att.is_end_date = True gaz_att.date_format = sel_end_date_format gaz_att.save() status_message += ' %s' % attribute.attribute else: logger.debug('Removing %s from gazetteer...' % attribute.attribute) gaz_att, created = GazetteerAttribute.objects.get_or_create( attribute=attribute) gaz_att.in_gazetteer = False gaz_att.save() # now update the gazetteer # TODO use Celery for this add_to_gazetteer(layer, attributes_list, start_attribute, end_attribute, gazetteer_name, request.user.username) gazetteer_attributes = [] for attribute in layer.attributes: if hasattr(attribute, 'gazetteerattribute'): attribute.in_gazetteer = attribute.gazetteerattribute.in_gazetteer else: attribute.in_gazetteer = False gazetteer_attributes.append(attribute) template = 'gazetteer/edit_layer_gazetteer.html' return render( request, template, { "layer": layer, "gazetteer_attributes": gazetteer_attributes, "status_message": status_message, })