I got Lab 9 up and running per spec and am trying to implement a 'delete' button for each row.

My current code works fine to delete each row in the table except for the first row (id = 1).

When I click 'delete' for the first row it generates an additional row with blank entries.

When I look at the network tab in Chrome it seems the effect of clicking delete on the first row is to route to "/" and trigger the db.execute INSERT statement therein to genereate an additional row with blank entries.

I'm not understanding why it doesn't route to "/deregister" (and trigger the db.execute DELETE statement) as it does for all the other rows.

Code below and any help much appreciated. Thanks!


<!DOCTYPE html>

<html lang="en">
        <link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@500&display=swap" rel="stylesheet">
        <link href="/static/styles.css" rel="stylesheet">
<div class="header">
        <div class="container">
            <div class="section">
            <h2>Add a Birthday</h2>
            <!-- TODO: Create a form for users to submit a name, a month, and a day -->

            <form action="/" method="post"> <!-- submits to / with a method of POST -->
                <input autocomplete="off" autofocus name="name" placeholder="Name" type="text">
                <input autocomplete="off" autofocus name ="month" placeholder="Month" type="text">
                <input autocomplete="off" autofocus name="day" placeholder="Day" type="text">
                <input type="submit">

        <div class="section">

            <h2>All Birthdays</h2>
                    {% for birthday in birthdays %}
                            <td>{{ birthday["name"] }}</td>
                            <td>{{ birthday["month"] }}/{{ birthday["day"] }}</td>
                                <form action="/deregister" method="post"> <!-- submits to /deregister with a method of POST -->
                                    <input name="id" type="hidden" value="{{ birthday.id }}">
                                    <input type="submit" value="Deregister">
                    {% endfor %}


@app.route("/", methods=["GET", "POST"])
def index():
if request.method == "POST": #means user has submitted something via form

    name = request.form.get("name")
    month = request.form.get("month")
    day = request.form.get("day")

    db.execute("INSERT INTO birthdays (name, month, day) VALUES(?, ?, ?)", name, month, day)

    return redirect("/")


    birthdays = db.execute("SELECT * FROM birthdays")

    return render_template("index.html", birthdays=birthdays)

    @app.route("/deregister", methods=["POST"])
    def deregister():
    # delete birthday
    id = request.form.get("id")
    if id:
      db.execute("DELETE FROM birthdays WHERE id = ?", id)

    return redirect("/")

1 Answer 1


Have you validated the HTML? (see Week 8 Lecture, starting at minute 54). The problem is identified in the spoiler, but you might want to take your generated HTML through the Direct Input tab at validator.w3.org. You would need to view the source through the context menu (right-click) in the browser and copy/paste that into the validator.

The first <form> is missing a close tag, so the first row in the birthday list "acts like" it is part of the first <form>

  • Thank you. I clearly need to get in the habit of using the validator. Feb 4, 2022 at 0:38

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .