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

I'm trying to write a delete method for the Flask tutorial app, Flaskr. So far I've been able to set up a delete method and modify my html to access it, but when I try to use it, I receive an error saying "Method Not Allowed The method is not allowed for the requested URL."

Here's my method

@app.route('/delete', methods=['DELETE'])
def delete_entry():
    if not session.get('logged_in'):
        abort(401)
    g.db.execute('delete from entries')
    g.db.commit()
    flash('Entry was successfully deleted')
    return redirect(url_for('show_entries'))

Here's my HTML file

{% extends "layout.html" %}
{% block body %}
  {% if session.logged_in %}
    <form action="{{ url_for('add_entry') }}" method=post class=add-entry>
      <dl>
        <dt>Title:
        <dd><input type=text size=30 name=title>
        <dt>Text:
        <dd><textarea name=text rows=5 cols=40></textarea>
        <dd><input type=submit value=Share>
      </dl>
    </form>
  {% endif %}
  <ul class=entries>
  {% for entry in entries %}
    <li><h2>{{ entry.title }}</h2>{{ entry.text|safe }}
      <form action="{{ url_for('delete_entry') }}" method=delete      class=delete_entry>
          <input type="submit" value="Delete entry" />
      </form>
  {% else %}
    <li><em>Unbelievable.  No entries here so far</em>
  {% endfor %}
  </ul>
{% endblock %}

Upvotes: 1

Views: 5584

Answers (1)

Wombatz
Wombatz

Reputation: 5458

I also know that problem :)

In this SO question or here it is explained that the method field of an html <form> only accepts GET and POST as valid values. You are giving it the value DELETE. I suppose that it will fall back to any of the other valid values.

You can indeed verify which method is actually used in your flask log. Because of the falling back your view at /delete will be accessed using a method which is not present in the methods parameter.

There are two ways to work around this.

  1. Make the view accessible by GET or POST. This is the worse of the two options because a GET request should not have any side effects and it is not RESTful

  2. Instead of using the "built-in" html form you can use an ajax request.

For the second option you would register an event handler for your form button using jQuery.

$("#delete_btn").click(function(){
    // send ajax request here
    return false; // prevent the form from submitting
}

where delete_btn would be the id for you submit button.

<input id="delete_btn" value="Delete entry">

For the actual ajax request use the ajax method from jQuery ( see the docs )

$.ajax({
    url: "your delete url",
    method: "DELETE",
})

You can also register a callback in the ajax method to reload the page on success and display a warning when it fails or whatever you want.

And please don't fill in the url for the ajax request by using the url_for function. This will unnecessarily couple the javascript to your html. You should instead write it into a custom data attribute of the submit button and read that attribute with jQuery. Like it is done here

Upvotes: 1

Related Questions