Connect HTML page with Elasticsearch using Python flask - python

I am new to web development. I am trying to create a web page which will display index from elastic search database. I am using python flask for backend.
I see html page and python console shows index.
But I am not able to fetch index from HTML page.
I am not sure what could be the issue
Python code is as follows:
from flask import Flask,render_template, request
from elasticsearch import Elasticsearch
app = Flask(__name__)
es = Elasticsearch([{'host': 'localhost', 'port': 9200}])
doc1 = {"food": "Japanese", "spice_level": "moderate"}
doc2 = {"food": "Italian", "spice_level": "mild"}
doc3 = {"food": "Indian", "spice_level": "spicy"}
es.index(index="food", doc_type="spice_level", id=1, body=doc2)
resp = es.get(index="food", doc_type="spice_level", id=1)
print(resp)
#app.route('/')
def home():
return render_template('index.html')
app.route('/dashboard', methods=['GET', 'POST'])
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000)
HTML code is as follows:
<!DOCTYPE html>
<BODY bgcolor="cyan">
<form method="GET" action="/dashboard">
<center>
<H1>Database UI </H1> <br>
search here <input type = "text" name= "index" /> <br>
<input type = "submit">
</center>
</form>
</BODY>
</html>
Whenever I type a index name and click on search button, page gives me error as :
The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again.
I cannot see any other error then this, and it's really difficult to debug with less information about error.

why your /dashboard return 404 ?
because lack of view function to response.
app.route('/dashboard', methods=['GET', 'POST']) is invalid.
How to access /dashboard of elascticsearch ?
In your case, the simplest way is modify the index.html
<!DOCTYPE html>
<BODY bgcolor="cyan">
<form method="POST" action="http://localhost:9200/dashboard">
<center>
<H1>Database UI </H1> <br>
search here <input type = "text" name= "index" /> <br>
<input type = "submit">
</center>
</form>
</BODY>
</html>

can you use this here? for Parse data from html to python code you need to have POST inside #app.route like this:
#app.route("/", methods=['GET', 'POST'])
def home():
return render_template('index.html')
if you want to pase data into index.html you can use this here:
somedata = "variable string"
render_template('index.html', somedata=somedata)
inside index.html do {{ somedata }}
<!DOCTYPE html>
<BODY bgcolor="cyan">
<form method="POST" action="">
<center>
<H1>Database UI </H1> <br>
<!-- it will show (variable string) -->
{{ somedata }}
search here <input type = "text" name= "index" /> <br>
<input type = "submit">
</center>
</form>
</BODY>
</html>
happy codeing.

Related

URL parameter in flask app is showing up 1 form submission late

I have a flask app that I am trying to append a url parameter to after a form submission. For example, I have a date input as a form, and if I selected 2022-02-17 and pressed the button to submit, I would want the url to then append ?date=2022-02-17. My problem is the its always 1 behind. So on first submit, it is only ?date=, and then if I chose another date that isn't 2022-02-17, the url would then update to ?date=2022-02-17. I have a print to make sure the date is being correctly passed into the handler function for that page as well.
Here is a jinja snippet of the form:
<div class="container">
<p>{{ search_date }}</p>
<form action={{ url_for('past_releases', date=search_date) }} method="POST">
<div class="input-group justify-content-center">
<div class="form-outline">
<input class="form-control" type="date" id="searchdate" name="searchdate">
</div>
<button type="submit" class="btn btn-primary">
<i class="fa fa-search"></i>
</button>
</div>
</form>
</div>
and here is the python function for handling that page:
#app.route("/past-releases", methods=["GET", "POST"])
def past_releases():
"""
Search for past releases' info, based on date.
"""
search_date = None
if request.method == "GET" and request.args.get("date"):
search_date = request.args.get("date")
elif request.method == "POST":
search_date = request.form["searchdate"]
# # we use a try here for when someone might click search on the placeholder
# # date of "mm/dd/yyyy"
print(search_date)
if search_date:
try:
date_selcted = dateutil.parser.parse(search_date).strftime("%B %d, %Y")
except ParserError:
return render_template("past_releases.jinja")
pipelines_and_tasks = get_pipeline_runs_by_date(search_date)
return render_template(
"past_releases.jinja",
date_selected=date_selcted,
pipelines_and_tasks=pipelines_and_tasks,
search_date=search_date,
)
return render_template("past_releases.jinja")
I think you should replace the "method" parameter of the form with the GET method. The parameter in url_for is then no longer required. The selected date is automatically added as a URL parameter when the form is submitted.
In the query using request.args, it is also possible to add a standard parameter as the second argument and, specifying the parameter name type, a function to convert the parameter to a date.
The example below illustrates the described possibility.
Flask (app.py)
from datetime import date
from flask import Flask, render_template, request
app = Flask(__name__)
#app.route('/search')
def search():
search_date = request.args.get(
'search-date',
date.today(),
type=date.fromisoformat
)
# Your filter function here.
return render_template('search.html', **locals())
HTML (templates/search.html)
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Search</title>
</head>
<body>
<form method="get">
<input type="date" name="search-date" value="{{search_date.isoformat()}}" />
<input type="submit" />
</form>
</body>
</html>

Not getting the search result

I just start learning Flask and i'm trying to use a simple search form on my news headline site but when i submit the search it seems that it's not working, i'm using a simple flask get request
Here is my code:
import feedparser
from flask import Flask
from flask import render_template
from flask import request
app = Flask(__name__)
rss_feed = {'wsj': "https://feeds.a.dj.com/rss/RSSWSJD.xml",
'cnbc': "https://www.cnbc.com/id/100003114/device/rss/rss.html",
'washington_post': "http://feeds.washingtonpost.com/rss/politics?itid=lk_inline_manual_2"}
#app.route("/")
def get_news():
query = request.args.get('publication')
if not query or query.lower not in rss_feed:
publication = 'wsj'
else:
publication = query.lower
feed = feedparser.parse(rss_feed[publication])
return render_template("home.html", articles=feed['entries'])
if __name__ == "__main__":
app.run(port=5000, debug=True)
and my html code:
<html>
<head>
<title>Headlines</title>
</head>
<body>
<h1>Headlines</h1>
<form>
<input type="text" name="publication" placeholder="search">
<input type="submit" value="Submit">
</form>
{% for article in articles %}
<b>{{article.title}}</b><br />
<i>{{ article.published }}</i><br />
<p>{{ article.summary }}</p>
<hr />
{% endfor %}
</body>
</html>
Now when i submit a search for 'cnbc' it still display the result for 'wsj' what wrong with my code?
I add 4 different notes in the code as comment, please have a look in the Glossary.
Here is the solution:
Python file, here is where the error occur, long stoyry short your if statement was always returning True, hence the publication variable was set as 'wsj
import feedparser
from flask import render_template, request, Flask
# Note 1
app = Flask(__name__)
rss_feed = {'wsj': "https://feeds.a.dj.com/rss/RSSWSJD.xml",
'cnbc': "https://www.cnbc.com/id/100003114/device/rss/rss.html",
'washington_post': "http://feeds.washingtonpost.com/rss/politics?itid=lk_inline_manual_2"}
#app.route("/")
def get_news():
if request.args.get('publication'):
query = request.args.get('publication').lower() # Note 2
print(f'Query is : {query}') # Note 4
if not query or query not in rss_feed: # Note 3
print('Publication is wsj') # Note 4
publication = 'wsj'
else:
print('Publication is the query entry') # Note 4
publication = query
feed = feedparser.parse(rss_feed[publication])
return render_template("view.html", articles=feed['entries'])
return render_template("view.html")
if __name__ == "__main__":
app.run(port=5000, debug=True)
HTML File
<html>
<head>
<title>Headlines</title>
</head>
<body>
<h1>Headlines</h1>
<!-- Note 5 -->
<form method="GET">
<input type="text" name="publication" placeholder="search">
<input type="submit" value="Submit">
</form>
{% for article in articles %}
<b>{{article.title}}</b><br />
<i>{{ article.published }}</i><br />
<p>{{ article.summary }}</p>
<hr />
{% endfor %}
</body>
</html>
NOTES GLOSSARY
Note 1: Have the imports from the same package in the same line
Note 2: Rather then check the query if is lower is better to turn it lower already in the variable as I did.
Note 3: Here is where the real issue was. This statement was always True hence setting the 'publication' variable as 'wsj'. This is because of add 'query.lower' not in rss_feed which obsiously it wasn't. And by the way you should have done it 'query.lower()'
Note 4: Just a reminder to How to find and troubleshot your code.The print() function is the first thing to learn in python and is the most usefull tool for this matter. This is how I found the error in less then 5 minutes because I let the code 'Speak' through the terminal.
Note 5: Few suggestion here, first add a method='GET' (not neccessary) just for readability. Then indent better the HTML file as it was all messed around.
Another solution that may be slightly clearer is this:
#app.route("/")
def get_news():
if request.args.get('publication'):
query = request.args.get('publication').lower()
if not query or query not in rss_feed:
publication = 'wsj'
feed = feedparser.parse(rss_feed[publication])
return render_template("view.html", articles=feed['entries'])
publication = query
feed = feedparser.parse(rss_feed[publication])
return render_template("view.html", articles=feed['entries'])
return render_template("view.html")

Flask, Passing User Entered Data Between Views

Problem transferring variables across views I tried using sessions and could not get the connection to work. Say I have two pages, a home and page2. I have a flask app that will take user input from the home and print out input on page2.
For example, if you start my app, you will see this as the home page:
This part works fine, I am able to enter a value.
What I want to happen next, is after you click submit, page2 is generated showing what was just entered:
Whatever string value was entered on home should show up in the highlighted portion.
I have the following app.py file:
from flask import Flask, render_template, request, session
app = Flask(__name__)
#app.route('/', methods=['GET', 'POST'])
def home():
stringval = ''
if request.method == 'POST' and 'stringval' in request.form:
stringval = request.form.get('stringval')
session["stringvalue_topass"] = stringval
return render_template('page2.html', stringval = stringval)
return render_template("home.html")
#app.route('/page2', methods=['GET', 'POST'])
def page2():
stringvalue_get = session.get('stringvalue_topass')
return render_template('page2.html', stringvalue_get = stringvalue_get)
if __name__ == '__main__':
app.run(debug=True)
The following home.html:
<!doctype html>
<h1>Enter Value </h1>
<div class="main">
<form class="pure-form" method="POST" action="/page2">
stringval:<br>
<input type="text" name="stringval"><br>
<button type="submit" class="pure-button pure-button-primary" value="Submit">Submit!</button>
</form>
</div>
</body>
And the following page2.html
<!doctype html>
<h1>You have selected </h1>
<div class="main">
{% if stringvalue_get %}
<pre>
{% print(stringvalue_get) %}
</pre>
{% endif %}
</div>
</body>
Okay, there are a few issues here. Firstly, the action attribute of your form in home.html is set to "/page2". This means that when the form is submitted, the POST request is going to the /page2 endpoint rather than to the /home endpoint, where you have written the code for handling the form submission. We can fix this by just deleting the action attribute, as this means the form will post to then endpoint that loaded it - in this case /home.
Secondly, Flask sessions cannot be used without setting a secret key to encrypt the session. This can be done by assigning a value to app.secret_key, like so:
app = Flask(__name__)
app.secret_key = b"my_secret_key"
Finally, instead of passing the string to the template like so: render_template('page2.html', stringval = stringval), (note also that this should be stringval_get = stringval), you can access the session object directly from templates already. So, in all, we can change your application code to:
app.py:
from flask import Flask, render_template, request, session
app = Flask(__name__)
app.secret_key = b"my_secret_key"
#app.route('/', methods=['GET', 'POST'])
def home():
if request.method == 'POST' and 'stringval' in request.form:
session["stringvalue_topass"] = request.form.get('stringval')
return render_template('page2.html')
return render_template("home.html")
#app.route('/page2', methods=['GET', 'POST'])
def page2():
return render_template('page2.html')
And your templates to:
home.html:
<!doctype html>
<h1>Enter Value </h1>
<div class="main">
<form class="pure-form" method="POST">
stringval:<br>
<input type="text" name="stringval"><br>
<button type="submit" class="pure-button pure-button-primary" value="Submit">Submit!</button>
</form>
</div>
</body>
page2.html:
<!doctype html>
<h1>You have selected </h1>
<div class="main">
{% if 'stringvalue_topass' in session %}
<pre>
{% print(session["stringvalue_topass"]) %}
</pre>
{% endif %}
</div>
</body>

Auto Generating SQL Scripts based on User Input using Flask, python

Problem: There is an arduous update script we run for work. It takes a lot of time to update because of security issues. We want to make sure we have edited the update script correctly/want to avoid all permission issues.
Solution: Using Flask as a front end gui to eliminate the possibility for adding the wrong value. The Flask app will guarantee correct placement of inputs into the update script by auto generating the script, so we can just copy and paste into SSMS.
The current problem I am having is aesthetics. I was able to generate a flask app using user inputs and exports a SQL script. The problem is, the sql looks horrible, here is an example of the output:
Ideally the output would be multi-line, like all current SQL scripts:
UPDATE table_name
SET ordercomplete = 1
WHERE UserName = 'testuser' and OrderID = 12345
Below are my files:
#templates home.html
<!doctype html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>SQL Auto Generate</title>
<link rel="stylesheet" href="https://unpkg.com/purecss#0.6.2/build/pure-min.css" integrity="sha384-UQiGfs9ICog+LwheBSRCt1o5cbyKIHbwjWscjemyBMT9YCUMZffs6UqUTd0hObXD" crossorigin="anonymous">
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='style.css') }}">
</head>
<h1>SQL Auto Generate</h1>
<h2>Add the following inputs, select 'Submit' to generate a script for SQL</h2>
<body>
<div class="main">
<form class="pure-form" method="POST" action="/">
UserName:<br>
<input type="text" name="UserName"><br>
OrderID:<br>
<input type="number" name="OrderID"><br>
<button type="submit" class="pure-button pure-button-primary" value="Submit">Submit</button>
</form>
</div>
<br>
<div class="main">
{% if UserName %}
<p>
{% print('''
UPDATE table_name
SET ordercomplete = 1
WHERE
UserName = {} and OrderID = {}
'''.format(UserName, OrderID)) %}
</p>
{% endif %}
</div>
</body>
# app.py
from flask import Flask, render_template, request
app = Flask(__name__)
#app.route('/', methods=['GET', 'POST'])
def index():
UserName = ''
OrderID = ''
if request.method == 'POST' and 'UserName' in request.form:
UserName = request.form.get('UserName')
OrderID = int(request.form.get('OrderID'))
return render_template("home.html", UserName=UserName, OrderID = OrderID)
if __name__ == '__main__':
app.run(debug=True)
I also uploaded to github: https://github.com/jpf5046/sqlflask
Ask: Is there a better way to create a text output with multi-line via flask?
By default, HTML ignores extra space, such as line endings. If you want to display the query exactly like you generate it, use <pre>:
<pre>
UPDATE table_name
SET ordercomplete = 1
WHERE
UserName = {{UserName}} and OrderID = {{OrderId}}
</pre>
I think you just need to add br tags in your html
{% if UserName %}
<p>UPDATE table_name <br>
SET ordercomplete = 1 <br>
WHERE <br>
UserName = {{ UserName }} and OrderID = {{ OrderID }}
</p>
{% endif %}

Flask-Sqlite posting to DB from webform

I have started just learning Flask and tried to find an answer how to post to SQLite DB from webform. So far haven't managed to get it work and bit lost with this. I manage to print values from DB based on code sample from simplypython but don't know how to add new ones from webform.
I would need to be able to address elements, open connection to the database, Insert values, save and close the connection. As far as I am aware I should add the POST method to the app.py and use request.form statement to pull the elements when submit button is pressed.
then the code should automatically display all the values on index html, which already works. could you please help me with the code I need to add to app.py file to get values added to DB and what to add to form action webform-section on html file?
index.html
<!DOCTYPE html>
<html>
<head>
<title>Flask Intro</title>
<!-- <meta name="viewport" content="width=device-width, initial-scale=1.0"> -->
</head>
<body>
<div class="container">
<h3 potsit </h3>
{% for post in posts %}
Titleotsikko: {{post.title }} <br>
Postotsikko: {{post.description}}
{% endfor %}
</div>
<div>
<form action="/????????????NOT SURE WHERE TO DIRECT" method="post">
<div>
<label for="title">title:</label>
<input type="text" id="title" />
</div>
<div>
<label for="description">description:</label>
<input type="text" id="description" />
</div>
<div class="button">
<button type="submit">Add to db</button>
</div>
</form>
</div>
</body>
</html>
app.py
from flask import Flask, render_template, request, session, g
import sqlite3
app = Flask(__name__)
#app.route('/')
def home():
g.db = sqlite3.connect("sample.db")
cur = g.db.execute('select * from posts')
posts = [dict(title=row[0], description=row[1]) for row in cur.fetchall()]
g.db.close()
return render_template("index.html", posts=posts)
if __name__=='__main__':
app.run(debug=True)
sql.py
import sqlite3
with sqlite3.connect("sample.db") as connection:
c = connection.cursor()
c.execute("DROP TABLE posts")
c.execute("CREATE TABLE posts(title TEXT, description TEXT)")
c.execute('INSERT INTO posts VALUES("Luck", "no luck.")')
EDIT
I made some changes based on the suggestion from Paul Rooney and created file called post.html, moved the form there from index.htmland added another #route on the app.py file. I believe I'm not far off but after trying to figure this out since Tuesday hoping to get it work. Unfortunately now I receive an error 405 'The method is not allowed for the requested URL.' and I'm stuck with this after trying different options.
post.html
<!DOCTYPE html>
<html>
<head>
<title>Flask post</title>
<!-- <meta name="viewport" content="width=device-width, initial-scale=1.0"> -->
</head>
<body
<div>
<form action="/post" method="post">
<div>
<label for="title">title:</label>
<input type="text" id="title" />
</div>
<div>
<label for="description">description:</label>
<input type="text" id="description" />
</div>
<div class="button">
<button type="submit">Add to db</button>
</div>
</form>
</div>
</body>
</html>
(edited) app.py
from flask import Flask, render_template, request, session, g, redirect, url_for
import sqlite3
app = Flask(__name__)
#app.route('/')
def home():
g.db = sqlite3.connect("sample.db")
cur = g.db.execute('select * from posts')
posts = [dict(title=row[0], description=row[1]) for row in cur.fetchall()]
g.db.close()
return render_template("index.html", posts=posts)
#app.route('/post', methods=['POST'])
def post():
title=request.form['title']
description=request.form['description']
print title, description
return redirect(url_for('/'))
if __name__=='__main__':
app.run(debug=True)
To answer your original question you should pick an endpoint to post your data to and use that in both your flask app and the html form action.
I suggested post in comments but it could be anything. I think you've grasped what to do here but for completeness.
The HTML
<form action="/post" method="post">
The Python Code
Add a route to handle the POSTed data.
#app.route('/post', methods=['POST'])
def post():
# Do db stuff then redirect back to index page.
pass
Edited Question
You have an indentation error in your code, which is causing the 405 error. Your post function is inside your home function. Make it more like this
app.py
from flask import Flask, render_template, request, session, g, redirect, url_for
import sqlite3
app = Flask(__name__)
#app.route('/')
def home():
g.db = sqlite3.connect("sample.db")
cur = g.db.execute('select * from posts')
posts = [dict(title=row[0], description=row[1]) for row in cur.fetchall()]
g.db.close()
return render_template("index.html", posts=posts)
# One level of indentation removed from here downwards
#app.route('/post', methods=['POST'])
def post():
title=request.form['title']
description=request.form['description']
return redirect(url_for('home'))
if __name__=='__main__':
app.run(debug=True)
After that I see a 400 Bad Request error, which stems from the fact that you don't have name parameters in your html form.
The attempt to access the title and description values in the form dict in app.py will throw a KeyError exception, as those keys will not be present without the name parameter in the html.
If you add them e.g.
...
<input type="text" id="title" name='title'/>
...
<input type="text" id="description" name='description'/>
...
Then it will run all the way through your function.
The next issue will be
redirect(url_for('/'))
instead use
redirect(url_for('home'))
home being the name of the function called for path '/'.
After that you should be good to go.

Categories