I use URL parameters on my site as identifiers for user data. If a user clicks one specific link on the site, these parameters will be 'none', and I try to use the following function to then send them back to the same page with the correct parameters:
Site
#app.route('/my-site/<param1>/<param2>/<param3>/<param4>', methods=['GET', 'POST'])
def site():
if param1 == 'none':
linking_data = Posts.query.filter_by(user=current_user.email).first()
return render_template('site', param1=linking_data.param1,
param2=linking_data.param2,
param3=linking_data.param3,
param4=linking_data.param4)
If the params are hard-coded, this approach works well. If I attempt to define the params as I have above however, it results in the following error:
werkzeug.routing.BuildError: Could not build url for endpoint 'site' with values ['param3', 'param4'].
Did you forget to specify values ['param1', 'param2']?
Why does it think I haven't specified the first two parameters?
You need to add the url parameters to the handler:
#app.route('/my-site/<param1>/<param2>/<param3>/<param4>', methods=['GET', 'POST'])
def site(param1=None, param2=None, param3=None, param4=None):
....
TIP: The None value outputs as string None, not none. It would be better if you updated your code to handle a string value for "none" that is not case-sensitive.
Related
im having an issues while trying to scrape the html from the current page the user is on.. Essentially the user is building a list of exercises to create a workout routine, the user is picking from a Select field, and each time they click the "add" button, it will populate a list of what they have chosen so far. Then I will grab the Text from that list and match it to what I have in my database
My issue is coming up in requests.get(url_for('createARoutine')).
requests.exceptions.MissingSchema: Invalid URL '/createaroutine': No schema supplied. Perhaps you meant http:///createaroutine?
when testing it with the direct url "http://127.0.0.1:5000/createaroutine" my error changes to werkzeug.routing.BuildError: Could not build url for endpoint 'http://127.0.0.1:5000/createaroutine'. Did you mean 'createARoutine' instead?
#app.route("/createaroutine", methods=["GET", "POST"])
def createARoutine():
"""
present form to creatine new routine, each time user clicks to
add an exercise, show the exercise to the side"""
form = CreateRoutineForm()
query = Exercises.query.all()
choices = [(c.id, c.name) for c in query]
form.exercises.choices = choices
# collect all exercises and add to routine,
# also add routine to users favorites
if request.method == 'POST':
this_html = requests.get(url_for('createARoutine')) <----ERROR
soup = BeautifulSoup(this_html, 'html.parser')
p = soup.find_all("li", {"id": "exerciseChoices"})
print(p)
return redirect(url_for('showWorkoutRoutines'))
return render_template("createRoutine.html", form=form)
`
This will not work, as requests needs a fully qualified url, including the server where you are running.
On the other hand, I'm strugling to understand why you are doing what you are doing! You are calling your own site with a get, instead of accessing the data from where you are. This is a terrible idea. You have all the data you need in the exact function. If you need the html, it's in the template. You should never, ever do what you are doing here.
I'm creating a REST API with flask_restful and want to parse the arguments coming from a PUT request. Below is the relevant code:
user_put_args = reqparse.RequestParser()
user_put_args.add_argument("user_id", type="str", help="user_id is needed for this user")
user_put_args.add_argument("spotify_username", type="str", help="Spotify username for the corresponding user_id")
user_put_args.add_argument("apple_music_username", type="str", help="Apple Music username for the corresponding user_id")
PUT function declaration:
def put(self, user_id):
args = user_put_args.parse_args()
rest of code ...
and here's the put request:
req4 = requests.put(HEROKU_BASE + "/users/" + "test1", {"spotify_username": "test_1", "apple_music_username":"something"})
print(req4.json())
The response I'm getting from the put call is:
{'message': {'spotify_username': 'Spotify username for the corresponding user_id'}}
meaning it's getting hung up on the request parse.
Any ideas on how to fix this? I'm following a guide that led me to this and my code is almost exactly the same. Thanks!
When you write type="str", reqparser tries to call the argument of type on your data and it is cannot be done with string
You shouldn't use quotes there, it will just be:
user_put_args.add_argument("spotify_username", type=str, help="Spotify username for the corresponding user_id")
This question already has answers here:
How to pass a variable between Flask pages?
(2 answers)
Create dynamic arguments for url_for in Flask
(2 answers)
Closed 3 years ago.
I'm still working on my project and now it comes to searching the data. Usually I do a post request do a route, giving the search string as parameter:
#bp.route('/search', methods=['GET', 'POST'])
def search():
if request.method == 'POST':
resp = db.session.query(MyTable).filter(MyTable.name.like('%'+request.form['search_name']+'%')).all()
... # do something else
My problem is how to implement pagination when the search results exceed the maximum amount of items per page.
Pagination itself won't be the problem when displaying data without any user action, there are several ways to do that either with Flask-paginate or via Flask-SQLAlchemy's paginate() function. But how to transfer the search string through the other pages since page is given as GET parameter with ?page=x and the search string is a POST parameter?
I somehow ran out of mind and did a lot of investigations on the net, but I only got results on doing pagination on normal data, not search results.
Could somehow give me an advice?
Many thanks in advance, regards, Thomas
I think I've got an solution for this - Flask's session class:
#app.route('/search', methods=['GET', 'POST'])
def search():
if 'name' in session['search']:
name = session['search']['name']
elif request.method == 'POST':
jboss_name = request.form.get('name')
session['search']['name'] = name
page = request.args.get('page', 1, type=int)
resp = db.session.query(MyTable)\
.filter(MyTable.name.like('%' + name + '%'))\
.paginate(page, app.config['ITEMS_PER_PAGE'], False)
next_url = url_for('search', page=resp.next_num) \
if resp.has_next else None
prev_url = url_for('search', page=resp.prev_num) \
if resp.has_prev else None
return render_template('search.html',
resp=resp,
next_url=next_url,
prev_url=prev_url)
The first call is done via POST request, sending the data to the corresponding app.route. If the session value is not set yet, it will be set at line 5. Through the session you can ensure that the original search string is taken through all pages.
This may not be highly developed but at least a working example on how to paginate through search results. Not implemented in this short snippet is clearing the session.
Regards, Thomas
I am using the following code to display the text on my browser:
from flask import Flask, jsonify, make_response, request
app = Flask(__name__)
#app.route('/api/v1.0/qanda/', methods=['GET'])
def people_api():
text = request.args.get('text'.replace('#',' ' ))
if text is None:
make_response(jsonify({'error': 'Missing text parameter'}), 400)
return text
app.run()
When I tried this:
http://127.0.0.1:5000/api/v1.0/qanda/?text=adam is my name
I got the output as:
adam is my name
But when I tried this:
http://127.0.0.1:5000/api/v1.0/qanda/?text=adam# is my name
I got the output as:
adam
I tried to replace the # symbol but it didn't work. I want to know, if I want to display my text in the browser using the above URL what I need to do? I want to display the complete text but only because of the # symbol this problem is arising, is what I suppose. Kindly, suggest me.
You can not put # as value in request parameter as like ?, &, /, &, =
If you really want to send # as in value of request parameter then you have to make it URL encoded to reach it to the server. Otherwise it will never reach to the server as you are expecting.
For encode of # you have to use %23.
As your requesting URL should be like http://127.0.0.1:5000/api/v1.0/qanda/?text=adam%23 is my name
The # symbol, like ? /, & and = has special meaning when used as part of the URL.
The # specifically is for identifying a named anchor in HTML; so the browser will not send it as part of the request.
Stick with space, or URL encode the string before you submit it.
I'm building a Python/Flask (fully ajax, without full page reloading) web application and I change the content of my master page when the sharp ("#") sign on the url change (Ben Alman, HashChange event)
I would like to catch all Error-404 to append an error page in my master page
Taking the following code in consideration
from flask import Flask, redirect
#WebServerGatewayInterface
class WSGI():
def __init__(self):
self.app = Flask(__name__)
self.app.debug = True
wsgi = WSGI()
#wsgi.app.route("/")
def Home():
return "Home"
#wsgi.app.route("/Contact")
def Contact():
return "Contact"
#wsgi.app.errorhandler(404)
def PageNotFound(error):
return "PageNotFound"
if __name__ == '__main__':
wsgi.app.run(host='127.0.0.1', port=7777)
I would like to understand why when I add a non-exising URL after the sharp ("#") sign, it isn't trapped by the errorhandler ?
E.g.
127.0.0.1:7777
#It returns "Home"
127.0.0.1:7777/Contact
#It returns "Contact"
127.0.0.1:7777/Aasdasdasdasd
#It returns "PageNotFound"
127.0.0.1:7777/#/asdsaasdasdasdas
#It returns "Home", which is not right since this URL doesn't exist
127.0.0.1:7777/#!/asdsaasdasdasdas
#It returns "Home", not ok...
127.0.0.1:7777/#!/Contact
#It returns "Home", not ok...
Everything after the # forms the fragment identifier of a resource and is handled client side. In the normal course of operation, the fragment identifier is never sent to the server:
The fragment identifier functions differently than the rest of the URI: namely, its processing is exclusively client-side with no participation from the web server
If a server is ever sent a fragment identifier in a URL, it must ignore this part of the URL. It is not part of the path, and thus Flask just sees 127.0.0.1:7777/ for all your sample URLs with a fragment.