Search code examples
flask

werkzeug.routing.BuildError: Could not build url for endpoint 'post'. Did you forget to specify values ['post_id']?


Hi I'm newbie to web development. I'm using flask and I have this ff. error:

"Could not build url for endpoint 'post'. Did you forget to specify values ['post_id']?"

I'm trying to redirect the page after deleting a comment in the post. But it brings me to "500 Internal Server Error" page and when I click the back button of my browser, the success flash msg is displayed and the comment was remove.

"routes.py"

@app.route("/post/<int:post_id>")
@login_required
def post(post_id):
    post = Post.query.get_or_404(post_id)
    return render_template("post.html", title="Post", post=post)


@app.route("/post-comment/<int:post_id>", methods=['GET','POST'])
@login_required
def comment_post(post_id):
    post = Post.query.get_or_404(post_id)
    form = CommentForm()
    if form.validate_on_submit():
        comment = Comment(body=form.body.data, post_id=post.id, author=current_user)
        db.session.add(comment)
        db.session.commit()
        flash("Your comment has been added to the post", "success")
        return redirect(url_for("comment_post", post_id=post.id, post=post))
    return render_template("comment.html", title="Comment Post", post_id=post.id, post=post, form=form)


@app.route("/comment-delete/<int:comment_id>", methods=['POST'])
@login_required
def delete_comment(comment_id):
    comment = Comment.query.filter_by(id=comment_id).first()
    if comment.author != current_user:
        abort(403)
    db.session.delete(comment)
    db.session.commit()
    flash('Your comment has been deleted!', 'success')
    return redirect(url_for('post'))
  

"post.html and comment.html" - both has url_for to delete_comment

{% for comment in post.comments %}
       <table>
        <tr>
         <td>
      {% if comment.author == current_user %}
           <form action="{{url_for('delete_comment', comment_id=comment.id, post_id=post.id, post=post)}}" method="POST">
              <input class="btn btn-danger" type="submit" value="Delete">
            </form>
      {% endif %}
            <small class="text-muted">{{ comment.author.username }}</small>
             <p class="mb-1">{{ comment.body }}</p>
           </td>
          </tr>
        </table>
{% endfor %}

DB

class User(db.Model, UserMixin):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(20), unique=True, nullable=False)
    password = db.Column(db.String(60), nullable=False)
    comments = db.relationship('Comment', backref='author', lazy=True)
    posts = db.relationship('Post', backref='author', lazy=True)

    def __repr__(self):
        return f"User('{self.username}')"

class Post(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(100), nullable=False)
    date_posted = db.Column(db.DateTime, nullable=False, default=datetime.utcnow())
    content = db.Column(db.Text, nullable=False)
    user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
    comments = db.relationship("Comment", backref="post", cascade="all, delete-orphan", lazy=True)

    def __repr__(self):
        return f"Post('{self.title}', '{self.date_posted}')"

class Comment(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    body = db.Column(db.String(100), nullable=False)
    user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
    post_id = db.Column(db.Integer, db.ForeignKey('post.id'), nullable=False)

    def __repr__(self):
        return f"Comment('{self.body}')"

Solution

  • In the delete_comment function, when you are redirecting to the post function, you have to pass the post_id also. It should be something like this: return redirect(url_for('post', post_id=post.id)) For this to work you have to fetch the post id from the database.