5

I am currently getting the following error when I run my flask code:

flask.debughelpers.FormDataRoutingRedirect - FormDataRoutingRedirect: A request was sent to this URL (http://localhost:5000/login) but a redirect was issued automatically by the routing system to "http://localhost:5000/login/". The URL was defined with a trailing slash so Flask will automatically redirect to the URL with the trailing slash if it was accessed without one. Make sure to directly send your POST-request to this URL since we can't make browsers or HTTP clients redirect with form data reliably or without user interaction.

I think it is to do with where the message flashing is placed but I can't seem to figure out how to fix this. I’m new to flask so not entirely sure what the best option is to solve this issue.

I have included my index.py and login.html file to help reproduce this error. Thanks in advance for the help! :)

Login section of app.py

@app.route('/login/', methods=['GET', 'POST'])
def login():
    form = LoginForm()

    if form.validate_on_submit():
        user = User.query.filter_by(username=form.username.data).first()
        if user:
            if check_password_hash(user.password, form.password.data):
                login_user(user, remember=form.remember.data)
                flash("Invalid username or password")
                return redirect(url_for('dashboard'))

    return render_template('login.html', form=form, errors=form.errors.items())

Login.html Template

{% block body_content %}
<div class="container">

<form method="POST" action="/login">
    {{ form.csrf_token }}
    <div class="form-group">
       {{ form.username }}
    </div>
    <div class="form-group">
        {{ form.password }}
    </div>
    <div class="form-group">
        {{ form.remember }}
    </div>
    <button type="submit" class="btn btn-primary">Sign In</button>
</form>

<div class="errors">
    {% for field, err in errors %}
        <p>{{field}} : {{err|join(', ')}}</p>
    {% endfor %}
</div>

<div class="message-flash">  
    {% for message in get_flashed_messages() %}
      <div class=flash>{{ message }}</div>
    {% endfor %}
</div> 

</div>
{% endblock %}

2 Answers2

6

Add a trailing slash to the action attribute inside the form as suggested in the message:

<form method="POST" action="/login/">

Preferably, use url_for to build URLs:

<form method="POST" action="{{ url_for('login') }}">

Since you're rendering the form with the same view that handles the post, you can omit the action.

<form method="POST">
davidism
  • 121,510
  • 29
  • 395
  • 339
PRMoureu
  • 12,817
  • 6
  • 38
  • 48
  • The reason I has that was because without it I get - "GET /login/ HTTP/1.1" 404 –  Nov 11 '17 at 23:53
  • That is the only place /login/ is used. I think its to do with the fact there is a redirect after the flash but i cant figure out the way to fix it –  Nov 12 '17 at 00:00
  • 1
    i manage to make it work by fixing the action attribute, do you get another error with it ? – PRMoureu Nov 12 '17 at 00:07
  • I no longer get the error but it doesn't display the flash message. Any ideas? –  Nov 12 '17 at 12:32
  • 1
    the message `flash("Invalid username or password")` is placed under the block where password is verified, so you are redirected before seeing anything. You should create another statement (`else`?) to handle the case where the message should be displayed – PRMoureu Nov 12 '17 at 16:22
0

You have two either of the following options:

  • @app.route('/login', methods=['GET', 'POST']) or
  • <form method="POST" action="/login/">

Make them both same.

RaiBnod
  • 2,141
  • 2
  • 19
  • 25