Issue
I am developing a Flask solution for the user to filter the items in a table using a drop down select list. The first page is a simple drop down list, from which the user selects a category. Upon hitting the enter button, the results page is rendered, with the list of all of the rows of the table where the category is the one selected by the user.
I do not receive any error messages, however, the results page only comes with the column headings -- no data is returned.
As this is a simple drop down box filter, I would think there would be a simple solution to this situation. I searched for relevant solutions within StackOverflow, but all of the other solutions were for much more complex situations that did not seem to be completely relevant to what I am trying to accomplish.
Here is the code I tried to implement my task:
@app.route('/search3')
def search3():
category = request.args.get('category', '')
query = Profile.query
if category:
query = query.filter_by(category=category)
profiles = query.all()
return render_template('search3.html', **locals())
@app.route('/results')
def results():
return render_template('results.html')
Here are the relevant parts of my code. Here is the table layout:
# Models
class Profile(db.Model):
id = db.Column(db.Integer, primary_key=True)
merchant = db.Column(db.String(20), unique=False, nullable=False)
cMerchantOther = db.Column(db.String(32), unique=False, nullable=False)
price = db.Column(db.Float, nullable=False)
drcr = db.Column(db.String(20), unique=False, nullable=False)
category = db.Column(db.String(20), unique=False, nullable=False)
pmtmethod = db.Column(db.String(20), unique=False, nullable=False)
updated = db.Column(db.String(20), unique=False, nullable=False)
def __repr__(self):
return f"Category : {self.category}, Price: {self.price}"
Here is the HTML page where the user selects the category by which to filter (search3.html):
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="{{url_for('static', filename = 'style/style1.css')}}" rel="stylesheet">
<title>Search</title>
</head>
<body>
<form>
<label>Select a Category</label>
<select name="category">
<option value>Select a category</option>
{% for value in ('Kitchen', 'Pay', 'Medical', 'Food',) -%}
<option value="{{ value }}" {% if value == category %}selected{% endif %}>{{ value }}</option>
{% endfor -%}
</select>
<button type="submit">Search</button>
</form>
Here is the code for the results page (results.html):
<!DOCTYPE html>
<html>
<head>
<title>Search Results</title>
<link href="{{url_for('static', filename = 'style/style1.css')}}" rel="stylesheet">
</head>
<body>
<table>
<thead>
<th>ID</th>
<th>Merchant</th>
<th>Other</th>
<th>Price</th>
<th>DrCr</th>
<th>Category</th>
<th>Payment Method</th>
<th>Date</th>
<th>#</th>
</thead>
{% for data in ProfileSearch %}
<tbody>
<td>{{data.id}}</td>
<td>{{data.merchant}}</td>
<td>{{data.cMerchantOther}}</td>
<td>{{data.price}}</td>
<td>{{data.drcr}}</td>
<td>{{data.category}}</td>
<td>{{data.pmtmethod}}</td>
<td>{{data.updated}}</td>
<td><a href="/delete/{{data.id}}" type="button">Delete</a></td>
</tbody>
{% endfor%}
</table>
</body>
</html>
Solution
You don't provide a clear method
attribute to submit the form. Either GET or POST should be specified. If nothing is specified, GET is chosen. However, by querying request.form
you expect an input via POST, which does not exist.
The following example sends the form data via GET. The optional input sent as URL parameters is requested using request.args
.
@app.route('/search')
def search():
category = request.args.get('category', '')
query = Profile.query
if category:
query = query.filter_by(category=category)
profiles = query.all()
return render_template('search.html', **locals())
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Search</title>
</head>
<body>
<form>
<label>Select a Category</label>
<select name="category">
<option value>Select a category</option>
{% for value in ('Kitchen', 'Pay', 'Medical', 'Food',) -%}
<option value="{{ value }}" {% if value == category %}selected{% endif %}>{{ value }}</option>
{% endfor -%}
</select>
<button type="submit">Search</button>
</form>
<table>
<thead>
<tr>
<th>ID</th>
<th>Merchant</th>
<th>Other</th>
<th>Price</th>
<th>DrCr</th>
<th>Category</th>
<th>Payment Method</th>
<th>Date</th>
<th>#</th>
</tr>
</thead>
<tbody>
{% for data in profiles -%}
<tr>
<td>{{data.id}}</td>
<td>{{data.merchant}}</td>
<td>{{data.cMerchantOther}}</td>
<td>{{data.price}}</td>
<td>{{data.drcr}}</td>
<td>{{data.category}}</td>
<td>{{data.pmtmethod}}</td>
<td>{{data.updated}}</td>
<td><a href="/delete/{{data.id}}" type="button">Delete</a></td>
</tr>
{% endfor -%}
</tbody>
</table>
</body>
</html>
If you want to use a POST request and present the results on another page, the following code is a possible solution. In this case, post is defined as a method and a separate route is declared to receive the data.
@app.route('/search')
def index():
return render_template('search.html')
@app.post('/results')
def results():
category = request.form.get('category', '')
query = Profile.query
if category:
query = query.filter_by(category=category)
profiles = query.all()
return render_template('results.html', **locals())
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="{{url_for('static', filename = 'style/style1.css')}}" rel="stylesheet">
<title>Search</title>
</head>
<body>
<form action="{{ url_for('.results') }}" method="post">
<label>Select a Category</label>
<select name="category">
<option value>Choose one</option>
{% for value in ('Kitchen', 'Pay', 'Medical', 'Food',) -%}
<option value="{{ value }}">{{ value }}</option>
{% endfor -%}
</select>
<button type="submit">Search</button>
</form>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Search Results</title>
<link href="{{url_for('static', filename = 'style/style1.css')}}" rel="stylesheet">
</head>
<body>
<table>
<thead>
<tr>
<th>ID</th>
<th>Merchant</th>
<th>Other</th>
<th>Price</th>
<th>DrCr</th>
<th>Category</th>
<th>Payment Method</th>
<th>Date</th>
<th>#</th>
</tr>
</thead>
<tbody>
{% for data in profiles %}
<tr>
<td>{{data.id}}</td>
<td>{{data.merchant}}</td>
<td>{{data.cMerchantOther}}</td>
<td>{{data.price}}</td>
<td>{{data.drcr}}</td>
<td>{{data.category}}</td>
<td>{{data.pmtmethod}}</td>
<td>{{data.updated}}</td>
<td><a href="/delete/{{data.id}}" type="button">Delete</a></td>
</tr>
{% endfor%}
</tbody>
</table>
</body>
</html>
Answered By - Detlef
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.