Getting <generator object inner at 0x7f2ad7874050> error Flask - python

Getting this error <generator object inner at 0x7f2ad7874050> on my page when I try to run the folliwhing flask function (route):
#app.route('/siteON', methods=['GET', 'POST'])
def siteon():
def inner():
proc = subprocess.Popen(
['/root/site_toggle/flaskr/testON.sh'],
shell=True,
stdout=subprocess.PIPE
)
for line in iter(proc.stdout.readline,''):
time.sleep(1)
yield line.rstrip() + '<br/>\n'
output = inner ()
return render_template('layout.html', ON_output=output)
here is my html
<input type="button" name="lien2" value="Turn OFF site"
onclick="self.location.href='http://10.10.10.30:5000/siteOFF'" style="background-color:#1ab171"
style="color:white; font-weight:bold"onclick>
<p>{{ ON_output }}</p>
I am looking to run button and display the output on the same flask page without streaming the output on a new page.
Thanks in advance for your help

That's not an error, that's the string representation of a generator object, which is what yield results in your function creating.
You seem to be trying to use a generator and sleep() to make things appear over time in your page, but that's not how templates work - they're a one-and-done kind of rendering. If you want things to appear over time in your page you're probably going to have to use some form of client-side javascript to fetch new updates.

Related

Python Flask Application not redirecting

I'm trying to create a list of clickable links to external URLs. My HTML file looks like this
<ul>
{% for post in posts %}
<li><a href={{url_for('go_to_reddit', url=post.url)}}>{{ post.title }}</a></li>
{% endfor %}
</ul>
and the python file like this
#app.route('/redirect/"<url>"')
def go_to_reddit(url):
print("Redirecting to ", url)
return redirect(url)
I keep getting the following error whenever I press on one of the links
Not Found
The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again.
I know it's not reaching the redirect function even though it hits the URL since my console doesn't print anything.
I don't think you can have quotes in a route parameter i.e. #app.route('/redirect/"<url>"') should be #app.route('/redirect/<url>') . Put another way, try dropping the quote around <url>
If you can't have quotes in a url parameter and you need to pass a complete url, then you should consider passing it as a query parameter e.g. /redirect/?link=post.url. Then in your handler for the route, you will do url = request.values.get('link', None)

Django Running Python Function to Update Page w/o Refresh

I am making a website that tracks population statistics. The site needs to update about every 5 seconds with the latest information.
Here is the relevant code for displaying the pandas df on the page (in a file titled "home.html"):
{% block content %}
<h1>Population Tracker</h1>
{% for index, label,data in pop_df.itertuples %}
<div class = "row__data">
<p>{{label}}: {{data}}</p>
</div>
{% endfor %}
{% endblock content %}
Here is the code for my scraper (in a separate file called "scraper.py")
class Scraper():
def __init__(self):
self.URL = "https://countrymeters.info/en/Japan"
def scrape(self):
"Scrapes the population data once"
page = requests.get(self.URL)
soup = BeautifulSoup(page.content,'html.parser')
data_div = soup.find_all('div',class_="data_div")[0]
table = data_div.findAll("table")[0]
tr = table.findAll('tr')
labels = []
numbers = []
for n, i in enumerate(tr):
number = i.findAll('td',{"class":"counter"})[0].text # numbers
label = i.findAll('td',{"class":"data_name"})[0].text # labels
labels.append(label)
numbers.append(number)
pop_df = pd.DataFrame(
{
'Labels':labels,
'Data': numbers
}
)
return pop_df
In my views.py file, here is what I have done:
from django.shortcuts import render
from bsoup_tracker.scraper import Scraper
scraper = Scraper()
df = scraper.scrape()
def home(request):
context = {
'pop_df':df
}
return render(request,'tracker/home.html',context)
Basically, I would like to be able to call the render onto my home.html page every 5 seconds to reupdate the page, without needing refreshes. I have tried to look elsewhere and see that Ajax could help; however I do not know where to begin.
Instead of using Django to render the page, create API and call every after 5 minutes and after getting the results, refresh the HTML content using JavaScript.
If you need more information please let me know.
AJAX stands for "asynchronous JavaScript and XML" so as you thought that would be the way to go if you need to fetch data from your backend and refresh the interface.
The base component to do so in the XmlHttpRequest object in vanilla JavaScript. However, I strongly advice using a library like jQuery, to me it's really easier to use. With vanilla JS, jQuery or any other library you choose, you can modify DOM to expose data you got from your backend. The major drawback is that you will probably end up with not so clean code which will get harder and harder to maintain.
Nowadays the most common solution would be to use djangorestframework (not mandatory, you can also use django's JsonResponse) to create an API along with a nodeJS framework like React or VueJS to create your interface using API's data. That way you will have a lot more control on your interface.
Finally, if you need to have some sort of live website (pulling data and refreshing interface every 5 seconds seems like a poor design pattern to me), you should use websockets for your frontend and ASGI in backend (instead of WSGI). Django-channel is a nice package to do so, but just Google "django websockets" and you will find a lot of documentation.

Is it possible to embed and run Python code on HTML?

I'm trying to run a Python script with HTML code embedded and it's not working. I'm want to execute a Python script and at the same time render the HTML which will be printed by the script.
app.py:
#!/usr/bin/python2.6
from flask import Flask, render_template
app = Flask(__name__)
#app.route('/')
def index():
return render_template('index.html')
#app.route('/briefing')
def briefing():
return render_template('briefing.html')
#app.route('/briefing/code')
def app_code():
return render_template('app_code.py')
if __name__ == '__main__':
app.run(debug=True)
app_code.py:
http://i.stack.imgur.com/sIFFJ.png
When I access http://127.0.0.1:5000/briefing/code the result is http://i.stack.imgur.com/iEKv2.png.
I know that what is happening is that I'm rendering as HTML and therefore the Python code inside of the file is not being interpreted.
How can I run the app_code.py and at the same time, render the HTML from it?
You are mixing up a lot of things, I saw the first post of the question took me a while to figure out what you are trying to do.
The idea that you seem to need to grasp is that, you'll need to prepare the model in Python first (e.g. a string, an object, a dict etc with the data you want), and then inject it into a template to be rendered (as opposed to printing out what you want to see in the HTML output)
If you want to display the output from a subprocess.call into an HTML page, here's what you should do:
Get the output from subprocess in a string format
Create a HTML template to display it in
Make Flask call the subprocess, render the template and return the HTTP response
app.py:
#!/usr/bin/python2.6
import subprocess
from flask import Flask, render_template
app = Flask(__name__)
def get_data():
"""
Return a string that is the output from subprocess
"""
# There is a link above on how to do this, but here's my attempt
# I think this will work for your Python 2.6
p = subprocess.Popen(["tree", "/your/path"], stdout=subprocess.PIPE)
out, err = p.communicate()
return out
#app.route('/')
def index():
return render_template('subprocess.html', subprocess_output=get_data())
if __name__ == '__main__':
app.run(debug=True)
subprocess.html:
<html>
<head>
<title>Subprocess result</title>
</head>
<body>
<h1>Subprocess Result</h1>
{{ subprocess_output }}
</body>
</html>
In the above template, {{ subprocess_output }} will be replaced by the value you pass from your Flask view before the resulting HTML page is sent to the browser.
How to pass more than one value
You can either render_template('page.html', value_1='something 1', value_2='something 2')
and in the template: {{ value_1 }} and {{ value_2}}
Or you can pass a dict called e.g. result:
render_template('page.html, result={'value_1': 'something 1', 'value_2': 'something 2'})
and in the template {{ result.value_1 }} and {{ result.value_2 }}

django views.py to call another python script

I'm new to Django. Please help me with the below.
I have a User form who provides URL1 and URL2.. These URLs need to be passed to another Python script[redirects.py] which will do the Validation to check whether they are in a valid URL format and return the Message to the User.
Now my question is how to write my views.py so as to get this done. I got to know that we can import the redirects.py in my views.py and call it. But I'm not aware of how to print the messages in my browser. Please help. Let me know if any more info is required.
def shortcuts_process(request):
print request.POST
return HttpResponse("Source is %s\nDestination is %s" % (request.POST['source'],request.POST['destination']))
Update :
This is my script overview. I have got a python script[redirects.py] in my system which accepts Source and Destination URLs. Once accepted, it validates whether they are in URL format, then takes backup, then add them into .htaccess and display the line added to the file. While doing all this, it keeps intimating the User with the information on whats happening in the script.
Now I have made the django to create a web portal which provides the User to input source and Destination. Now i want to call the script from views.py and print all those redirects.py Script output in User's web browser.
Please help me in getting this, I have spent an entire day looking for this answer. Thanks.
Update 2:
Please let me know why the below is not getting displayed in my browser
From views.py
def shortcuts_process(request):
if 'source' in request.POST and 'destination' in request.POST and request.POST['source'] and request.POST['destination']:
src=request.POST['source']
desti= request.POST['destination']
my_result=process_input(src,desti)
return render_to_response('results.html',{'result': my_result}
From results.html :
<html>
<head>
This is the result page to User
</head>
<body>
<ul>
{% for each_line in result %}
<p>{{ each_line }}</p>
{% endfor %}
</ul>
<p>
I'm supposed to be printed</p>
</body>
</html>
From browser output :
This is the result page to User
I'm supposed to be printed
From Linux prompt :
[10/Jun/2013 04:41:11] "GET /redirects HTTP/1.1" 200 727 [10/Jun/2013
04:41:14] "GET /choice?selection=shortcuts HTTP/1.1" 200 817 The URL
is not in the right format The URL is not in the right format
[10/Jun/2013 04:41:18] "POST /shortcuts.conf HTTP/1.1" 200 125
So now my question, why the Message The URL is not in the right format is not getting displayed on browser rather it displays in Linux prompt. Please help. Thanks
Whatever string you want to display in the browser, return it in the HttpResponse.
You could try something like:
#validation.py
def validate(url1, url2):
# perform validation here
if valid:
return "urls are valid"
else:
return "urls are invalid"
#views.py
def shortcuts_process(request):
print request.POST
url1 = request.POST.get('url1', '')
url2 = request.POST.get('url2'. '')
return HttpResponse(validate(url1, url2))
Hope that helps.
For form validation, please refer to Chapter 7 in the django book (http://www.djangobook.com/en/2.0/chapter07.html)
Thanks all.. I managed to get the answer.
Rather having my function validate_url to print the values, changing it to return has given me the desired result.
I'm being so dumb to find this out. Failure is the stepping stone of Success !! :O)

How to run a Python script in a web page

I'm very new to Python. I just know what Python is.
I have created the below code (in Python IDLE):
print "Hi Welcome to Python test page\n";
print "Now it will show a calculation";
print "30+2=";
print 30+2;
Then I saved this page in my localhost as index.py
I run the script using
http://localhost/index.py
But it does not show the executed Python script. Instead, it showed the above code as HTML. Where is the problem? How can I run a Python file in a web page?
In order for your code to show, you need several things:
Firstly, there needs to be a server that handles HTTP requests. At the moment you are just opening a file with Firefox on your local hard drive. A server like Apache or something similar is required.
Secondly, presuming that you now have a server that serves the files, you will also need something that interprets the code as Python code for the server. For Python users the go to solution is nowadays mod_wsgi. But for simpler cases you could stick with CGI (more info here), but if you want to produce web pages easily, you should go with a existing Python web framework like Django.
Setting this up can be quite the hassle, so be prepared.
As others have pointed out, there are many web frameworks for Python.
But, seeing as you are just getting started with Python, a simple CGI script might be more appropriate:
Rename your script to index.cgi. You also need to execute chmod +x index.cgi to give it execution privileges.
Add these 2 lines in the beginning of the file:
#!/usr/bin/python
print('Content-type: text/html\r\n\r')
After this the Python code should run just like in terminal, except the output goes to the browser. When you get that working, you can use the cgi module to get data back from the browser.
Note: this assumes that your webserver is running Linux. For Windows, #!/Python26/python might work instead.
Using the Flask library in Python, you can achieve that.
Remember to store your HTML page to a folder named "templates" inside where you are running your Python script.
So your folder would look like
templates (folder which would contain your HTML file)
your Python script
This is a small example of your Python script. This simply checks for plagiarism.
from flask import Flask
from flask import request
from flask import render_template
import stringComparison
app = Flask(__name__)
#app.route('/')
def my_form():
return render_template("my-form.html") # This should be the name of your HTML file
#app.route('/', methods=['POST'])
def my_form_post():
text1 = request.form['text1']
text2 = request.form['text2']
plagiarismPercent = stringComparison.extremelySimplePlagiarismChecker(text1,text2)
if plagiarismPercent > 50 :
return "<h1>Plagiarism Detected !</h1>"
else :
return "<h1>No Plagiarism Detected !</h1>"
if __name__ == '__main__':
app.run()
This a small template of HTML file that is used:
<!DOCTYPE html>
<html lang="en">
<body>
<h1>Enter the texts to be compared</h1>
<form action="." method="POST">
<input type="text" name="text1">
<input type="text" name="text2">
<input type="submit" name="my-form" value="Check !">
</form>
</body>
</html>
This is a small little way through which you can achieve a simple task of comparing two strings and which can be easily changed to suit your requirements.
If you are using your own computer, install a software called XAMPP (or WAMP either works). This is basically a website server that only runs on your computer. Then, once it is installed, go to the xampp folder and double click the htdocs folder. Now you
need to create an HTML file (I'm going to call it runpython.html). (Remember to move the Python file to htdocs as well.)
Add in this to your HTML body (and inputs as necessary).
<form action = "file_name.py" method = "POST">
<input type = "submit" value = "Run the Program!!!">
</form>
Now, in the Python file, we are basically going to be printing out HTML code.
# We will need a comment here depending on your server. It is basically telling the server where your python.exe is in order to interpret the language. The server is too lazy to do it itself.
import cgitb
import cgi
cgitb.enable() # This will show any errors on your webpage
inputs = cgi.FieldStorage() # REMEMBER: We do not have inputs, simply a button to run the program. In order to get inputs, give each one a name and call it by inputs['insert_name']
print "Content-type: text/html" # We are using HTML, so we need to tell the server
print # Just do it because it is in the tutorial :P
print "<title> MyPythonWebpage </title>"
print "Whatever you would like to print goes here, preferably in between tags to make it look nice"
Well, the OP didn't say server or client side, so I will just leave this here in case someone like me is looking for client side:
Skulpt is a implementation of Python to run at client side. Very interesting, no plugin required, just simple JavaScript code.
With your current requirement, this would work:
def start_html():
return '<html>'
def end_html():
return '</html>'
def print_html(text):
text = str(text)
text = text.replace('\n', '<br>')
return '<p>' + str(text) + '</p>'
if __name__ == '__main__':
webpage_data = start_html()
webpage_data += print_html("Hi Welcome to Python test page\n")
webpage_data += fd.write(print_html("Now it will show a calculation"))
webpage_data += print_html("30+2=")
webpage_data += print_html(30+2)
webpage_data += end_html()
with open('index.html', 'w') as fd: fd.write(webpage_data)
Open the index.html file, and you will see what you want.

Categories

Resources