2

I have an HTML table which pulls data from an SQLAlchemy database.

In this table, for each row, I have a Delete button, which should delete that row and database entry when I click on it.

The issue I have, is that if I try to delete any row in this table, it deletes only the first row (see image below) and the associated data in the database.

The row and the data I wanted deleted remain unchanged (the 3rd row in the image below).

enter image description here

If I click Delete on the first row in the table, it works without issues.

The Update button works as indented (updating the correct entry)

This is the database model I have:

class ActualPost(db.Model):
    __tablename__ = 'actualpost'
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    title_actual = db.Column(db.String(30), nullable=False, default='actual')
    category_actual = db.Column(db.String(30), nullable=False, default=None)
    actual_amount_name = db.Column(db.String(30), nullable=True)
    actual_amount = db.Column(db.Float, nullable=False)
    user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
    date_posted = db.Column(db.DateTime, nullable=False, default=datetime.utcnow)
    comments = db.Column(db.Text, nullable=True)

    def __repr__(self):
        return f"ActualPost('{self.title_actual}, '{self.category_actual}'\
        , '{self.actual_amount_name}', '{self.actual_amount}'\
        , '{self.date_posted}', '{self.comments}')"

Here are my routes (Update and Delete)

@posts.route("/post/<int:post_id>/update_actual", methods=['GET', 'POST'])
@login_required
def update_actual_post(post_id):
    post = ActualPost.query.get_or_404(post_id)
    if post.actual_author != current_user:
        abort(403)
    form = PostActualForm()
    if form.validate_on_submit():
        post.title_actual = form.title_actual.data
        post.category_actual = form.category_actual.data
        post.actual_amount_name = form.actual_amount_name.data.name
        post.actual_amount = form.actual_amount.data
        post.comments = form.comments.data
        db.session.commit()
        flash('Your post has been updated!', 'success')
        return redirect(url_for('main.actual', post_id=post.id))
    elif request.method == 'GET':
        form.title_actual.data = post.title_actual
        form.category_actual.data= post.category_actual
        form.actual_amount_name.data = post.actual_amount_name
        form.actual_amount.data = post.actual_amount
        form.comments.data = post.comments
    return render_template('create_actual_post.html', title='Update Actual',
                           form=form, legend='Update Actual')


@posts.route("/post/<int:post_id>/delete_actual", methods=['POST'])
@login_required
def delete_actual_post(post_id):
    post = ActualPost.query.get_or_404(post_id)
    if post.actual_author != current_user:
        abort(403)
    db.session.delete(post)
    db.session.commit()
    flash('Your post has been deleted!', 'success')
    return redirect(url_for('main.actual', post_id=post.id))

This is the HTML code I use for the Delete button:

<div class="modal-footer">
   <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
   <form action="{{ url_for('posts.delete_actual_post', post_id = post.id) }}" method="post">
     <input class="btn btn-danger" type="submit" value="Delete">
   </form>
</div>
3
  • 3
    Did you make sure that you are passing the correct post_id to the get_or_404() method by printing to console? Commented Jun 10, 2018 at 23:45
  • 2
    Also in your chrome/firefox developer tools, make sure you check that form's action property and ensure that its correct in the case of that delete button. Commented Jun 10, 2018 at 23:48
  • Thank you for the tips! I have investigated further, and it seems that the modal I have in my html is the culprit. I have it placed in a for loop and it is not getting the ID correctly. Commented Jun 11, 2018 at 11:05

2 Answers 2

2

Here is my code to delete particular row by id. You can co-relate it with your code

SQL-alchemy Modal :

class Componants(db.Model):
    __tablename__ = 'componants'
    id = db.Column(db.Integer, primary_key=True)
    cmp_options = db.Column(db.Text, default=None)
    updated_at = db.Column(db.DateTime, nullable=True)
    created_at = db.Column(db.DateTime, nullable=True)


def __init__(self , cmp_options ):
    self.cmp_options = cmp_options 
    self.created_at = datetime.now()
    self.updated_at = datetime.now()

def __repr__(self):
    return '<id {}>'.format(self.id)

Controller :

@componants_blueprint.route('/delete_component/<component_id>')
@login_required
def delete_component(component_id):
    component = Componants.query.filter_by(id=component_id).first_or_404()
    db.session.delete(component)
    db.session.commit() 
    return True

View:

              <tbody>
                {% for item in all_components %}
                <tr>
                  <td>{{ item.id }}</td>
                  <td>{{ item.cmp_options }}</td>
                  <td>{{ item.created_at }}</td>
                  <td class="text-center"> 
                    <a href="{{ url_for('componants.delete_component', component_id=item.id) }}" title="Delete" class="far fa-trash-alt"></a>
                  </td>    
                </tr>
                {% endfor %}
            </tbody>
Sign up to request clarification or add additional context in comments.

Comments

0

The above did not help me. But the comments in this post did help me.

In short: the problem is inside the HTML tags. I used a 'modal' from the Bootstrap.

The comments in this page suggested to inspect the page elements.

Also in your chrome/firefox developer tools, make sure you check that form's action property and ensure that its correct in the case of that delete button. – Prahlad Yeri Jun 10, 2018 at 23:48

The inspection showed that each row in the table did create 'some' unique features such as the name of the item I like to delete. However, during 'inspect' I clicked on my delete button. This showed that the action was stuck in the first line of the table. It did not jump to the line where I clicked 'delete'.

What is inside the HTML generating the issue? Is it the row or is it the modal?

I noticed that the html tag for the modal 'id' was the same for all rows in my table. Question: shouldn't it be unique for each row? I guess, yes.

So, I added the jinja tag to my ID. Would it work? Yes, for me it did...

{% block table %}
<table id="data" class="table table-striped">
    <thead>
      <tr>
          <th scope="col">Name</th>
          <th scope="col">Latitude</th>
          <th scope="col">Longitude</th>
          <th scope="col">Jars</th>
          <th scope="col">Actions</th>
      </tr>
    </thead>
    <tbody>
      {% for map in maps %}
        <tr>
          <td>{{ map.map_name }}</td>
          <td>{{ map.latitude }}</td>
          <td>{{ map.longitude }}</td>
          <td><span style="white-space: pre-line">{% for jar in map.jar_id %}
                                                        {{ jar.jar_name }}
                                                    {% endfor %}
                </span>
            </td>
          <td><!-- Button trigger modal -->
                <button type="button" class="btn btn-warning" data-bs-toggle="modal" data-bs-target="#{{map.map_name}}Modal">
                    Delete
                </button>
                <!-- Modal -->
                <div class="modal fade" id="{{map.map_name}}Modal" tabindex="-1" aria-labelledby="{{map.map_name}}ModalLabel" aria-hidden="true">
                    <div class="modal-dialog">
                        <div class="modal-content">
                            <div class="modal-header">
                                <h5 class="modal-title" id="{{map.map_name}}ModalLabel">Are you sure?</h5>
                                <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
                            </div>
                            <div class="modal-body">
                            <p>Are you sure to delete the item : {{ map.map_name }}</p>
                            </div>
                            <div class="modal-footer">
                                <a href="{{ url_for('map._map_name_delete', map_name=map.map_name) }}" class="btn btn-primary" tabindex="-1" role="button">Yes</a>
                                <a href="{{ url_for('map.table_maps')}}" class="btn btn-primary" tabindex="-1" role="button">No</a>
                            </div>
                        </div>
                    </div>
                </div>
            </td>
        </tr>
      {% endfor %}
    </tbody>
  </table>
{% endblock %}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.