def add_tableau(request, loc_code): """ Respond to the "/add_tableau/XYZ" URL. We let the user add a new tableau to the given location. """ if not request.user.is_authenticated: return HttpResponseRedirect(reverse(settings.ADMIN_HOME_VIEW)) try: location = Location.objects.get(code=loc_code) except Location.DoesNotExist: return HttpResponseRedirect(reverse("location_editor.views.main")) if request.method == "GET": # We're displaying this form for the first time -> set up our default # values. name = "" err_msg = None elif request.method == "POST": # The user is submitting this form. See what the user wants to do. if request.POST.get("cancel") != None: # The user clicked on the "Cancel" button -> redirect the user back # to the main tableau page for this location. return HttpResponseRedirect( reverse("tableau_editor.views.select", args=[location.code])) # If we get here, the user is attempting to add a new tableau. Check # that the entered name is valid. name = request.POST.get("name") err_msg = None # initially. if Tableau.objects.filter(location=location, name=name).exists(): err_msg = "Sorry, there is already a tableau with that name " \ + "for this location." if err_msg == None: # The entered name is valid -> add the tableau. tableau = Tableau() tableau.location = location tableau.name = name tableau.meta_data = "{}" tableau.save() # Return the user back to the main list of tableaux for this # location. return HttpResponseRedirect( reverse("tableau_editor.views.select", args=[location.code])) # Finally, display our page. menu_html = menus.generate(request, "Tableau Editor", "tableau_editor", "add_tableau") return render_to_response("tableau_editor/templates/add_tableau.html", {'menu_html' : menu_html, 'heading' : "Add Tableau for "+str(location), 'name' : name, 'err_msg' : err_msg, }, context_instance=RequestContext(request))
def create_tableau(factory, location): """ Create a single tableau for a given location using a given factory. This function does the actual work of generating an individual tableau based upon the factory definition. It can be called directly to generate a desired tableau, or it can be called indirectly by the daemon (using the private 'create_tableau' API call) to generate tableaux en masse. Upon completion, we return None if the tableau-generation attempt was successful. Otherwise, we return a suitable error message explaining why the tableau could not be generated. """ # Get the location's outline. try: outline = Outline.objects.get(location=location) except Outline.DoesNotExist: # We can't create a tableau for a location without an outline -> # tell the user the bad news. return "Location has no outline." # Delete the existing tableau with this name, if any. Tableau.objects.filter(location=location, name=factory.tableau_name).delete() # Create the new Tableau for this location. tableau = Tableau() tableau.location = location tableau.name = factory.tableau_name tableau.meta_data = factory.tableau_meta_data tableau.bounds_render = factory.tableau_bounds_render tableau.save() # Create a single view for the tableau, covering the location's entire # extent. min_long,min_lat,max_long,max_lat = outline.outline.extent # Add a margin around the edges so that the location is easier to see. width = abs(max_long - min_long) height = abs(max_lat - min_lat) buffer = 0.02 * (width + height) / 2 min_long = min_long - buffer max_long = max_long + buffer min_lat = min_lat - buffer max_lat = max_lat + buffer # Ensure the calculated view bounds are allowable. if min_lat < MIN_ALLOWED_LATITUDE: min_lat = MIN_ALLOWED_LATITUDE elif min_lat > MAX_ALLOWED_LATITUDE: min_lat = MAX_ALLOWED_LATITUDE if max_lat < MIN_ALLOWED_LATITUDE: max_lat = MIN_ALLOWED_LATITUDE elif max_lat > MAX_ALLOWED_LATITUDE: max_lat = MAX_ALLOWED_LATITUDE if min_long < MIN_ALLOWED_LONGITUDE: min_long = MIN_ALLOWED_LONGITUDE elif min_long > MAX_ALLOWED_LONGITUDE: min_long = MAX_ALLOWED_LONGITUDE if max_long < MIN_ALLOWED_LONGITUDE: max_long = MIN_ALLOWED_LONGITUDE elif max_long > MAX_ALLOWED_LONGITUDE: max_long = MAX_ALLOWED_LONGITUDE # Create the view. view = TableauView() view.tableau = tableau view.ordinal_rank = 1 view.name = location.display_name view.min_lat = "%0.4f" % min_lat view.max_lat = "%0.4f" % max_lat view.min_long = "%0.4f" % min_long view.max_long = "%0.4f" % max_long view.meta_data = factory.view_meta_data view.bounds_render = factory.view_bounds_render view.save() # Add the factory's filter(s) to the tableau's view. for factory_filter in factory.tableaufactoryviewfilter_set.all(): filter = TableauViewFilter() filter.tableauView = view filter.type = factory_filter.filter_type filter.value = factory_filter.filter_value filter.meta_data = factory_filter.filter_meta_data filter.draw_bubbles = factory_filter.filter_draw_bubbles filter.polygon_render = factory_filter.filter_polygon_render filter.bubble_render = factory_filter.filter_bubble_render filter.save() # Calculate the aspect ratio for the tableau's view. proj = GlobalMercator() min_x,min_y = proj.LatLonToMeters(min_lat, min_long) max_x,max_y = proj.LatLonToMeters(max_lat, max_long) viewWidth = max_x - min_x viewHeight = max_y - min_y if viewWidth == 0: viewWidth = 1.0 if viewHeight == 0: viewHeight = 1.0 aspectRatio = viewWidth / viewHeight # Create a single layout for the tableau. The size of the layout is # based on the view's aspect ratio. layout_width = LAYOUT_MAX_WIDTH layout_height = layout_width / aspectRatio if layout_height > LAYOUT_MAX_HEIGHT: layout_height = LAYOUT_MAX_HEIGHT layout_width = layout_height * aspectRatio layout = TableauLayout() layout.tableau = tableau layout.width = layout_width layout.height = layout_height layout.save() # Create a single TableauLayoutViewPosition record, positioning the view # within the layout. position = TableauLayoutViewPosition() position.tableauLayout = layout position.tableauView = view position.min_x = 0 position.min_y = 0 position.max_x = layout_width position.max_y = layout_height position.save() # Finally, tell the caller that the tableau was successfully generated. return None