51

I'm getting the following error whenever I try to submit data to my Flask form:

Method Not Allowed The method is not allowed for the requested URL.

I think the issue is in the return redirect(url_for('database')) I'm doing. I've also tried return render_template('database.html) too. I'm trying to call the database page once form entries have been submitted to the database.

Relevant parts of my code are as follows:

@app.route('/entry', methods=['GET', 'POST'])
def entry_page():
    if request.method == 'POST':
        date = request.form['date']
        title = request.form['blog_title']
        post = request.form['blog_main']
        post_entry = models.BlogPost(date = date, title = title, post = post)
        db.session.add(post_entry)
        db.session.commit()
        return redirect(url_for('database'))
    else:
        return render_template('entry.html')

@app.route('/database')        
def database():
    query = []
    for i in session.query(models.BlogPost):
        query.append((i.title, i.post, i.date))
    return render_template('database.html', query = query)

entry.html is...

THIS IS THE BLOG ENTRY PAGE

blog:
<html>
    <form action='/database' method = "post">
        date<input name = "date" type = "text" class="text">
        title<input name = "blog_title" type = "text" class="text">
        main<input name = "blog_main" type = "text" class="text">
        <input type = "submit">
    </form> 
</html>

and database.html...

THIS IS THE QUERY:

{{query}}
Suraj Kapoor
  • 1,615
  • 4
  • 22
  • 34

9 Answers9

65

What is happening here is that database route does not accept any url methods.

I would try putting the url methods in the app route just like you have in the entry_page function:

@app.route('/entry', methods=['GET', 'POST'])
def entry_page():
    if request.method == 'POST':
        date = request.form['date']
        title = request.form['blog_title']
        post = request.form['blog_main']
        post_entry = models.BlogPost(date = date, title = title, post = post)
        db.session.add(post_entry)
        db.session.commit()
        return redirect(url_for('database'))
    else:
        return render_template('entry.html')

@app.route('/database', methods=['GET', 'POST'])        
def database():
    query = []
    for i in session.query(models.BlogPost):
        query.append((i.title, i.post, i.date))
    return render_template('database.html', query = query)
Wondercricket
  • 7,651
  • 2
  • 39
  • 58
  • Thanks, that did the job. Although for some reason it's not committing to the database anymore. – Suraj Kapoor Dec 19 '13 at 19:08
  • 1
    That is because your database submit functionality is in your entry_page function whereas you form post is redirecting to the database function. You may want to move that logic out of the entry_page function and put it into the database function – Wondercricket Dec 19 '13 at 19:12
  • Thanks again, that worked! I'm not sure I fully understand why though. I am asking it to commit data to the database before the redirect occurs, and this works when I'm redirecting to a page other than '/database'. Anyway, appreciate your help. – Suraj Kapoor Dec 19 '13 at 19:27
  • 1
    I'm glad I could help. If you wish to do the database commit before the redirect, then your entry_page function looks correct. You would just need to remove the action attribute in the form tag. If you remove that tag, it will refresh the page with the post method and then should go into your if statement – Wondercricket Dec 19 '13 at 19:29
  • 1
    Putting the URL methods did it for me: .. methods=['GET', 'POST']) ---Thanks! – Leo Gurdian Apr 07 '21 at 07:25
  • may just be me, but it looks exactly like the question asked...? – Dekriel May 26 '22 at 12:34
8

I think you forgot to add methods for your database function.

@app.route('/database', methods=['GET', 'POST']) 
def database():
    query = []
    for i in session.query(models.BlogPost):
        query.append((i.title, i.post, i.date))
    return render_template('database.html', query = query)
Andrew
  • 139
  • 2
  • 3
6

I had a similar problem when I deployed my Flask app in the IIS. Apparently, IIS does not accept route that include an underline ("_"). When I removed the underline, problem was resolved.

Hossein
  • 93
  • 2
  • 7
1

I had the same problem, and my solving was to replace :

return redirect(url_for('index'))

with

return render_template('index.html',data=Todos.query.all())

in my POST and DELETE route.

Ka Wa Yip
  • 2,546
  • 3
  • 22
  • 35
1

flask need to have enctype="" must be added in the form tag. Like below.

<html>
    <form action='/database' method = "post" enctype="multipart/form-data">
        date<input name = "date" type = "text" class="text">
        title<input name = "blog_title" type = "text" class="text">
        main<input name = "blog_main" type = "text" class="text">
        <input type = "submit">
    </form> 
</html>
pavi
  • 11
  • 3
0

I also had similar problem where redirects were giving 404 or 405 randomly on my development server. It was an issue with gunicorn instances.

Turns out that I had not properly shut down the gunicorn instance before starting a new one for testing. Somehow both of the processes were running simultaneously, listening to the same port 8080 and interfering with each other. Strangely enough they continued running in background after I had killed all my terminals. Had to kill them manually using fuser -k 8080/tcp

sanskarsharma
  • 343
  • 3
  • 10
0

try to add methods

@app.route('/database', methods=['GET', 'POST'])

Spectrum
  • 1
  • 1
  • This does not provide an answer to the question. Once you have sufficient [reputation](https://stackoverflow.com/help/whats-reputation) you will be able to [comment on any post](https://stackoverflow.com/help/privileges/comment); instead, [provide answers that don't require clarification from the asker](https://meta.stackexchange.com/questions/214173/why-do-i-need-50-reputation-to-comment-what-can-i-do-instead). - [From Review](/review/late-answers/32639681) – Deenadhayalan Manoharan Sep 08 '22 at 09:30
  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Sep 08 '22 at 13:36
0

Maybe parallel to this error: Say your endpoint is like the following:

    @app.route('/entry', methods=['GET', 'POST'])

Now if in your html the action attribute doesn't match the endpoint mentioned, naturally, you've got an error:

    <!-- N.B. its `entri`; but it should be `entry`-->
    <form action="entri" method="post" class="">

It is obvious, but could be sneaky. Hope it helps someone.

heschmat
  • 73
  • 1
  • 5
0

Took me almost 5 hours and the solution for me is simply just specify the method first, then the action.

<form method = "post" action='/database'>
TCMF
  • 3
  • 2