user9724045
user9724045

Reputation:

In Flask, how can I generate a dynamic URL upon button click?

For example, now if I have two buttons in a form element, when you click on either one of them, you'll be directed to the corresponding profile.

<form action="{{ url_for('getProfile') }}" method="post">
    <button type="submit" name="submit" value="profile1"> View Profile</button>
    <button type="submit" name="submit" value="profile2"> View Profile</button>
</form>

In my apprunner.py, I have

 @app.route('/profile', methods=['POST'])
 def getProfile():
       if request.form['submit'] = 'profile1':
            return render_template("profile1.html")
       else if request.form['submit'] = 'profile2':
            return render_template("profile2.html")

However, my problem is when I click on either button, the url will always be something like "127.0.0.1:5000/profile". But, I want it to look like "http://127.0.0.1:5000/profile1" or "http://127.0.0.1:5000/profile2".

I have looked for solution on how to generate dynamic URL online, but none of them works for button click.

Thanks in advance!

Upvotes: 2

Views: 6927

Answers (1)

bluesmonk
bluesmonk

Reputation: 1286

@app.route('/profile<int:user>')                                                                                                   
def profile(user):                                                                                                             
    print(user)

You can test it on a REPL:

import flask
app = flask.Flask(__name__)

@app.route('/profile<int:user>')
def profile(user):
    print(user)

ctx = app.test_request_context()
ctx.push()

flask.url_for('.profile', user=1)
'/profile1'

EDIT:

how you pass the user parameter to your new route depends on what you need. If you need hardcoded routes for profile1 and profile2 you can pass user=1 and user=2 respectively. If you want to generate those links programatically, depends on how these profiles are stored.

Otherwise you could redirect instead of render_template, to the url_for with the parsed element in the request object. This means having two routes

@app.route('/profile<int:user>')
def profile_pretty(user):
    print(user)

@app.route('/profile', methods=['POST'])
def getProfile():
      if request.form['submit'] = 'profile1':
           return redirect(url_for('.profile_pretty', user=1))
       else if request.form['submit'] = 'profile2':
            return redirect(url_for('.profile_pretty', user=2))

caveat: This would make your routes look like you want, but this is inefficient as it generates a new request each time, just to make your urls the way you want. At this point it's safe to ask why do you want to have dynamically generated routes for static content.


As explained in http://exploreflask.com/en/latest/views.html#url-converters

When you define a route in Flask, you can specify parts of it that will be converted into Python variables and passed to the view function.

@app.route('/user/<username>')
def profile(username):
    pass

Whatever is in the part of the URL labeled will get passed to the view as the username argument. You can also specify a converter to filter the variable before it’s passed to the view.

@app.route('/user/id/<int:user_id>')
def profile(user_id):
    pass

In this code block, the URL http://myapp.com/user/id/Q29kZUxlc3NvbiEh will return a 404 status code – not found. This is because the part of the URL that is supposed to be an integer is actually a string.

We could have a second view that looks for a string as well. That would be called for /user/id/Q29kZUxlc3NvbiEh/ while the first would be called for /user/id/124.

Upvotes: 2

Related Questions