def main(request): """ Respond to the "/" URL. This is the main entry point for the sanity_checker application. We search for "suspicious" locations, and list them as possible problems that need fixing. Note that, for speed, we bypass the ORM and access the MySQL database directly. """ if not request.user.is_authenticated: return HttpResponseRedirect(reverse(settings.ADMIN_HOME_VIEW)) if request.method == "GET": # We're displaying the page for the first time. pass elif request.method == "POST": # See if the user clicked on our "Proceed" button. if request.POST.get("proceed") != None: return HttpResponseRedirect( reverse("sanity_checker.views.check")) # Finally, display the page to the user. menu_html = menus.generate(request, "Location Sanity-Checker", "sanity_checker", "main") return render_to_response("sanity_checker/templates/sanity_check.html", {'menu_html' : menu_html}, context_instance=RequestContext(request))
def busy(request): """ Display the main page when our tableau-calculating daemon is busy. We display the status of the daemon, and reload the page on a regular basis so the user can see the status as it changes. """ num_to_go = TableauCacheRequest.objects.count() if num_to_go == 0: # Redirect the user back to the "idle" page. return HttpResponseRedirect(reverse("tableau_cache.views.idle")) if request.method == "POST": # See if the user clicked on our "Cancel" button. if request.POST.get("cancel") == "Cancel": # Delete the remaining requests, and return to the "idle" view. TableauCacheRequest.objects.all().delete() return HttpResponseRedirect(reverse("tableau_cache.views.idle")) # Finally, display our page to the user. menu_html = menus.generate(request, "Tableau Cache", "tableau_cache", "main") return render_to_response("tableau_cache/templates/main_busy.html", {'num_to_go' : num_to_go, 'menu_html' : menu_html, }, context_instance=RequestContext(request))
def main(request): """ Respond to the "/" URL. This is the main entry point for the tableau_editor application. We let the user select a location to edit the tableaux for. """ if not request.user.is_authenticated: return HttpResponseRedirect(reverse(settings.ADMIN_HOME_VIEW)) levels = [] for level in Level.objects.all(): levels.append(level) starred_locs = [] for loc in Location.objects.filter(starred=True): starred_locs.append(loc) menu_html = menus.generate(request, "Tableau Editor", "tableau_editor", "main") base_url = reverse("tableau_editor.views.select", args=["Z"])[:-2] selector_html = location_selector.generate( request, "Edit the tableaux for a location", "Tableau Editor", "tableau_editor", "main", base_url ) return render_to_response( "tableau_editor/templates/main.html", {"menu_html": menu_html, "selector_html": selector_html, "starred_locs": starred_locs, "levels": levels}, context_instance=RequestContext(request), )
def create_tableaux_for_location(request, loc_code): """ Create the factory-based tableaux for the given location. """ if not request.user.is_authenticated: return HttpResponseRedirect(reverse(settings.ADMIN_HOME_VIEW)) if request.method == "GET": # Ask the user to confirm the operation. return render_to_response("shared/templates/confirm.html", {'title' : "Whenua Admin", 'heading' : "Create Factory Tableaux", 'message' : "Are you sure you want to " + "create a new set of factory " + "tableaux for this location?" + " If you proceed, the " + "existing factory tableaux " + "will be overwritten.", }, context_instance=RequestContext(request)) elif request.POST['confirm'] != "1": # The user cancelled -> go back to the main tableau editor page. return HttpResponseRedirect(reverse("tableau_editor.views.select", args=[loc_code])) # If we get here, we're ready to create the factory tableau for this # location. Load the location object into memory. try: location = Location.objects.get(code=loc_code) except Location.DoesNotExist: # Should never happen. return HttpResponseRedirect(reverse("tableau_editor.views.select", args=[loc_code])) # Build a list of tableau factories we need to run. factories = factory_generator.calc_factories_for_location(location) # Create each tableau in turn, keeping track of any errors which occur # along the way. results = [] for factory in factories: err_msg = factory_generator.create_tableau(factory, location) results.append({'factory' : factory, 'location' : location, 'err_msg' : err_msg}) # Finally, display the results to the caller. menu_html = menus.generate(request, "Tableau Editor", "tableau_editor", "create_factory") return render_to_response("tableau_editor/templates/" + "create_factory_results.html", {'menu_html' : menu_html, 'results' : results, 'loc_code' : loc_code, }, context_instance=RequestContext(request))
def create_all_busy(request): """ Respond to the "/create_all_busy" URL. We display the status of the generation request, along with any errors which may have occurred. """ num_to_go = TableauFactoryGenerationRequest.objects.count() if num_to_go == 0: # Redirect the user back to the "idle" page. return HttpResponseRedirect(reverse( "tableau_editor.views.create_factory.create_all_idle")) if request.method == "POST": # See if the user clicked on our "Cancel" button. if request.POST.get("cancel") == "Cancel": # Delete the remaining requests, and return to the "idle" view. TableauFactoryGenerationRequest.objects.all().delete() return HttpResponseRedirect(reverse( "tableau_editor.views.create_factory.create_all_idle")) # See if the user clicked on our "Finished" button. if request.POST.get("finished") != None: return HttpResponseRedirect( reverse("tableau_editor.views.tableau_factories.main")) # Finally, display our page to the user. menu_html = menus.generate(request, "Tableau Editor", "tableau_editor", "create_all_tableaux") errors = [] for error in TableauFactoryGenerationError.objects.all(): try: factory = TableauFactory.objects.get(id=error.factory_id) except TableauFactory.DoesNotExist: continue # Should never happen. try: location = Location.objects.get(code=error.loc_code) except Location.DoesNotExist: continue # Should never happen. errors.append({'factory' : factory, 'location' : location, 'err_msg' : error.err_msg}) return render_to_response("tableau_editor/templates/create_all_busy.html", {'num_to_go' : num_to_go, 'menu_html' : menu_html, 'errors' : errors, }, context_instance=RequestContext(request))
def import_locations(request): """ Respond to the "import" URL. We let the user import location data from a tab-delimited text file. """ if not request.user.is_authenticated: return HttpResponseRedirect(reverse(settings.ADMIN_HOME_VIEW)) if request.method == "GET": # We're displaying the form for the first time -> set up our default # values. log = [] elif request.method == "POST": # The user is submitting our form -> see what the user wants to do. if request.POST.get("finished") != None: # The user clicked on the "Finished" button -> redirect the user # back to the main admin page. return HttpResponseRedirect(reverse(settings.ADMIN_HOME_VIEW)) log = [] # Log of import results. # Extract the uploaded file, and save it to a temporary file on disk. if 'upload' not in request.FILES: log.append("Please select a file to import!") else: upload_file = request.FILES['upload'] f = TemporaryFile() for chunk in upload_file.chunks(): chunk = chunk.replace("\r\n", "\n") # Fix weird line endings. chunk = chunk.replace("\n\r", "\n") # ditto. chunk = chunk.replace("\r", "\n") # ditto. f.write(chunk) upload_file.close() f.seek(0) # Import the locations from the temporary file. import_data(f, log) menu_html = menus.generate(request, "Location Editor", "import_export", "import_locations") return render_to_response("import_export/templates/import.html", {'menu_html' : menu_html, 'log' : log}, context_instance=RequestContext(request))
def main(request): """ Respond to a "/" request. This is our top-most view. """ is_daemon_running = daemonMonitor.is_daemon_running() menu_html = menus.generate(request, "Admin Home", "admin_interface", "main") return render_to_response("admin_interface/templates/main.html", {'is_daemon_running' : is_daemon_running, 'menu_html' : menu_html}, context_instance=RequestContext(request))
def main(request): """ Implement the "/" URL. This is the main entry point for the location_editor application. We let the user select a location to edit, either by typing in the desired location name or code, or by selecting the location level to start browsing. """ if not request.user.is_authenticated: return HttpResponseRedirect(reverse(settings.ADMIN_HOME_VIEW)) levels = [] for level in Level.objects.all(): levels.append(level) starred_locs = [] for loc in Location.objects.filter(starred=True): starred_locs.append(loc) has_import_export = ("import_export" in settings.INSTALLED_APPS) menu_html = menus.generate(request, "Location Editor", "location_editor", "main") base_url = reverse("location_editor.views.details", args=["Z"])[:-2] selector_html = location_selector.generate(request, "Select a location to edit", "Location Editor", "location_editor", "main", base_url) return render_to_response("location_editor/templates/main.html", {'menu_html' : menu_html, 'selector_html' : selector_html, 'starred_locs' : starred_locs, 'levels' : levels, 'has_import_export' : has_import_export}, context_instance=RequestContext(request))
def login(request): """ Respond to a "/login" URL. We let the user log in. """ if request.method == "GET": # We're displaying the form for the first time. err_msg = None elif request.method == "POST": # Respond to the user submitting our form. if request.POST.get("cancel") == "Cancel": return HttpResponseRedirect(reverse(settings.ADMIN_HOME_VIEW)) err_msg = None # initially. username = request.POST['username'] password = request.POST['password'] user = auth.authenticate(username=request.POST['username'], password=request.POST['password']) if user == None: err_msg = "Incorrect username or password." if err_msg == None: auth.login(request, user) return HttpResponseRedirect(reverse(settings.ADMIN_HOME_VIEW)) # Display the page to the user. menu_html = menus.generate(request, "User Login", "admin_interface", "login") return render_to_response("admin_interface/templates/login.html", {'menu_html' : menu_html, 'err_msg' : err_msg}, context_instance=RequestContext(request))
def main(request): """Respond to the "/" URL. This is the main entry point for the polygon_editor application. We display a menu of available options within the polygon builder. """ if not request.user.is_authenticated: return HttpResponseRedirect(reverse(settings.ADMIN_HOME_VIEW)) options = [] # List of (label, url) tuples. options.append(("Polygon Builder", reverse("polygon_editor.views.builder.main"))) options.append(("Polygon Validator", reverse("polygon_editor.views.validator"))) menu_html = menus.generate(request, "Polygon Editor", "polygon_editor", "main") return render_to_response("polygon_editor/templates/main.html", {'menu_html' : menu_html, 'options' : options}, context_instance=RequestContext(request))
def names(request, loc_code): """ Respond to the "/names/XYZ/" URL. We let the user edit the names for 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(settings.ADMIN_HOME_VIEW)) loc_names = [] for loc_name in LocationName.objects.filter(location=location): loc_names.append(loc_name) imports = [] imports.append('<link href="' + settings.MEDIA_URL + 'editor.css" ' + 'rel="stylesheet" type="text/css">') if request.method == "GET": # We're displaying the form for the first time. Process our CGI # parameters (if any). confirm = request.GET.get("confirm") elif request.method == "POST": # Respond to the user clicking on one of our buttons. # Did the user click on the "Finished" button? if request.POST.get("finished") == "Finished": return HttpResponseRedirect( reverse("location_editor.views.main")) # Did the user click on one of our "Edit" buttons? We redirect the # user to the "Edit" page for the associated location name. for loc_name in loc_names: editValue = request.POST.get("edit-" + str(loc_name.id)) if editValue == "Edit": return HttpResponseRedirect( reverse("location_editor.views.edit_name", args=[loc_name.id])) # Did the user click on one of our "Delete" buttons? We firstly # display the confirmation button beside the entry, and only delete the # entry if the user confirms. for loc_name in loc_names: deleteValue = request.POST.get("del-" + str(loc_name.id)) if deleteValue == "Delete": # The user clicked on the "Delete" button for the first time -> # redisplay the page with the confirmation buttons. return HttpResponseRedirect( reverse("location_editor.views.names", args=[loc_code]) + "?confirm=" + str(loc_name.id)) elif deleteValue == "Yes": # The user clicked on our "Yes" confirmation button. Remove # this location name entry. If this is the last occurrence of # this name, remove the name as well. name = loc_name.name loc_name.delete() if name.locationname_set.count() == 0: name.delete() # Redisplay the updated page without the confirmation buttons. return HttpResponseRedirect( reverse("location_editor.views.names", args=[loc_code])) elif deleteValue == "No": # The user clicked on the "No" confirmation button. Redisplay # the page without the confirmation buttons. return HttpResponseRedirect( reverse("location_editor.views.names", args=[loc_code])) # Did the user click on the "Add" button? if request.POST.get("add") == "Add Name": return HttpResponseRedirect( reverse("location_editor.views.add_name", args=[loc_code])) # If we get here, we're going to display the form again. Grab our # "confirm" parameter so the form can display the appropriate # confirmation buttons. confirm = request.POST.get("confirm") # If we get here, display the list of names for this location. menu_html = menus.generate(request, "Location Editor", "location_editor", "names") return render_to_response("location_editor/templates/wrapper.html", {'menu_html' : menu_html, 'tab' : "names", 'heading' : "Editing " + str(location), 'location' : location, 'template_name' : "names.html", 'extra_head_tags' : imports, 'errMsg' : None, 'form' : None, 'confirm' : confirm, 'loc_names' : loc_names, }, context_instance=RequestContext(request))
def add(request, level=None): """ Respond to the "/add" URL. If a level was supplied, we let the user add the location with that level. Otherwise, we let the user choose which level of location to add. """ if not request.user.is_authenticated: return HttpResponseRedirect(reverse(settings.ADMIN_HOME_VIEW)) if level == None: # The user hasn't chosen a level yet. Display the "Choose a Level" # page. levels = [] for level in Level.objects.all(): levels.append(level) menu_html = menus.generate(request, "Location Editor", "location_editor", "add") return render_to_response("location_editor/templates/" + "add_select_level.html", {'menu_html' : menu_html, 'levels' : levels, }, context_instance=RequestContext(request)) # If we get here, we know what level of location to add. Display the # "Add Location" form. try: level = Level.objects.get(level=level) except Level.DoesNotExist: return HttpResponseRedirect(reverse("location_editor.views.main")) if request.method == "GET": form = LocationDetailsForm() errMsg = None elif request.method == "POST": if request.POST.get("cancel") == "Cancel": return HttpResponseRedirect(reverse("location_editor.views.main")) form = LocationDetailsForm(request.POST) errMsg = None if form.is_valid(): code = request.POST['code'] name = request.POST['name'] display_name = request.POST['display_name'] abbreviation = request.POST['abbreviation'] display_lat = request.POST['display_point_lat'] display_long = request.POST['display_point_long'] if code == "": errMsg = "You must enter a code for this location." elif name == "": errMsg = "You must enter a name for this location." elif Location.objects.filter(code=code).count() > 0: errMsg = "There is already a location with that code." elif Location.objects.filter(level=level, name=name).count() > 0: errMsg = "There is already a " + level.name.lower() \ + " with that name." if errMsg == None: location = Location() location.level = level location.code = code location.name = name location.display_name = display_name location.abbreviation = abbreviation location.min_zoom_lat = decimal.Decimal("0.00") location.min_zoom_long = decimal.Decimal("0.00") location.max_zoom_lat = decimal.Decimal("0.00") location.max_zoom_long = decimal.Decimal("0.00") if display_lat != "": location.display_lat = decimal.Decimal(display_lat) if display_long != "": location.display_long = decimal.Decimal(display_long) location.population = 0 location.area = 0 location.averageIncome = 0 location.save() # Finally, redirect the user to the "details" page for the # newly-added location. return HttpResponseRedirect( reverse("location_editor.views.details", args=[location.code])) return render_to_response("shared/templates/editForm.html", {'title' : "Whenua Admin", 'heading' : "Add " + level.name, 'errMsg' : errMsg, 'form' : form}, context_instance=RequestContext(request))
def add_layout(request, tableau_id): """ Respond to the /add_layout/NNN/" URL. We let the user add a new layout to the given tableau. """ if not request.user.is_authenticated: return HttpResponseRedirect(reverse(settings.ADMIN_HOME_VIEW)) try: tableau = Tableau.objects.get(id=tableau_id) except Tableau.DoesNotExist: return HttpResponseRedirect(reverse(settings.ADMIN_HOME_VIEW)) if request.method == "GET": # We're displaying this form for the first time -> set up our default # values. width = 0 height = 0 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 "Edit" page for this tableau. return HttpResponseRedirect( reverse("tableau_editor.views.edit_tableau", args=[tableau.id])) # If we get here, the user is attempting to add a new layout. Check # that the entered size is valid. err_msg = None # initially. try: width = int(request.POST.get("width")) except: err_msg = "You must enter a valid width, in pixels." if err_msg == None: try: height = int(request.POST.get("height")) except: err_msg = "You must enter a valid height, in pixels." if err_msg == None: if width < 10 or width > 2000: err_msg = "The width must be between 10 and 2000 pixels." if err_msg == None: if height < 10 or height > 2000: err_msg = "The height must be between 10 and 2000 pixels." if err_msg == None: if TableauLayout.objects.filter(tableau=tableau, width=width, height=height).exists(): err_msg = "There is already a tableau with that size." # If everything is okay, add the new layout. if err_msg == None: layout = TableauLayout() layout.tableau = tableau layout.width = width layout.height = height layout.save() # Return the user back to the "Edit Tableau" page. return HttpResponseRedirect( reverse("tableau_editor.views.edit_tableau", args=[tableau.id])) # Finally, display our page. menu_html = menus.generate(request, "Tableau Editor", "tableau_editor", "add_layout") return render_to_response("tableau_editor/templates/add_layout.html", {'menu_html' : menu_html, 'heading' : "Add Layout for Tableau '" + tableau.name + '"', 'width' : width, 'height' : height, 'err_msg' : err_msg, }, context_instance=RequestContext(request))
def edit_layout(request, layout_id): """ Respond to the "/edit_layout/NNN/" URL. We let the user edit the given tableau layout. """ if not request.user.is_authenticated: return HttpResponseRedirect(reverse(settings.ADMIN_HOME_VIEW)) try: layout = TableauLayout.objects.get(id=layout_id) except TableauLayout.DoesNotExist: return HttpResponseRedirect( reverse("tableau_editor.views.main")) tableau = layout.tableau # Load the list of TableauLayoutViewPosition records for this layout into # memory, adding new records if they don't already exist. positions = [] anchorX = 10 anchorY = 10 views = TableauView.objects.filter(tableau=tableau) for view in views.order_by("-ordinal_rank"): try: position = TableauLayoutViewPosition.objects.get( tableauLayout=layout, tableauView=view) except TableauLayoutViewPosition.DoesNotExist: # Create a new view position record for this view. Note that we # have to set the view's rectangle up to have the aspect ratio of # the original view bounds, or else the view will be distorted when # it is displayed. proj = GlobalMercator() min_lat = float(view.min_lat) min_long = float(view.min_long) max_lat = float(view.max_lat) max_long = float(view.max_long) 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 boxWidth = 40 boxHeight = boxWidth / aspectRatio position = TableauLayoutViewPosition() position.tableauLayout = layout position.tableauView = view position.min_x = anchorX position.min_y = anchorY position.max_x = anchorX + boxWidth position.max_y = anchorY + boxHeight position.save() anchorX = anchorX + 20 if anchorX > layout.width - 10: anchorX = 10 anchorY = anchorY + 20 if anchorY > layout.height - 10: anchorY = 10 positions.append(position) # See what the user wants to do. if request.method == "POST": if request.POST.get("update_size") != None: # The user clicked on the "Update" button to change the layout size # -> update the size of the layout. new_width = request.POST.get("width") if new_width != None: try: layout.width = int(new_width) except ValueError: pass new_height = request.POST.get("height") if new_height != None: try: layout.height = int(new_height) except ValueError: pass layout.save() return HttpResponseRedirect( reverse("tableau_editor.views.edit_layout", args=[layout.id])) if request.POST.get("fit_contents") != None: # The user clicked on the "Resize Layout to Fit Contents" button. # Calculate the new size for the layout. new_width = 10 new_height = 10 for position in positions: max_x = request.POST.get("view_"+str(position.id)+"_max_x") max_y = request.POST.get("view_"+str(position.id)+"_max_y") if max_x != None and max_y != None: max_x = int(max_x) max_y = int(max_y) if max_x > new_width: new_width = max_x if max_y > new_height: new_height = max_y layout.width = new_width layout.height = new_height layout.save() return HttpResponseRedirect( reverse("tableau_editor.views.edit_layout", args=[layout.id])) if request.POST.get("save") != None: # The user clicked on the "Save" button -> save the updated layout. for position in positions: min_x = request.POST.get("view_"+str(position.id)+"_min_x") max_x = request.POST.get("view_"+str(position.id)+"_max_x") min_y = request.POST.get("view_"+str(position.id)+"_min_y") max_y = request.POST.get("view_"+str(position.id)+"_max_y") if (min_x != None and min_y != None and max_x != None and max_y != None): position.min_x = int(min_x) position.min_y = int(min_y) position.max_x = int(max_x) position.max_y = int(max_y) position.save() return HttpResponseRedirect( reverse("tableau_editor.views.edit_tableau", args=[tableau.id])) if request.POST.get("cancel") != None: # The user clicked on the "Cancel" button -> return to the main # "Edit Tableau" page. return HttpResponseRedirect( reverse("tableau_editor.views.edit_tableau", args=[tableau.id])) # If we get here, we're displaying the form for the first time. Do so. menu_html = menus.generate(request, "Tableau Editor", "tableau_editor", "edit_layout") return render_to_response("tableau_editor/templates/edit_layout.html", {'menu_html' : menu_html, 'heading' : "Edit Layout for Tableau '" + tableau.name + "'", 'width' : layout.width, 'height' : layout.height, 'positions' : positions, }, context_instance=RequestContext(request))
def main(request): """ Implement the "/" URL. This is the main entry point for the geolocator_api_test application. """ if not request.user.is_authenticated: return HttpResponseRedirect(reverse(settings.ADMIN_HOME_VIEW)) if request.method == "GET": # We're displaying the page for the first time -> set up our default # values. req_type = "unstructured" req_text = "" req_country = "" req_state = "" req_metro = "" req_region = "" req_county = "" req_city = "" req_locality = "" req_zipCode = "" req_latitude = "" req_longitude = "" req_source = "" results = [] log = [] elif request.method == "POST": # Respond to the user submitting our form. # Extract the submitted request. req_type = request.POST['req_type'] req_text = request.POST['req_text'] req_country = request.POST['req_country'] req_state = request.POST['req_state'] req_metro = request.POST['req_metro'] req_region = request.POST['req_region'] req_county = request.POST['req_county'] req_city = request.POST['req_city'] req_locality = request.POST['req_locality'] req_zipCode = request.POST['req_zipCode'] req_latitude = request.POST['req_latitude'] req_longitude = request.POST['req_longitude'] req_source = request.POST['req_source'] # Build the request to send to the Geolocator API. params = {} if req_type == "unstructured": params['text'] = req_text elif req_type == "structured": if req_country != "": params['country'] = req_country if req_state != "": params['state'] = req_state if req_metro != "": params['metro'] = req_metro if req_region != "": params['region'] = req_region if req_county != "": params['county'] = req_county if req_city != "": params['city'] = req_city if req_locality != "": params['locality'] = req_locality if req_zipCode != "": params['zipCode'] = req_zipCode elif req_type == "coordinate": params['lat'] = req_latitude params['long'] = req_longitude if req_source != "": params['source'] = req_source params['verbose'] = "1" # Send off the request to the Geolocator API. code,response = geolocator.geolocate(params) if code != 200: # OK. log = [response] results = [] else: if "locations" not in response: results = [] log = [repr(response)] else: results = [] log = [] for key,value in sorted(response['locations'][0].items()): if key == "log": log = value else: if isinstance(value, dict): parts = [] for field in sorted(value.keys()): parts.append(field + "=" + str(value[field])) value = ", ".join(parts) results.append((key, value)) for i in range(len(log)): log[i] = log[i].replace(" ", " ") # If we get here, display our form with the supplied parameters. menu_html = menus.generate(request, "Gelocator API Test", "geolocator_api_test", "main") return render_to_response("geolocator_api_test/templates/testgeo.html", {'menu_html' : menu_html, 'req_type' : req_type, 'req_text' : req_text, 'req_country' : req_country, 'req_state' : req_state, 'req_metro' : req_metro, 'req_region' : req_region, 'req_county' : req_county, 'req_city' : req_city, 'req_locality' : req_locality, 'req_zipCode' : req_zipCode, 'req_latitude' : req_latitude, 'req_longitude' : req_longitude, 'req_source' : req_source, 'results' : results, 'log' : log, }, context_instance=RequestContext(request))
def main(request): """ Respond to a "/" request. This is the top-most view for the user_editor application. """ if not request.user.is_superuser: return HttpResponseRedirect(reverse(settings.ADMIN_HOME_VIEW)) users = [] for user in User.objects.all(): if not user.is_superuser: users.append(user) if request.method == "GET": # We're displaying the page for the first time. Process our CGI # parameters (if any). confirm = request.GET.get("confirm") elif request.method == "POST": # Respond to the user clicking on one of our buttons. # Did the user click on one of our "Edit" buttons? We redirect the # user to the "Edit" page for the associated user. for user in users: editValue = request.POST.get("edit-" + user.username) if editValue == "Edit": return HttpResponseRedirect(reverse("user_editor.views.edit", args=[source.code])) # Did the user click on one of our "Delete" buttons? We firstly # display the confirmation button beside the entry, and only delete the # entry if the user confirms. for user in users: deleteValue = request.POST.get("del-" + user.username) if deleteValue == "Delete": # The user clicked on the "Delete" button for the first time -> # redisplay the page with the confirmation buttons. return HttpResponseRedirect(reverse("user_editor.views.main") + "?confirm="+user.username) elif deleteValue == "Yes": # The user clicked on our "Yes" confirmation button. Delete # this user. user.delete() return HttpResponseRedirect(reverse("user_editor.views.main")) elif deleteValue == "No": # The user clicked on the "No" confirmation button. Redisplay # the page without the confirmation buttons. return HttpResponseRedirect(reverse("user_editor.views.main")) # Did the user click on the "Add" button? if request.POST.get("add") == "Add User": return HttpResponseRedirect(reverse("user_editor.views.add")) # If we get here, we're going to display the page again. Grab our # "confirm" CGI parameter so the page can display the appropriate # confirmation buttons. confirm = request.POST.get("confirm") # If we get here, display the list of data sources. menu_html = menus.generate(request, "User Editor", "user_editor", "main") return render_to_response("user_editor/templates/select_user.html", {'menu_html' : menu_html, 'users' : users, 'confirm' : confirm, }, context_instance=RequestContext(request))
def add_view(request, tableau_id): """ Respond to the "/add_view/NNN/" URL. We let the user add a new view to the given tableau. """ if not request.user.is_authenticated: return HttpResponseRedirect(reverse(settings.ADMIN_HOME_VIEW)) try: tableau = Tableau.objects.get(id=tableau_id) except Tableau.DoesNotExist: return HttpResponseRedirect(reverse("location_editor.views.main")) # See what the user wants to do. 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 "Edit Tableau" page for this tableau. return HttpResponseRedirect( reverse("tableau_editor.views.edit_tableau", args=[tableau.id])) # If we get here, the user is attempting to add a new view. Check that # the entered name is valid. name = request.POST.get("name") err_msg = None # initially. if name == "": err_msg = "Please enter a name for this view." if TableauView.objects.filter(tableau=tableau, name=name).exists(): err_msg = "Sorry, there is already a view with that name " \ + "for this tableau." if err_msg == None: # The entered name is valid -> add the view. query = TableauView.objects.filter(tableau=tableau) rank = query.aggregate(Max("ordinal_rank"))['ordinal_rank__max'] if rank == None: rank = 1 else: rank = rank + 1 view = TableauView() view.tableau = tableau view.name = name view.ordinal_rank = rank view.min_lat = 0 view.max_lat = 0 view.min_long = 0 view.max_long = 0 view.save() # Return the user back to the main "Edit Tableau" page for this # tableau. return HttpResponseRedirect( reverse("tableau_editor.views.edit_tableau", args=[tableau.id])) # Finally, display our page. menu_html = menus.generate(request, "Tableau Editor", "tableau_editor", "add_view") return render_to_response("tableau_editor/templates/add_view.html", {'menu_html' : menu_html, 'heading' : "Add View for Tableau '" + tableau.name + "'", 'name' : name, 'err_msg' : err_msg, }, context_instance=RequestContext(request))
def parents(request, loc_code): """ Respond to the "/geo/editor/location/parents/XYZ/" URL. We let the user edit the list of parents for 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(settings.ADMIN_HOME_VIEW)) parents = [] for parent in location.parents.all(): parents.append(parent) if request.method == "GET": # We're visiting the page for the first time -> just display it. form = AddLocationForm() errMsg = None confirm = request.GET.get("confirm") elif request.method == "POST": # The user is submitting our form. See what the user wants to do. # Did the user click on the "Finished" button? if request.POST.get("finished") == "Finished": return HttpResponseRedirect( reverse("location_editor.views.main")) # Did the user click on one of our "Delete" buttons? We firstly # display the confirmation button beside the entry, and only delete the # entry if the user confirms. for parent in location.parents.all(): deleteValue = request.POST.get("del-" + parent.code) if deleteValue == "Delete": # The user clicked on the "Delete" button for the first time -> # redisplay the page with the confirmation buttons. return HttpResponseRedirect( reverse("location_editor.views.parents", args=[loc_code]) + "?confirm=" + parent.code) elif deleteValue == "Yes": # The user clicked on our "Yes" confirmation button. Delete # this parent. location.parents.remove(parent) location.save() # Finally, tell the user's web browser to reload the page. return HttpResponseRedirect( reverse("location_editor.views.parents", args=[loc_code])) elif deleteValue == "No": # The user clicked on the "No" confirmation button. Redisplay # the page without the confirmation buttons. return HttpResponseRedirect( reverse("location_editor.views.parents", args=[loc_code])) # Did the user click on the "Add" button? if request.POST.get("add") == "Add": # Respond to the user adding a new parent. form = AddLocationForm(request.POST) errMsg = None if form.is_valid(): new_parent_id = form.cleaned_data['loc_id'] if new_parent_id == None: errMsg = "Please enter a location" if errMsg == None: try: newParent = Location.objects.get(id=new_parent_id) except Location.DoesNotExist: errMsg = "No such location." if errMsg == None: filter = location.parents.filter(id=new_parent_id) if filter.count() > 0: errMsg = "That location is already listed as " \ + "a parent!" if errMsg == None: location.parents.add(newParent) location.save() # Finally, tell the user's web browser to reload the # page. return HttpResponseRedirect( reverse("location_editor.views.parents", args=[loc_code])) # If we get here, we're going to display the form again. Grab our # "confirm" parameter so the form can display the appropriate # confirmation buttons. confirm = request.POST.get("confirm") # If we get here, display the form to the user. imports = ['<script type="text/javascript" ' + 'src="'+settings.MEDIA_URL+'jquery-1.2.6.min.js">' + '</script>', '<script type="text/javascript" ' + 'src="'+settings.MEDIA_URL+'jquery.autocomplete.js">' + '</script>', '<link href="'+settings.MEDIA_URL+'jquery.autocomplete.css" ' + 'rel="stylesheet" type="text/css">', '<link href="'+settings.MEDIA_URL+'editor.css" rel="stylesheet" ' + 'type="text/css">', ] lookup_url = reverse("admin_interface.views.lookup.location") menu_html = menus.generate(request, "Location Editor", "location_editor", "parents") return render_to_response("location_editor/templates/wrapper.html", {'menu_html' : menu_html, 'tab' : "parents", 'heading' : "Editing " + str(location), 'location' : location, 'template_name' : "parents.html", 'errMsg' : errMsg, 'form' : form, 'parents' : parents, 'confirm' : confirm, 'extra_head_tags' : imports, 'lookup_url' : lookup_url, }, context_instance=RequestContext(request))
def select(request, loc_code): """ Respond to the "select/XYZ/" URL. We let the user view the list of tableaux for 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("tableau_editor.views.main") tableaux = [] for tableau in Tableau.objects.filter(location=location): tableaux.append(tableau) err_msg = None # initially. if request.method == "GET": # We're displaying the form for the first time. Process our CGI # parameters (if any). confirm = request.GET.get("confirm") elif request.method == "POST": # Respond to the user clicking on one of our buttons. # Did the user click on the "Finished" button? if request.POST.get("finished") != None: return HttpResponseRedirect(reverse("tableau_editor.views.main")) # Did the user click on the "Add Tableau" button? if request.POST.get("add") != None: return HttpResponseRedirect( reverse("tableau_editor.views.add_tableau", args=[loc_code])) # Did the user click on the "Create Factory Tableaux" button? if request.POST.get("create_factory") != None: return HttpResponseRedirect( reverse("tableau_editor.views.create_factory." + "create_tableaux_for_location", args=[loc_code])) # Did the user click on one of our "Edit" buttons? We redirect the # user to the "Edit" page for the associated tableau. for tableau in tableaux: editValue = request.POST.get("edit-" + str(tableau.id)) if editValue == "Edit": return HttpResponseRedirect( reverse("tableau_editor.views.edit_tableau", args=[tableau.id])) # Did the user click on one of our "Delete" buttons? We firstly # display the confirmation button beside the entry, and only delete the # entry if the user confirms. for tableau in tableaux: deleteValue = request.POST.get("del-" + str(tableau.id)) if deleteValue == "Delete": # The user clicked on the "Delete" button for the first time. # We allow the user to delete a tableau if it doesn't have a # name of "DEFAULT". if tableau.name.upper() == "DEFAULT": err_msg = "Sorry, you can't delete the default tableau." else: # redisplay the page with the confirmation buttons. return HttpResponseRedirect( reverse("tableau_editor.views.select", args=[loc_code]) + "?confirm=" + str(tableau.id)) elif deleteValue == "Yes": # The user clicked on our "Yes" confirmation button. Remove # this tableau. tableau.delete() # Redisplay the updated page without the confirmation buttons. return HttpResponseRedirect( reverse("tableau_editor.views.select", args=[loc_code])) elif deleteValue == "No": # The user clicked on the "No" confirmation button. Redisplay # the page without the confirmation buttons. return HttpResponseRedirect( reverse("tableau_editor.views.select", args=[loc_code])) # If we get here, we're going to display the form again. Grab our # "confirm" parameter so the form can display the appropriate # confirmation buttons. confirm = request.POST.get("confirm") # If we get here, display the list of names for this location. menu_html = menus.generate(request, "Tableau Editor", "tableau_editor", "select") return render_to_response("tableau_editor/templates/select.html", {'menu_html': menu_html, 'heading' : "Edit Tableau for "+str(location), 'errMsg' : err_msg, 'confirm' : confirm, 'tableaux' : tableaux, }, context_instance=RequestContext(request))
def edit(request, rec_id): """ Respond to the "/render_instructions/edit" URL. """ try: render = TableauRenderingInstructions.objects.get(id=rec_id) except TableauRenderingInstructions.DoesNotExit: raise Http404 if render.type == TableauRenderingInstructions.TYPE_TABLEAU: type = "tableau" elif render.type == TableauRenderingInstructions.TYPE_VIEW: type = "view" elif render.type == TableauRenderingInstructions.TYPE_LOCATION: type = "location" elif render.type == TableauRenderingInstructions.TYPE_BUBBLE: type = "bubble" else: type = None # See what the user wants to do, if anything. if request.method == "GET": # We're displaying the form for the first time -> nothing to do. err_msg = None elif request.method == "POST": err_msg = None # initially. # See if the user wants to save their changes. if request.POST.get("ok") != None: # Extract the entered values from our CGI parameters. render.name = request.POST.get("name") render.border_size = float(request.POST.get("border_size")) render.border_color = request.POST.get("border_color") render.border_opacity = float(request.POST.get("border_opacity")) render.fill_color = request.POST.get("fill_color") render.fill_opacity = float(request.POST.get("fill_opacity")) # Check that the entered name is valid. if render.name == "": err_msg = "You must enter a name." else: is_dup = False # initially. for aRender in TableauRenderingInstructions.objects.filter( name=render.name): if aRender.id != render.id: is_dup = True break if is_dup: err_msg = "That name is already in use." if err_msg == None: # Save the changed values, and redirect the user back to the # "list" view for this type of rendering instruction. render.save() return HttpResponseRedirect( reverse("tableau_editor.views.render_instructions.list", args=[type])) # See if the user clicked on the "Cancel" button. if request.POST.get("cancel") != None: # Go back to the "list" view for this type of rendering # instruction. return HttpResponseRedirect( reverse("tableau_editor.views.render_instructions.list", args=[type])) # If we get here, we're going to display the page. Do so. menu_html = menus.generate(request, "Tableau Editor", "tableau_editor", "render_instructions.edit") return render_to_response("tableau_editor/templates/render_edit.html", {'menu_html' : menu_html, 'type' : type, 'render' : render, 'preview_width' : 200, 'preview_height' : 100, 'err_msg' : err_msg}, context_instance=RequestContext(request))
def add_filter(request, view_id): """ Respond to the "/add_filter/NNN/" URL. We let the user add a new filter to the given tableau view. """ if not request.user.is_authenticated: return HttpResponseRedirect(reverse(settings.ADMIN_HOME_VIEW)) try: view = TableauView.objects.get(id=view_id) except TableauView.DoesNotExist: return HttpResponseRedirect(reverse("location_editor.views.main")) # See what the user wants to do. if request.method == "POST": # The user is submitting the 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 "Edit View" page for this view. return HttpResponseRedirect( reverse("tableau_editor.views.edit_view", args=[view.id])) # If we get here, the user wants to add a new view filter. type = request.POST.get("type") filter = TableauViewFilter() filter.tableauView = view if type == "cur_loc": filter.type = TableauViewFilter.TYPE_CUR_LOCATION filter.value = "" elif type == "level": filter.type = TableauViewFilter.TYPE_LEVEL filter.value = "" elif type == "location": filter.type = TableauViewFilter.TYPE_LOCATION filter.value = "" elif type == "parents": filter.type = TableauViewFilter.TYPE_RELATION filter.value = "parent" elif type == "children": filter.type = TableauViewFilter.TYPE_RELATION filter.value = "child" elif type == "neighbors": filter.type = TableauViewFilter.TYPE_RELATION filter.value = "neighbor" elif type == "peers": filter.type = TableauViewFilter.TYPE_RELATION filter.value = "peer" else: filter.type = TableauViewFilter.TYPE_LEVEL filter.value = "" filter.save() return HttpResponseRedirect( reverse("tableau_editor.views.edit_view", args=[view.id])) # If we get here, we're displaying the form for the first time -> do so. cur_loc = view.tableau.location menu_html = menus.generate(request, "Tableau Editor", "tableau_editor", "add_filter") return render_to_response("tableau_editor/templates/add_view_filter.html", {'menu_html' : menu_html, 'heading' : "Add Filter for Tableau View '" + view.name + "'", 'cur_loc' : cur_loc, }, context_instance=RequestContext(request))
def preview(request): """ Respond to the "/preview/" URL. We preview the tableau for the given location. """ if not request.user.is_authenticated: return HttpResponseRedirect(reverse(settings.ADMIN_HOME_VIEW)) if request.method == "GET": loc_code = request.GET.get("location") tableau_name = request.GET.get("tableau") elif request.method == "POST": loc_code = request.POST.get("location") tableau_name = request.POST.get("tableau") if request.POST.get("finished") != None: # Redirect the user back to the main "edit tableau" page. try: tableau = Tableau.objects.get(location__code=loc_code, name=tableau_name) except Tableau.DoesNotExist: return HttpResponseRedirect( reverse("location_editor.views.tableaux", args=[loc_code])) return HttpResponseRedirect( reverse("tableau_editor.views.edit_tableau", args=[tableau.id])) # Prepare the tableau to display. max_width = 800 max_height = 600 try: tableau = Tableau.objects.get(location__code=loc_code, name=tableau_name) except Tableau.DoesNotExist: return HttpResponseRedirect( reverse("location_editor.views.tableaux", args=[loc_code])) layout = tableau.tableaulayout_set.all()[0] layout_aspect_ratio = float(layout.width) / float(layout.height) if max_width / layout_aspect_ratio > max_height: height = max_height width = int(height * layout_aspect_ratio) else: width = max_width height = int(width / layout_aspect_ratio) generated_tableau = tableauGenerator.generate_tableau(tableau, width, height) shapes = [] # Add a rectangle to show the tableau's bounds. render = generated_tableau['render'] shapes.append({'type' : "RECTANGLE", 'x' : 0, 'y' : 0, 'width' : width, 'height' : height, 'fillColour' : render.get('fill_color', "none"), 'fillOpacity' : render.get('fill_opacity', 1.0), 'lineColour' : render.get('border_color', "none"), 'lineSize' : render.get('border_size', 0.0), 'lineOpacity' : render.get('border_opacity', 1.0), }) # Process the tableau's views. for view in generated_tableau['views']: # Draw the view's outline. render = view['render'] shapes.append({'type' : "RECTANGLE", 'x' : view['min_x'], 'y' : view['min_y'], 'width' : view['max_x'] - view['min_x'] + 1, 'height' : view['max_y'] - view['min_y'] + 1, 'fillColour' : render.get('fill_color', "none"), 'fillOpacity' : render.get('fill_opacity', 1.0), 'lineColour' : render.get('border_color', "none"), 'lineSize' : render.get('border_size', 0.0), 'lineOpacity' : render.get('border_opacity', 1.0), }) # Draw the view's location polygons. for location in view['locations']: render = location['render'] for polygon in location['polygons']: exterior = [] for x,y in polygon['exterior']: exterior.append([x, y]) shapes.append( {'type' : "POLYGON", 'exterior' : exterior, 'fillColour' : render.get('fill_color', "none"), 'fillOpacity' : render.get('fill_opacity', 1.0), 'lineColour' : render.get('border_color', "none"), 'lineSize' : render.get('border_size', 0.0), 'lineOpacity' : render.get('border_opacity', 1.0), }) # Display the generated web page. menu_html = menus.generate(request, "Tableau Editor", "tableau_editor", "preview") return render_to_response("tableau_editor/templates/preview.html", {'menu_html' : menu_html, 'heading' : "Previewing tableau '" + tableau_name + "'", 'loc_code' : loc_code, 'tableau_name' : tableau_name, 'width' : width, 'height' : height, 'shapes' : shapes, }, context_instance=RequestContext(request))
def list(request, type): """ Respond to the "/render_instructions/list/<TYPE>" URL. We let the user view the list of tableau rendering instructions for the given type of element. """ if not request.user.is_superuser: return HttpResponseRedirect(reverse(settings.ADMIN_HOME_VIEW)) # See if we've been given a valid "type" parameter. If not, reload the # page with type="tableau". if type == "tableau": type_num = TableauRenderingInstructions.TYPE_TABLEAU elif type == "view": type_num = TableauRenderingInstructions.TYPE_VIEW elif type == "location": type_num = TableauRenderingInstructions.TYPE_LOCATION elif type == "bubble": type_num = TableauRenderingInstructions.TYPE_BUBBLE else: return HttpResponseRedirect( reverse("tableau_editor.views.render_instructions.list") + "tableau/") # Load the list of current tableau rendering instructions of the given type # into memory. renders = [] for render in TableauRenderingInstructions.objects.filter(type=type_num): renders.append(render) # See what the user wants to do. if request.method == "GET": # We're displaying the form for the first time. Process our CGI # parameters (if any). confirm = request.GET.get("confirm") err_msg = None elif request.method == "POST": confirm = request.POST.get("confirm") err_msg = None # initially. # If the user clicked on the "Finished" button, redirect the user back # to the main admin page. if request.POST.get("finished") != None: return HttpResponseRedirect(reverse("tableau_editor.views.main")) # See if the user clicked on the "Add" button. if request.POST.get("add") != None: new_name = request.POST.get("name") name_ok = True # initially. if new_name in [None, ""]: err_msg = "Please enter a name." name_ok = False if name_ok: for render in renders: if new_name.upper() == render.name.upper(): err_msg = "That name is already in use." name_ok = False break if name_ok: # Create a new set of tableau rendering instructions for this # name. render = TableauRenderingInstructions() render.type = type_num render.name = new_name if len(renders) == 0: # Make the first set of rendering instructions the default. render.default = True else: render.default = False render.border_size = 0 render.border_color = "000000" # black. render.border_opacity = 1.0 render.fill_color = "ffffff" # white. render.fill_opacity = 1.0 render.save() # Reload the page so that the newly-created location shows up. return HttpResponseRedirect( reverse("tableau_editor.views." + "render_instructions.list", args=[type])) # If the user clicked on one of our "Edit" buttons, redirect the user # to the "Edit Rendering Instruction" page. for render in renders: if request.POST.get("edit-" + str(render.id)) != None: return HttpResponseRedirect( reverse("tableau_editor.views." + "render_instructions.edit", args=[render.id])) # If the user clicked on one of our "Delete" buttons, we firstly # display the confirmation button beside the instructions, and only # delete the instructions if the user confirms. for render in renders: deleteValue = request.POST.get("del-" + str(render.id)) if deleteValue == "Delete": # Prevent the user from deleting the default rendering # instructions. if render.default: err_msg = "You can't delete the default " \ + "set of rendering instructions." else: # Show the confirmation button. return HttpResponseRedirect( reverse("tableau_editor.views." + "render_instructions.list", args=[type]) + "?confirm=" + str(render.id)) elif deleteValue == "Yes": # Delete this set of rendering instructions. render.delete() # Reload the page to show the updated list of rendering # instructions. return HttpResponseRedirect( reverse("tableau_editor.views." + "render_instructions.list", args=[type])) # If the user clicked on one of our "Set Default" buttons, change the # default template. for render in renders: if request.POST.get("default-" + str(render.id)) != None: for r in renders: if r.default: r.default = False r.save() render.default = True render.save() # Reload the page to show the updated list of rendering # instructions. return HttpResponseRedirect( reverse("tableau_editor.views." + "render_instructions.list", args=[type])) # Finally, display the generated web page. menu_html = menus.generate(request, "Tableau Editor", "tableau_editor", "render_instructions.list") return render_to_response("tableau_editor/templates/render_list.html", {'menu_html' : menu_html, 'heading' : "Tableau Rendering Instructions", 'type' : type, 'renders' : renders, 'confirm' : confirm, 'err_msg' : err_msg}, context_instance=RequestContext(request))
def fix_disowned(request): """ Respond to the "/fixdisowned" URL. We fix any "disowned" locations -- locations where the parent/child, child/parent, or neighbour/neighbour relations aren't symmetrical. In particular: * If a location has a parent which doesn't list the locaiton as a child, a child entry will be added to the parent. * If a location has a child which doesn't list the location as a parent, a parent entry will be added to the child. * If a location has a neighbour which doesn't list the location as a neighbour, a neighbour entry will be added to the neighbour. """ # Display a "please wait" message while we work. if not pleasewait.shown(request): return pleasewait.message(request, "Whenua Admin", "Location Sanity-Checker", "Fixing disowned locations, please wait...") # Get a connection to our database. cursor = connections['geo_shared'].cursor() # Load the list of Level records into memory. levelIDToNumber = {} # Maps Level record ID to level number. for level in Level.objects.all(): levelIDToNumber[level.id] = level.level # Load the list of Location records into memory. locations = {} # Maps record ID to a (code, level_num, name, display_name) # tuple. cursor.execute("SELECT id,code,level_id,name,display_name " + "FROM shared_location") row = cursor.fetchone() while row != None: id,code,level_id,name,display_name = row level_num = levelIDToNumber[level_id] locations[id] = (code, level_num, name, display_name) row = cursor.fetchone() # Load the list of location parents into memory. location_parents = {} # Maps record ID to a set of parent record IDs. cursor.execute("SELECT from_location_id,to_location_id " + "FROM shared_location_parents") row = cursor.fetchone() while row != None: from_loc_id,to_loc_id = row try: location_parents[from_loc_id].add(to_loc_id) except KeyError: location_parents[from_loc_id] = set([to_loc_id]) row = cursor.fetchone() # Load the list of location children into memory. location_children = {} # Maps record ID to set of child record IDs. cursor.execute("SELECT from_location_id,to_location_id " + "FROM shared_location_children") row = cursor.fetchone() while row != None: from_loc_id,to_loc_id = row try: location_children[from_loc_id].add(to_loc_id) except KeyError: location_children[from_loc_id] = set([to_loc_id]) row = cursor.fetchone() # Load the list of location neighbours into memory. location_neighbours = {} # Maps record ID to set of neighbour record IDs. cursor.execute("SELECT from_location_id,to_location_id " + "FROM shared_location_neighbors") row = cursor.fetchone() while row != None: from_loc_id,to_loc_id = row try: location_neighbours[from_loc_id].add(to_loc_id) except KeyError: location_neighbours[from_loc_id] = set([to_loc_id]) row = cursor.fetchone() # Fix any locations which have been "disowned" by their parents. That is, # location A lists location B as a parent, but location B doesn't list # location A as a child. num_parents_fixed = 0 for loc_id in locations.keys(): if loc_id not in location_parents: continue # No parents. for parent_id in location_parents[loc_id]: disowned = False if parent_id not in location_children: disowned = True elif loc_id not in location_children[parent_id]: disowned = True if disowned: location = Location.objects.get(id=loc_id) parent = Location.objects.get(id=parent_id) parent.children.add(location) num_parents_fixed = num_parents_fixed + 1 # Fix any locations which have been "disowned" by their children. That is, # location A lists location B as a child, but location B doesn't list # location A as a parent. num_children_fixed = 0 for loc_id in locations.keys(): if loc_id not in location_children: continue # No children. for child_id in location_children[loc_id]: disowned = False if child_id not in location_parents: disowned = True elif loc_id not in location_parents[child_id]: disowned = True if disowned: location = Location.objects.get(id=loc_id) child = Location.objects.get(id=child_id) child.parents.add(location) num_children_fixed = num_children_fixed + 1 # Fix any locations which are "disowned" by their neighbours. That is, # location A lists location B as a neighbour, but location B doesn't list # location A as a neighbour. num_neighbours_fixed = 0 for loc_id in locations.keys(): if loc_id not in location_neighbours: continue # No neighbours. for neighbour_id in location_neighbours[loc_id]: disowned = False if neighbour_id not in location_neighbours: disowned = True elif loc_id not in location_neighbours[neighbour_id]: disowned = True if disowned: location = Location.objects.get(id=loc_id) neighbour = Location.objects.get(id=neighbour_id) neighbour.neighbors.add(location) num_neighbours_fixed = num_neighbours_fixed + 1 # Finally, tell the user the results. admin_home_url = reverse(settings.ADMIN_HOME_VIEW) menu_html = menus.generate(request, "sanity_checker", "main") return render_to_response("sanity_checker/templates/disowned_fixed.html", {'menu_html' : menu_html, 'num_parents_fixed' : num_parents_fixed, 'num_children_fixed' : num_children_fixed, 'num_neighbours_fixed' : num_neighbours_fixed, 'admin_home_url' : admin_home_url}, context_instance=RequestContext(request))
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 check(request): """ Respond to the "/check" URL. We display a "please wait" message while performing the sanity check, and then finally display the results back to the caller. """ if not request.user.is_authenticated: return HttpResponseRedirect(reverse(settings.ADMIN_HOME_VIEW)) # Display a "please wait" message while waiting for the results to be # calculated. if not pleasewait.shown(request): return pleasewait.message(request, "Whenua Admin", "Location Sanity-Checker", "Checking locations, please wait...") # Get a connection to our database. cursor = connections['geo_shared'].cursor() # Load the list of Level records into memory. levelIDToNumber = {} # Maps Level record ID to level number. levelNumberToName = {} # Maps Level number to name. for level in Level.objects.all(): levelIDToNumber[level.id] = level.level levelNumberToName[level.level] = level.name # Load the list of Location records into memory. locations = {} # Maps record ID to a (code, level_num, name, display_name) # tuple. cursor.execute("SELECT id,code,level_id,name,display_name " + "FROM shared_location") row = cursor.fetchone() while row != None: id,code,level_id,name,display_name = row level_num = levelIDToNumber[level_id] locations[id] = (code, level_num, name, display_name) row = cursor.fetchone() # Load the list of location parents into memory. location_parents = {} # Maps record ID to a set of parent record IDs. cursor.execute("SELECT from_location_id,to_location_id " + "FROM shared_location_parents") row = cursor.fetchone() while row != None: from_loc_id,to_loc_id = row try: location_parents[from_loc_id].add(to_loc_id) except KeyError: location_parents[from_loc_id] = set([to_loc_id]) row = cursor.fetchone() # Load the list of location children into memory. location_children = {} # Maps record ID to set of child record IDs. cursor.execute("SELECT from_location_id,to_location_id " + "FROM shared_location_children") row = cursor.fetchone() while row != None: from_loc_id,to_loc_id = row try: location_children[from_loc_id].add(to_loc_id) except KeyError: location_children[from_loc_id] = set([to_loc_id]) row = cursor.fetchone() # Load the list of location neighbours into memory. location_neighbours = {} # Maps record ID to set of neighbour record IDs. cursor.execute("SELECT from_location_id,to_location_id " + "FROM shared_location_neighbors") row = cursor.fetchone() while row != None: from_loc_id,to_loc_id = row try: location_neighbours[from_loc_id].add(to_loc_id) except KeyError: location_neighbours[from_loc_id] = set([to_loc_id]) row = cursor.fetchone() # Load the list of names into memory. names = {} # Maps record ID to name. cursor.execute("SELECT id,name FROM shared_name") row = cursor.fetchone() while row != None: id,name = row names[id] = name row = cursor.fetchone() # Load the list of names used by each location into memory. location_names = {} # Maps location record ID to set of name record IDs. cursor.execute("select location_id,name_id FROM shared_locationname") row = cursor.fetchone() while row != None: loc_id,name_id = row try: location_names[loc_id].add(name_id) except KeyError: location_names[loc_id] = set([name_id]) row = cursor.fetchone() # Now that we've got all the information we need in memory, start looking # for potentially bad locations. bad_locs = [] # List of potentially bad locations. Each list item is a # dictionary with the following entries: # # 'code' # # The location's code. # # 'level' # # A descriptive name for this location's level # # 'name' # # The name for this location. # # 'problem' # # A string describing what was wrong with the # location. # Find any locations that aren't countries and lack parents. for loc_id in locations.keys(): level_num = locations[loc_id][1] if level_num == 1: continue # ignore countries. if len(location_parents.get(loc_id, [])) == 0: # This location has no parents -> flag it as a bad location. code,level_num,name,display_name = locations[loc_id] bad_locs.append({'code' : code, 'level' : levelNumberToName[level_num], 'name' : name, 'problem' : "lacks a parent"}) # Find any locations which lack a name. for loc_id in locations.keys(): level_num = locations[loc_id][1] if level_num == 8: continue # ZIP codes don't have names. if len(location_names.get(loc_id, [])) == 0: # This location has no name -> flag it as a bad location. code,level_num,name,display_name = locations[loc_id] bad_locs.append({'code' : code, 'level' : levelNumberToName[level_num], 'name' : name, 'problem' : "has no names"}) # Find any locations which have names ending or starting with a space. bad_name_ids = set() # Set of name IDs which have bad values. for name_id,name in names.items(): badName = False if name.startswith(" "): badName = True if name.endswith(" "): badName = True if badName: bad_name_ids.add(name_id) for loc_id,name_ids_for_loc in location_names.items(): for bad_name_id in name_ids_for_loc.intersection(bad_name_ids): code,level_num,name,display_name = locations[loc_id] bad_name = names[bad_name_id] bad_locs.append({'code' : code, 'level' : levelNumberToName[level_num], 'name' : name, 'problem' : "has a name (" + bad_name + ") " + "starting or ending with a space"}) # Find any locations which have been "disowned" by their parents. That is, # location A lists location B as a parent, but location B doesn't list # location A as a child. for loc_id in locations.keys(): if loc_id not in location_parents: continue # No parents. for parent_id in location_parents[loc_id]: disowned = False if parent_id not in location_children: disowned = True elif loc_id not in location_children[parent_id]: disowned = True if disowned: code,level_num,name,display_name = locations[loc_id] parent_code = locations[parent_id][0] parent_name = locations[parent_id][2] bad_locs.append({'code' : code, 'level' : levelNumberToName[level_num], 'name' : name, 'problem' : "has been disowned by parent " + parent_name+" ("+parent_code+")", }) # Find any locations which have been "disowned" by their children. That # is, location A lists location B as a child, but location B doesn't list # location A as a parent. for loc_id in locations.keys(): if loc_id not in location_children: continue # No children. for child_id in location_children[loc_id]: disowned = False if child_id not in location_parents: disowned = True elif loc_id not in location_parents[child_id]: disowned = True if disowned: code,level_num,name,display_name = locations[loc_id] child_code = locations[child_id][0] child_name = locations[child_id][2] bad_locs.append({'code' : code, 'level' : levelNumberToName[level_num], 'name' : name, 'problem' : "has been disowned by child " + child_name+" ("+child_code+")", }) # Find any locations which are "disowned" by their neighbours. That is, # location A lists location B as a neighbour, but location B doesn't list # location A as a neighbour. for loc_id in locations.keys(): if loc_id not in location_neighbours: continue # No neighbours. for neighbour_id in location_neighbours[loc_id]: disowned = False if neighbour_id not in location_neighbours: disowned = True elif loc_id not in location_neighbours[neighbour_id]: disowned = True if disowned: code,level_num,name,display_name = locations[loc_id] neighbour_code = locations[neighbour_id][0] neighbour_name = locations[neighbour_id][2] bad_locs.append({'code' : code, 'level' : levelNumberToName[level_num], 'name' : name, 'problem' : "has been disowned by neighbor " + neighbour_name + " (" + neighbour_code + ")", }) # Find any locations which lack a default tableau. cursor.execute("SELECT id FROM shared_location WHERE NOT EXISTS (" + "SELECT * FROM shared_tableau WHERE shared_location.id=" + "shared_tableau.location_id AND shared_tableau.name=" + '"DEFAULT")') row = cursor.fetchone() while row != None: loc_id = row[0] code,level_num,name,display_name = locations[loc_id] bad_locs.append({'code' : code, 'level' : levelNumberToName[level_num], 'name' : name, 'problem' : "is missing a default tableau"}) row = cursor.fetchone() # Finally, display the potentially-bad locations to the user. admin_home_url = reverse(settings.ADMIN_HOME_VIEW) menu_html = menus.generate(request, "sanity_checker", "main") return render_to_response("sanity_checker/templates/results.html", {'menu_html' : menu_html, 'bad_locs' : bad_locs, 'admin_home_url' : admin_home_url}, context_instance=RequestContext(request))
def create_all_idle(request): """ Respond to the "/create_all_idle" URL. We display the accumulated errors, if any, and give the user the chance to start generating all the factory tableaux. """ num_to_go = TableauFactoryGenerationRequest.objects.count() if request.method == "GET": pass # We're displaying the page for the first time -> nothing to do. elif request.method == "POST": # If the user clicked on our "Finished" button, go back to the main # tableau factory page. if request.POST.get("finished") != None: return HttpResponseRedirect( reverse("tableau_editor.views.tableau_factories.main")) # If the user clicked on our "Create all Factory Tableaux" button, # start generating the requests. if request.POST.get("create_all_tableaux") != None: # Add entries to the tableau factory generation request queue # to create the requested factory tableaux. _queue_requests() # Clear the previous list of errors. _clear_errors() # Redirect the user to the "busy" page so we can see the # ongoing progress of the tableau creation. return HttpResponseRedirect(reverse( "tableau_editor.views.create_factory.create_all_busy")) # Finally, display our page to the user. menu_html = menus.generate(request, "Tableau Editor", "tableau_editor", "create_all_tableaux") errors = [] for error in TableauFactoryGenerationError.objects.all(): try: factory = TableauFactory.objects.get(id=error.factory_id) except TableauFactory.DoesNotExist: continue # Should never happen. try: location = Location.objects.get(code=error.loc_code) except Location.DoesNotExist: continue # Should never happen. errors.append({'factory' : factory, 'location' : location, 'err_msg' : error.err_msg}) return render_to_response("tableau_editor/templates/create_all_idle.html", {'num_to_go' : num_to_go, 'menu_html' : menu_html, 'errors' : errors, }, context_instance=RequestContext(request))
def outline(request, loc_code): """ Respond to the "/outline/XYZ/" URL. We let the user edit the outline for 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(settings.ADMIN_HOME_VIEW)) try: outline = Outline.objects.get(location=location) except Outline.DoesNotExist: outline = Outline() outline.location = location outline.save() formType = getMapForm() if request.method == "GET": # We're visiting the page for the first time -> just display it. wkt = outline.outline form = formType({'geometry' : wkt}) elif request.method == "POST": # The user is submitting our form. If the user clicked on the # "Finished" button, redirect the user back to the main location editor # page. if request.POST.get("finished") == "Finished": return HttpResponseRedirect( reverse("location_editor.views.main")) # Save the updated outline back into the database. form = formType(request.POST) try: if form.is_valid(): wkt = form.cleaned_data['geometry'] outline.outline = wkt outline.save() # Finally, tell the user's web browser to reload the page. return HttpResponseRedirect( reverse("location_editor.views.outline", args=[loc_code])) except ValueError: pass # If we get here, display the form. imports = [] imports.append('<script src="http://openlayers.org/api/OpenLayers.js">') imports.append('</script>') menu_html = menus.generate(request, "Location Editor", "location_editor", "outline") return render_to_response("location_editor/templates/wrapper.html", {'menu_html' : menu_html, 'tab' : "outline", 'heading' : "Editing " + str(location), 'location' : location, 'template_name' : "outline.html", 'extra_head_tags' : imports, 'errMsg' : None, 'form' : form, }, context_instance=RequestContext(request))
def edit_view(request, view_id): """ Respond to the "/edit_view/NNN/" URL. We let the user edit the given tableau view. """ if not request.user.is_authenticated: return HttpResponseRedirect(reverse(settings.ADMIN_HOME_VIEW)) try: view = TableauView.objects.get(id=view_id) except TableauView.DoesNotExist: return HttpResponseRedirect(reverse(settings.ADMIN_HOME_VIEW)) tableau = view.tableau filters = [] for filter in TableauViewFilter.objects.filter(tableauView=view): filters.append(filter) try: meta_data_dict = eval(view.meta_data) except: meta_data_dict = {} meta_data = [] for key,value in sorted(meta_data_dict.items()): meta_data.append({'key' : key, 'value' : value}) if view.bounds_render == None: cur_render = None else: cur_render = view.bounds_render.name all_renders = [] for render in TableauRenderingInstructions.objects.filter( type=TableauRenderingInstructions.TYPE_VIEW): all_renders.append(render.name) # See what the user wants to do. if request.method == "GET": # We're displaying the form for the first time. Process our CGI # parameters (if any). err_msg = None confirm_filter = request.GET.get("confirm_filter") elif request.method == "POST": err_msg = None # initially. confirm_filter = request.POST.get("confirm_filter") # If the user clicked on the "Finished" button, redirect the user back # to the "Edit Tableau" page for this tableau. if request.POST.get("finished") != None: return HttpResponseRedirect( reverse("tableau_editor.views.edit_tableau", args=[tableau.id])) # If the user clicked on the "Update Name" button, update the view's # name. if request.POST.get("update-name") != None: name = request.POST.get("name") if name.upper() != view.name.upper(): if TableauView.objects.filter(tableau=tableau, name=name).exists(): err_msg = "That name is already used by another " \ + " view within this tableau." if err_msg == None: view.name = name view.save() return HttpResponseRedirect( reverse("tableau_editor.views.edit_view", args=[view.id])) # If the user clicked on the "Reset Bounds" button, reset the view's # bounds to the location's display bounds. if request.POST.get("reset_bounds") != None: view.min_lat = tableau.location.min_zoom_lat view.max_lat = tableau.location.max_zoom_lat view.min_long = tableau.location.min_zoom_long view.max_long = tableau.location.max_zoom_long view.save() updateViewPositions(view) return HttpResponseRedirect( reverse("tableau_editor.views.edit_view", args=[view.id])) # If the user dragged out a new view bounds, update the view's bounds # and redisplay the page. if request.POST.get("set_bounds") == "yes": # Store the updated bounds into the TableauView record. Note that # we have to convert the coordinates from meters to lat/long values # before saving them. min_x = float(request.POST['min_x']) min_y = float(request.POST['min_y']) max_x = float(request.POST['max_x']) max_y = float(request.POST['max_y']) proj = GlobalMercator() min_lat,min_long = proj.MetersToLatLon(min_x, min_y) max_lat,max_long = proj.MetersToLatLon(max_x, max_y) view.min_lat = "%0.4f" % min_lat view.min_long = "%0.4f" % min_long view.max_lat = "%0.4f" % max_lat view.max_long = "%0.4f" % max_long view.save() updateViewPositions(view) return HttpResponseRedirect( reverse("tableau_editor.views.edit_view", args=[view.id])) # If the user clicked on the "Add Filter" button, redirect the user to # the "Add Tableau View Filter" page. if request.POST.get("add-filter") != None: return HttpResponseRedirect( reverse("tableau_editor.views.add_filter", args=[view.id])) # If the user clicked on the "Edit" button for a filter, display the # "Edit Tableau View Filter" page for the clicked-on filter. for filter in filters: if request.POST.get("edit-filter-" + str(filter.id)) == "Edit": return HttpResponseRedirect( reverse("tableau_editor.views.edit_filter", args=[filter.id])) # If the user clicked on the "Delete" button for a filter, firstly # display the confirmation button beside the filter, and only delete # the filter if the user confirms. for filter in filters: deleteValue = request.POST.get("del-filter-" + str(filter.id)) if deleteValue == "Delete": # Show the confirmation button. return HttpResponseRedirect( reverse("tableau_editor.views.edit_view", args=[view.id]) + "?confirm_filter="+str(filter.id)) elif deleteValue == "Yes": # Delete this filter. filter.delete() # Redisplay the page without the confirmation buttons. return HttpResponseRedirect( reverse("tableau_editor.views.edit_view", args=[view.id])) # If the user clicked on the "Add Meta-Data" button, add the entered # key and value (if any) to the view's meta-data. if request.POST.get("add-meta") != None: key = request.POST.get("meta-data-key-new") value = request.POST.get("meta-data-value-new") if key not in ["", None] and value not in ["", None]: # Add the entered key and value to the tableau's meta-data. try: meta_data_dict = eval(view.meta_data) except: meta_data_dict = {} meta_data_dict[key] = value view.meta_data = repr(meta_data_dict) view.save() # Redisplay the page with the updated meta-data. return HttpResponseRedirect( reverse("tableau_editor.views.edit_view", args=[view.id])) # If the user clicked on the "Update Meta-Data" button, update the # associated meta-data value. for i in range(len(meta_data)): if request.POST.get("update-meta-" + str(i)) != None: key = request.POST.get("meta-data-key-" + str(i)) value = request.POST.get("meta-data-value-" + str(i)) if key not in ["", None] and value not in ["", None]: # Store the updated key and value into the view's # meta-data. try: meta_data_dict = eval(view.meta_data) except: meta_data_dict = {} del meta_data_dict[meta_data[i]['key']] meta_data_dict[key] = value view.meta_data = repr(meta_data_dict) view.save() # Redisplay the page with the updated meta-data. return HttpResponseRedirect( reverse("tableau_editor.views.edit_view", args=[view.id])) # If the user clicked on the "Remove Meta-Data" button, remove the # associated meta-data value. for i in range(len(meta_data)): if request.POST.get("del-meta-" + str(i)) != None: try: meta_data_dict = eval(view.meta_data) except: meta_data_dict = {} del meta_data_dict[meta_data[i]['key']] view.meta_data = repr(meta_data_dict) view.save() # Redisplay the page with the updated meta-data. return HttpResponseRedirect( reverse("tableau_editor.views.edit_view", args=[view.id])) # If the user clicked on the "Set" button beside a rendering # instruction, set the view's current rendering instruction. for render_name in all_renders: if request.POST.get("render-" + render_name) != None: try: render = TableauRenderingInstructions.objects.get( type=TableauRenderingInstructions.TYPE_VIEW, name=render_name) except TableauRenderingInstructions.DoesNotExist: render = None view.bounds_render = render view.save() # Redisplay the page with the updated rendering instruction. return HttpResponseRedirect( reverse("tableau_editor.views.edit_view", args=[view.id])) # If the user clicked on the "Set" button for the default rendering # instruction, set the view to use the default. if request.POST.get("render-") != None: view.bounds_render = None view.save() # Redisplay the page with the updated rendering instruction. return HttpResponseRedirect( reverse("tableau_editor.views.edit_view", args=[view.id])) # If we get here, we're going to display the page. Calculate the # information we need to display the bounding box map. try: outline = Outline.objects.get(location=tableau.location) except Outline.DoesNotExist: outline = None if outline != None: # Convert the outline to WKT format, reprojecting it into Spherical # Mercator projection so we can display it on the map. ogrGeom = outline.outline.ogr ogrGeom.transform(900913) wkt = ogrGeom.wkt else: wkt = None if outline != None and outline.outline != None: min_long,min_lat,max_long,max_lat = outline.outline.extent else: if view.min_long != None: min_long = float(view.min_long) else: min_long = 0 if view.min_lat != None: min_lat = float(view.min_lat) else: min_lat = 0 if view.max_long != None: max_long = float(view.max_long) else: max_long = 0 if view.max_lat != None: max_lat = float(view.max_lat) else: max_lat = 0 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 proj = GlobalMercator() origin_lat = float(min_lat + max_lat) / 2 origin_long = float(min_long + max_long) / 2 origin_x,origin_y = proj.LatLonToMeters(origin_lat, origin_long) mLeft,mBottom = proj.LatLonToMeters(min_lat, min_long) mRight,mTop = proj.LatLonToMeters(max_lat, max_long) starting_zoom_level = None for zoom in range(MAX_ZOOM_LEVEL, -1, -1): pLeft,pBottom = proj.MetersToPixels(mLeft, mBottom, zoom) pRight, pTop = proj.MetersToPixels(mRight, mTop, zoom) pixel_width = pRight - pLeft pixel_height = pTop - pBottom if pixel_width <= MAP_WIDTH and pixel_height <= MAP_HEIGHT: # We've reached a zoom level that fits the entire bounds onto # the map -> this is our desired starting zoom level. starting_zoom_level = zoom break if view.min_long != None and view.min_lat != None and \ view.max_long != None and view.max_lat != None: has_bounds = True bounds_left = float(view.min_long) bounds_right = float(view.max_long) bounds_bottom = float(view.min_lat) bounds_top = float(view.max_lat) mBounds_left,mBounds_bottom = proj.LatLonToMeters(bounds_bottom, bounds_left) mBounds_right,mBounds_top = proj.LatLonToMeters(bounds_top, bounds_right) else: has_bounds = False # Finally, display our web page. menu_html = menus.generate(request, "Tableau Editor", "tableau_editor", "edit_view") return render_to_response("tableau_editor/templates/edit_view.html", {'menu_html' : menu_html, 'heading' : "Edit View for " + "Tableau '" + tableau.name + "'", 'name' : view.name, 'err_msg' : err_msg, 'map_width' : MAP_WIDTH, 'map_height' : MAP_HEIGHT, 'wkt' : wkt, 'has_bounds' : has_bounds, 'mBounds_left' : mBounds_left, 'mBounds_bottom' : mBounds_bottom, 'mBounds_right' : mBounds_right, 'mBounds_top' : mBounds_top, 'origin_x' : origin_x, 'origin_y' : origin_y, 'starting_zoom_level' : starting_zoom_level, 'filters' : filters, 'meta_data' : meta_data, 'meta_data_new' : {'key' : "", 'value' : ""}, 'cur_render' : cur_render, 'all_renders' : all_renders, 'confirm_filter' : confirm_filter, }, context_instance=RequestContext(request))
def edit_tableau(request, tableau_id): """ Respond to the "/edit_tableau/NN" URL. We let the user edit the Tableau record with the given ID. """ if not request.user.is_authenticated: return HttpResponseRedirect(reverse(settings.ADMIN_HOME_VIEW)) try: tableau = Tableau.objects.get(id=tableau_id) except Tableau.DoesNotExist: return HttpResponseRedirect( reverse("location_editor.views.main")) location = tableau.location views = [] for view in TableauView.objects.filter(tableau=tableau).order_by( "ordinal_rank"): views.append(view) layouts = [] for layout in TableauLayout.objects.filter(tableau=tableau).order_by( "width", "height"): layouts.append(layout) try: meta_data_dict = eval(tableau.meta_data) except: meta_data_dict = {} meta_data = [] for key,value in sorted(meta_data_dict.items()): meta_data.append({'key' : key, 'value' : value}) if tableau.bounds_render == None: cur_render = None else: cur_render = tableau.bounds_render.name all_renders = [] for render in TableauRenderingInstructions.objects.filter( type=TableauRenderingInstructions.TYPE_TABLEAU): all_renders.append(render.name) # See what the user wants to do. if request.method == "GET": # We're displaying the form for the first time. Process our CGI # parameters (if any). err_msg = None confirm_view = request.GET.get("confirm_view") confirm_layout = request.GET.get("confirm_layout") elif request.method == "POST": err_msg = None # initially. confirm_view = request.POST.get("confirm_view") confirm_layout = request.POST.get("confirm_layout") # If the user clicked on the "Finished" button, redirect the user back # to the main tableau page for this location. if request.POST.get("finished") != None: return HttpResponseRedirect( reverse("tableau_editor.views.select", args=[location.code])) # If the user clicked on the "Preview" button, redirect the user to the # "preview tableau" page for this location and tableau name. if request.POST.get("preview") != None: return HttpResponseRedirect( reverse("tableau_editor.views.preview") + "?location=" + location.code + "&tableau=" + tableau.name) # If the user clicked on the "Update Name" button, update the tableau's # name. if request.POST.get("update-name") != None: name = request.POST.get("name") if name.upper() != tableau.name.upper(): if tableau.name.upper() == "DEFAULT": err_msg = "Sorry, you can't change the name of the " \ + "default tableau." if err_msg == None: if Tableau.objects.filter(location=location, name=name).exists(): err_msg = "That name is already used by another " \ + " tableau for this location." if err_msg == None: tableau.name = name tableau.save() return HttpResponseRedirect( reverse("tableau_editor.views.edit_tableau", args=[tableau.id])) # If the user clicked on the "Add View" button, redirect the user to # the "Add Tableau View" page. if request.POST.get("add-view") != None: return HttpResponseRedirect( reverse("tableau_editor.views.add_view", args=[tableau.id])) # If the user clicked on the "Edit" button for a view, display the # "Edit Tableau View" page for the clicked-on view. for view in views: if request.POST.get("edit-view-" + str(view.id)) == "Edit": return HttpResponseRedirect( reverse("tableau_editor.views.edit_view", args=[view.id])) # If the user clicked on the "Delete" button for a view, firstly # display the confirmation button beside the view, and only delete the # view if the user confirms. for view in views: deleteValue = request.POST.get("del-view-" + str(view.id)) if deleteValue == "Delete": # Show the confirmation button. return HttpResponseRedirect( reverse("tableau_editor.views.edit_tableau", args=[tableau.id]) + "?confirm_view=" + str(view.id)) elif deleteValue == "Yes": # Delete this view. view.delete() # Redisplay the page without the confirmation buttons. return HttpResponseRedirect( reverse("tableau_editor.views.edit_tableau", args=[tableau.id])) # If the user clicked on the "Move Forward" button for a view, update # the ordinal rankings for the tableau's views as appropriate. for viewNum,view in enumerate(views): if request.POST.get("move-view-forward-" + str(view.id)) != None: # Move the given view forward by swapping ordinal rankings. if viewNum > 0: otherView = views[viewNum-1] rank1 = otherView.ordinal_rank rank2 = view.ordinal_rank view.ordinal_rank = rank1 view.save() otherView.ordinal_rank = rank2 otherView.save() # Redisplay the page. return HttpResponseRedirect( reverse("tableau_editor.views.edit_tableau", args=[tableau.id])) # If the user clicked on the "Move Backward" button for a view, update # the ordinal rankings for the tableau's views as appropriate. for viewNum,view in enumerate(views): if request.POST.get("move-view-backward-" + str(view.id)) != None: # Move the given view forward by swapping ordinal rankings. if viewNum < len(views)-1: otherView = views[viewNum+1] rank1 = view.ordinal_rank rank2 = otherView.ordinal_rank view.ordinal_rank = rank2 view.save() otherView.ordinal_rank = rank1 otherView.save() # Redisplay the page. return HttpResponseRedirect( reverse("tableau_editor.views.edit_tableau", args=[tableau.id])) # If the user clicked on the "Add Layout" button, redirect the user to # the "Add Tableau Layout" page. if request.POST.get("add-layout") != None: return HttpResponseRedirect( reverse("tableau_editor.views.add_layout", args=[tableau.id])) # If the user clicked on the "Edit" button for a layout, display the # "Edit Tableau Layout" page for the clicked-on layout. for layout in layouts: if request.POST.get("edit-layout-" + str(layout.id)) == "Edit": return HttpResponseRedirect( reverse("tableau_editor.views.edit_layout", args=[layout.id])) # If the user clicked on the "Delete" button for a layout, firstly # display the confirmation button beside the layout, and only delete # the layout if the user confirms. for layout in layouts: deleteValue = request.POST.get("del-layout-" + str(layout.id)) if deleteValue == "Delete": # Show the confirmation button. return HttpResponseRedirect( reverse("tableau_editor.views.edit_tableau", args=[tableau.id]) + "?confirm_layout="+str(layout.id)) elif deleteValue == "Yes": # Delete this layout. layout.delete() # Redisplay the page without the confirmation buttons. return HttpResponseRedirect( reverse("tableau_editor.views.edit_tableau", args=[tableau.id])) # If the user clicked on the "Add Meta-Data" button, add the entered # key and value (if any) to the tableau's meta-data. if request.POST.get("add-meta") != None: key = request.POST.get("meta-data-key-new") value = request.POST.get("meta-data-value-new") if key not in ["", None] and value not in ["", None]: # Add the entered key and value to the tableau's meta-data. try: meta_data_dict = eval(tableau.meta_data) except: meta_data_dict = {} meta_data_dict[key] = value tableau.meta_data = repr(meta_data_dict) tableau.save() # Redisplay the page with the updated meta-data. return HttpResponseRedirect( reverse("tableau_editor.views.edit_tableau", args=[tableau.id])) # If the user clicked on the "Update Meta-Data" button, update the # associated meta-data value. for i in range(len(meta_data)): if request.POST.get("update-meta-" + str(i)) != None: key = request.POST.get("meta-data-key-" + str(i)) value = request.POST.get("meta-data-value-" + str(i)) if key not in ["", None] and value not in ["", None]: # Store the updated key and value into the tableau's # meta-data. try: meta_data_dict = eval(tableau.meta_data) except: meta_data_dict = {} del meta_data_dict[meta_data[i]['key']] meta_data_dict[key] = value tableau.meta_data = repr(meta_data_dict) tableau.save() # Redisplay the page with the updated meta-data. return HttpResponseRedirect( reverse("tableau_editor.views.edit_tableau", args=[tableau.id])) # If the user clicked on the "Remove Meta-Data" button, remove the # associated meta-data value. for i in range(len(meta_data)): if request.POST.get("del-meta-" + str(i)) != None: try: meta_data_dict = eval(tableau.meta_data) except: meta_data_dict = {} del meta_data_dict[meta_data[i]['key']] tableau.meta_data = repr(meta_data_dict) tableau.save() # Redisplay the page with the updated meta-data. return HttpResponseRedirect( reverse("tableau_editor.views.edit_tableau", args=[tableau.id])) # If the user clicked on the "Set" button beside a rendering # instruction, set the template's current rendering instruction. for render_name in all_renders: if request.POST.get("render-" + render_name) != None: try: render = TableauRenderingInstructions.objects.get( type=TableauRenderingInstructions.TYPE_TABLEAU, name=render_name) except TableauRenderingInstructions.DoesNotExist: render = None tableau.bounds_render = render tableau.save() # Redisplay the page with the updated rendering instruction. return HttpResponseRedirect( reverse("tableau_editor.views.edit_tableau", args=[tableau.id])) # If the user clicked on the "Set" button for the default rendering # instruction, set the template to use the default. if request.POST.get("render-") != None: tableau.bounds_render = None tableau.save() # Redisplay the page with the updated rendering instruction. return HttpResponseRedirect( reverse("tableau_editor.views.edit_tableau", args=[tableau.id])) # If we get here, display our page with the tableau's details. menu_html = menus.generate(request, "Tableau Editor", "tableau_editor", "edit_tableau") return render_to_response("tableau_editor/templates/edit_tableau.html", {'menu_html' : menu_html, 'heading' : "Edit Tableau for " + str(location), 'name' : tableau.name, 'err_msg' : err_msg, 'views' : views, 'layouts' : layouts, 'meta_data' : meta_data, 'meta_data_new' : {'key' : "", 'value' : ""}, 'cur_render' : cur_render, 'all_renders' : all_renders, 'confirm_view' : confirm_view, 'confirm_layout' : confirm_layout, }, context_instance=RequestContext(request))