I have a script that gets a table from MSSQL database and then registers it with ArcGIS. It uses several other arcpy methods as well. I tried to combine it with Flask and developed an HTML interface where you can specify tables. The script runs on console perfectly well, however, when running with Flask on http://127.0.0.1:5000/ , the arcpy functions do not run, then the app throws errors.
I am using my local python directory, so I do not have any problem with importing arcpy on flask. So, I am able to use pymssql functions and create a new table, however when it comes to arcpy function, It throws does not exist error, however, the table exists. I feel like there is something wrong with running arcpy with Flask, but any help would be appreciated.
(2) I tried the same thing in Django but I am having the same problem.
Thanks
forms.py
class createGISLayer(FlaskForm):
tCreateLayer = SubmitField('Create GIS Layer')
DashboardMain()
try:
cursor.execute(QueryCreate)
print ("Table Created.")
print(self.dbTablePath)
descTable = arcpy.Describe(self.dbTablePath)
except arcpy.ExecuteError:
print(arcpy.GetMessages())
app.py
if formCreate.tCreateLayer.data and formCreate.validate_on_submit():
if myLayer is not None:
try:
print("Create GIS Layer")
myLayer.dashboardMain()
flash('GIS Layer created!', 'success')
except Exception as e:
print(e.message)
flash(e.message, 'danger')
index.html
<!-- Create GIS Layer -->
<div class="content-section">
<form name='idCreateGISLayer' action="" method="POST">
<table style="height: auto; margin-left: auto; margin-right: auto; width: 600px;">
<tbody>
<tr>
{{ formCreate.hidden_tag() }}
<td style="height: 39px; width: 259px">
<h2 style="text-align: left;"><font size="3"><strong>(2) Create </strong></font></h2>
</td>
<td style="text-align: left; height: 39px;">
<div class="auto-style2">
{{ formCreate.tCreateLayer(class="btn btn-outline-info")}}
</div>
</td>
</tr>
</tbody>
</table>
</form>
</div>
ERROR
Table Created.
F:\Projects\Dashboard\Publish.sde\Publish.dbo.A_WebT1
"F:\Projects\Dashboard\Publish.sde\Publish.dbo.A_WebT1" does not exist
screenshot
Instead of calling the function, I ran my script with DOS.
#app.route('/cad2json', methods=['POST'])
def cad2sde():
dwg_path = request.form.get('dwg_path')
reference_scale = request.form.get('reference_scale')
spatial_reference = request.form.get('spatial_reference')
target_layer = request.form.get('target_layer')
sentence = (u'C:\\Python27\\ArcGIS10.1\\python.exe C:\\Users\\Administrator \\Desktop\\flask\\cad.py %s %s %s %s'
%(dwg_path,reference_scale,spatial_reference,target_layer))
p = os.popen(sentence)
return format(p.read())
ArcPy is not free. It only works in ESRI software or anaconda. You can not import.
Related
This question already has an answer here:
Flask : href link to html not working
(1 answer)
Closed last year.
I'm trying to make a program to display some time and temperature numbers on a web page. I have two html templates, "index.html" and "set.html" in a "templates" directory under the main "furnace" directory. The index part works as it should when called by flask but the "set" link (to go to a page to enter a new time and date) results in a "404 Not found" error. I've stripped everything out of the Python program that isn't part of flask and displaying the html, and I still get the error. At this point, all that's left is about the same as simple examples I've found; I've compared my program to the examples and I just can't see what's going wrong. Can some sharp eyes spot my mistake?
furnace-9x.py
import time
import datetime
import RPi.GPIO as GPIO
import smbus
from gpiozero import Button
from flask import Flask, render_template
import SDL_DS3231_dev
import lcddriver
import threading
# Using a global here for simplicity in this demo
# Globals are generally bad practice, so you would maintain
# the status of "lcd_counter" in a more elegant way
# (e.g. through a shared module, through classes, etc.)
# A simple global serves the purpose for this demo
# of a flask server running in parallel to another process
# emulating some I/O, printing to the console, etc.
lcd_counter = 0
app = Flask(__name__)
#app.route("/")
def index():
print('Index')
global datetimestr, temperature
global minutes_24,minutes_30,heatOn
return render_template('index.html')
#app.route("/set")
def setTime():
print("Set time")
return render_template('set.html')
if __name__ == '__main__':
#=== Prelude ===
app.run(debug=False, host='0.0.0.0')
index.html
<!DOCTYPE html>
<html>
<head>
<style type="text/css">
body {font-family:arial;
background-color: rgb(185,179,175);
text-align: left;}
table, tr {text-align: left;
font-size: 150%;
border-style: solid;}
</style>
</head>
<body>
<h1>Furnace</h1>
<table>
<tr>
<td colspan="3">{{dtstr}}</td>
</tr>
<tr>
<td>30 day: </td>
<td>{{m30}}</td>
<td>{{p30}}%</td>
</tr>
<tr>
<td>24 hour: </td>
<td>{{m24}}</td>
<td>{{p24}}%</td>
</tr>
<tr>
<td>Temp:</td>
<td> {{temper}}°F </td>
<td>Heat: {{heat}}</td>
</tr>
</table>
<p>Set time</p>
</body>
</html>
set.html
<!DOCTYPE html>
<html>
<head>
<style type="text/css">
body {font-family:arial;
background-color: rgb(185,179,175);
text-align: left;}
table, tr {text-align: left;
font-size: 150%;
border-style: solid;}
</style>
</head>
<body>
<p>Enter the date and time:
<input type="text" name="datetime" size="15" maxlength="19" />
<input type="submit" value="Submit" />
</p>
</body>
</html>
The problem here is a mismatch between the link in index.html (set.html) and your route (/set).
To resolve the issue, you can update line 35 in your index.html like this:
<p>Set time</p>
The flask web server matches the route strings exactly, and not the file names of the templates. Even better, you can use the flask built in function url_for:
<p>Set time</p>
It is several years since I have used Flask, starting on a new project.
I get a HTTP 404 error. The requested URL is not found??
The index and the requested URL are both in the templates folder.
I don't understand why it is throwing a HTTP 404 error??
Any pointers appreciated, thanks.
Clive
I have a code snippet in routes.py.
#app.route('/service_response', methods=['GET','POST'])
def service_response():
servicesql = "SELECT * FROM DASHBOARD_SERVICE_RESPONSE"
data = list(conn.execute(servicesql))
return render_template('service_response.html', service_response=servicesql)
In index.html I have:
<div class="form chartdisplay" >
<div class="form-heading">BCC Report Period</div>
<br>
<div class="form-group"; class="height-auto";>
<table>
<thead>
<iframe src="service_response.html" width="90%" height="90%"></iframe>
</thead>
</table>
</div>
</div>
Your code points to src="service_response.html" while what you want to do is to point to /service_response which will render the 'service_response.html' jinja template.
here is my code to upload images to folder and name to the database and it isn't working.
i am getting an error 'bytes' object has no attribute 'image' Exception occured
#html code -->#
<html>
<head>
<TITLE> Product Image</TITLE>
</head>
<body>
<form enctype="multipart/form-data" action="productimg.py" method=post>
<table align=center cellspacing=20 cellpadding=10 >
<th align="center" colspan=3 > <u>Upload Image of the Goods</u></th>
<tr ><th colspan="4"> Enter your details below and wait minimum for half an hour.</th></tr>
<tr>
<td> Product Image : </td><td> <input type=file name="image" accept = "image/*" accept=".png/*" value="image"> </td>
</tr>
<tr>
<td> </td> <td> <input type=Submit > <input type=Reset> </td>
</tr>
</table>
</form>
</body>
</html>
i am getting an error 'bytes' object has no attribute 'image' Exception occured in pyhton code.
#python code -->#
#!C:\Users\Pc\AppData\Local\Programs\Python\Python38-32\python.exe
print('Content-type:text/html\n\r')
import cgi
import sys
from myconnect import *
message=0
try:
con,cur=myconnect()
form= cgi.FieldStorage()
# Get here.
fileitem=form.getvalue('image');
#fileitem = form['image']
# Test if the file was uploaded
if fileitem.image:
# strip leading path from file name to avoid
# directory traversal attacks
fn = os.path.basename(fileitem.image)
open('/uploads/' + fn, 'wb').write(fileitem.file.read())
message = 'The file "' + fn + '" was uploaded successfully'
query=f"select product_delivery_id from tbl_product_deliver order by product_delivery_id desc"
cur.execute(query)
pid=cur.fetchone()
update=f"UPDATE `tbl_product_deliver` SET `product_image`='{fn}' WHERE `product_delivery_id`='{pid}'"
cur.execute(update)
con.commit()
else:
message = 'No file was uploaded'
except Exception as e:
print(e)
print("Exception occured")
You cannot use a python script like php. Typically you have to configure an eventhandler waiting for a post-request. For doing this in python you need a framework like flask or bottle for receiving post request and instead of productimg.py you use the route you've set with this framework as action in html.
Your FieldStorage object is called without arguments, so you create an empty Fieldstorge object with no data.
A FieldStorage object receiving a post request looks like this:
fs= FieldStorage(fp=request.body, headers=request.headers, environ={'REQUEST_METHOD':'POST', 'CONTENT_TYPE':request.headers['Content-Type'], })
However ensure you solved issue 1 before doing issue 2.
With bottle use this python code:
from bottle import post, request, run
#post('/upload')
def getImage():
#printing the raw data
print(request.body)
#insert your code here
run(host='localhost', port=8080)
and change in html:
action="http://localhost:8080/upload
Good luck
I am using python and flask to make a web app. I am new to it, but have gotten most of what I am trying to accomplish done. Where I am stuck, is that I have a label whose value is a python variable( {{id}} ) This id is the id of a row I need to update in a sqlite database. My code is below. when I click the approve button, it takes me to a route which does the update query, but I have no way to pass the {{id}} with it. This would have been much easier if I could have just used javascript for the update query, but everything I've found using javascript, is for web sql, not sqlite, even though some of them say they are for sqlite.
</script>
<table border='1' align="center">
{% for post in posts %}
<tr>
<td>
<label>{{post.id}}</label>
<h1 id ='grill1'>{{post.photoName}}</h1>
<span>
<img id = 'photo1' src='{{post.photo}}' alt="Smiley face" height="200" width="200">
</span><br>
<h5 id ='blurb1'>
{{post.blurb}}
</h5>
<br>
<div style=" padding:10px; text-align:center;">
<input type="button" value="Approve" name="approve" onclick="window.location='/approve;">
<input type="button" value="Deny" onclick="window.location='/deny';"><br>
</div>
</td>
</tr>
{% endfor %}
</table>
Why not just do:
...
<input type="button" value="Approve" name="approve" onclick="window.location='/approve/{{post.id}};">
<input type="button" value="Deny" onclick="window.location='/deny/{{post.id}}';">
...
Then your flask route for approve and / or deny can just take a parameter for the post to approve or deny. i.e.:
#app.route("/approve/<int:post_id>")
def approve(post_id):
"""approve this post!"""
I have tried reading the docs for Bottle, however, I am still unsure about how static file serving works. I have an index.tpl file, and within it it has a css file attached to it, and it works. However, I was reading that Bottle does not automatically serve css files, which can't be true if the page loads correctly.
I have, however, run into speed issues when requesting the page. Is that because I didn't use the return static_file(params go here)? If someone could clear up how they work, and how they are used when loading the page, it would be great.
Server code:
from Bottle import route,run,template,request,static_file
#route('/')
def home():
return template('Templates/index',name=request.environ.get('REMOTE_ADDR'))
run(host='Work-PC',port=9999,debug=True)
Index:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="content-type"
content="text/html; charset=ISO-8859-1">
<title>index</title>
<link type="text/css"
href="cssfiles/mainpagecss.css"
rel="stylesheet">
</head>
<body>
<table
style="width: 100%; text-align: left; margin-left: auto; margin-right: auto;"
border="0" cellpadding="2" cellspacing="2">
<tbody>
<tr>
<td>
<h1><span class="headertext">
<center>Network
Website</center>
</span></h1>
</td>
</tr>
</tbody>
</table>
%if name!='none':
<p align="right">signed in as: {{name}}</p>
%else:
pass
%end
<br>
<table style="text-align: left; width: 100%;" border="0" cellpadding="2"
cellspacing="2">
<tbody>
<tr>
<td>
<table style="text-align: left; width: 100%;" border="0"
cellpadding="2" cellspacing="2">
<tbody>
<tr>
<td style="width: 15%; vertical-align: top;">
<table style="text-align: left; width: 100%;" border="1"
cellpadding="2" cellspacing="2">
<tbody>
<tr>
<td>Home<br>
<span class="important">Teamspeak Download</span><br>
<span class="important">Teamspeak Information</span></td>
</tr>
</tbody>
</table>
</td>
<td style="vertical-align: top;">
<table style="text-align: left; width: 100%;" border="1"
cellpadding="2" cellspacing="2">
<tbody>
<tr>
<td>
<h1><span style="font-weight: bold;">Network Website</span></h1>
To find all of the needed information relating to the network's social
capabilities, please refer to the links in the side bar.</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</body>
</html>
To serve static files using bottle you'll need to use the provided static_file function and add a few additional routes. The following routes direct the static file requests and ensure that only files with the correct file extension are accessed.
from bottle import get, static_file
# Static Routes
#get("/static/css/<filepath:re:.*\.css>")
def css(filepath):
return static_file(filepath, root="static/css")
#get("/static/font/<filepath:re:.*\.(eot|otf|svg|ttf|woff|woff2?)>")
def font(filepath):
return static_file(filepath, root="static/font")
#get("/static/img/<filepath:re:.*\.(jpg|png|gif|ico|svg)>")
def img(filepath):
return static_file(filepath, root="static/img")
#get("/static/js/<filepath:re:.*\.js>")
def js(filepath):
return static_file(filepath, root="static/js")
Now in your html, you can reference a file like so:
<link type="text/css" href="/static/css/main.css" rel="stylesheet">
Directory layout:
`--static
| `--css
| `--fonts
| `--img
| `--js
Just providing an answer here because a number of my students have used this code in an assignment and I have a bit of a concern about the solution.
The standard way to serve static files in Bottle is in the documentation:
from bottle import static_file
#route('/static/<filepath:path>')
def server_static(filepath):
return static_file(filepath, root='/path/to/your/static/files')
in this way, all of the files below your static folder are served from a URL starting with /static. In your HTML, you need to reference the full URL path for the resource, eg:
<link rel='stylesheet' type='text/css' href='/static/css/style.css'>
The answer from Sanketh makes it so that any reference to an image, css file etc anywhere in the URL space is served from a given folder inside the static folder. So /foo/bar/baz/picture.jpg and /picture.jpg would both be served from static/images/picture.jpg. This means that you don't need to worry about getting the path right in your HTML code and you can always use relative filenames (ie. just src="picture.jpg").
The problem with this approach comes when you try to deploy your application. In a production environment you want the static resources to be served by a web server like nginx, not by your Bottle application. To enable this, they should all be served from a single part of the URL space, eg. /static. If your code is littered with relative filenames, it won't translate easily to this model.
So, I'd advise using the three line solution from the Bottle tutorial rather than the more complex solution listed on this page. It's simpler code (so less likely to be buggy) and it allows you to seamlessly move to a production environment without code changes.
As indicated in the documentation, you should serve static files using the static function and css is a static file. The static function handles security and some other function which you can find out from the source. The path argument to the static function should point to the directory wherever you store the css files
Rather than use regular expression matching for serving files as in Sanketh's answer, I'd prefer not to modify my templates and provide a path to the static files explicitly, as in:
<script src="{{ get_url('static', filename='js/bootstrap.min.js') }}"></script>
You can do this simply by replacing the <filename> in the static route decorator with one of type :path - like so:
#app.route('/static/<filename:path>', name='static')
def serve_static(filename):
return static_file(filename, root=config.STATIC_PATH)
The :path matches an entire file path in a non-greedy way so you don't have to worry about changing templates when switching to production - just keep everything in the same relative folder structure.
I've used Sanketh's template in the past but over time condensed it to an extension agnostic function. You just have to add extension-folder mappings in the ext_map dictionary. It defaults to static/ folder if an extension is not mapped explicitly.
import os.path
# Static Routes
#get('/<filename>')
def serve_static_file(filename):
ext = os.path.splitext(filename)[1][1:]
ext_map = {'image':['png','gif','jpg','ico'],'js':['js']}
sub_folder = next((k for k, v in ext_map.items() if ext in v),'')
return static_file(filename, root='static/'+sub_folder)