Elisha
Elisha

Reputation: 51

How to handle a put request from the html form using bottle framework

I am using bottle, and I want to handle a put request from HTML and update a nested dictionary. I know I can do front-end validation but I am currently working on an assignment where this is a requirement.

here is my dictionary of items:

items = {
    'daf-394kd-d-39823-393': {
        "name": "a", "lastname": "a"
    },
    'daf-djfk3-32983-393dg': {
        "name": "b", "lastname": "b"
    }
}

and here is my route:

@put("/items/<item_id>")
def _(item_id):

    new_name = request.forms.get("name")
    new_lastname = request.forms.get("lastname")

    items[item_id] = {"name": new_name, "lastname": new_lastname}

    return redirect("/items")

and here is my HTML code:

<form action="/items" method="post">
   <input type="hidden" name="_method" value="put">
   <label for="">NAME</label>
   <input name="name" type="text" placeholder="name">
   <label for="">LAST NAME</label><br>
   <input name="lastname" type="text" placeholder="lastname"><br><br>
   <button>Update</button>
</form>

I tried to use a hidden input in order to change the post method to put but it doesn't seem to work.

Upvotes: 1

Views: 488

Answers (1)

ggorlen
ggorlen

Reputation: 57394

Surprisingly, I don't see anything in the documentation, GitHub issues, Stack Overflow, or the internet in general about how to add a hidden field to your form to tell Bottle to call the PUT handler for a form submission. Workarounds are to use JS/AJAX to send a PUT request or to use a POST with PUT (update) semantics:

server.py

from bottle import redirect, request, route, run, template

items = {
    "daf-394kd-d-39823-393": {
        "name": "a",
        "lastname": "a"
    },
    "daf-djfk3-32983-393dg": {
        "name": "b",
        "lastname": "b"
    }
}

@route("/items/<item_id>", method="POST")
def items_update(item_id):
    new_name = request.forms.get("name")
    new_lastname = request.forms.get("lastname")
    items[item_id] = {"name": new_name, "lastname": new_lastname}
    return redirect("/items")

@route("/items")
def items_all():
    return template("items.tpl", items=items)

run(host="localhost", port=8080)

items.tpl

<!DOCTYPE html>
<html>
<body>
% for k, v in items.items():
  <div>
    <div>
      id: {{k}}, first name: '{{v["name"]}}', last name: '{{v["lastname"]}}'
    </div>
    <form action="/items/{{k}}" method="post">
      <label for="name">NAME</label>
      <input name="name" placeholder="name">
      <label for="lastname">LAST NAME</label>
      <input name="lastname" placeholder="lastname">
      <input type="submit">
    </form>
  </div>
% end
</body>
</html>

This is less than satisfying since the same route would need explicit branches to differentiate actions:

server.py (partial)

@route("/items/<item_id>", method="POST")
def items_update_delete(item_id):
    if request.forms.get("_method") == "put":
        new_name = request.forms.get("name")
        new_lastname = request.forms.get("lastname")
        items[item_id] = {"name": new_name, "lastname": new_lastname}
    elif request.forms.get("_method") == "delete":
        del items[item_id]

    return redirect("/items")

index.tpl

<!DOCTYPE html>
<html>
<body>
% for k, v in items.items():
  <div>
    <div>
      id: {{k}}, first name: '{{v["name"]}}', last name: '{{v["lastname"]}}'
    </div>
    <form action="/items/{{k}}" method="post">
      <input type="hidden" name="_method" value="put" />
      <label for="name">NAME</label>
      <input name="name" placeholder="name">
      <label for="lastname">LAST NAME</label>
      <input name="lastname" placeholder="lastname">
      <input type="submit">
    </form>
    <form action="/items/{{k}}" method="post">
      <input type="hidden" name="_method" value="delete" />
      <input type="submit" value="Delete">
    </form>
  </div>
% end
</body>
</html>

I'd be happy to see a more idiomatic answer that shows the correct hidden field for triggering Bottle's PUT route and I'll update this answer if I come across it. Opening an issue in Bottle's GitHub repo might be worth doing.

Upvotes: 1

Related Questions