我有一个博客类型的应用程序,其中主页显示带有一些信息并以Add Comment
形式的帖子。该表单旨在针对该特定帖子写到models.py中的Comments()
模型。
问题:因为我正在循环浏览home.html中的帖子,所以home
中的routes.py
函数无法使用post.id。因此,在验证表单后,注释将应用于所有帖子,而不仅仅是添加注释的帖子。
问题:如何从Jinja post.id
的{{1}}函数中获取相关的home
并将评论应用于特定帖子,而不只是首页上的所有帖子?我没有看到我的逻辑/语法错误-我在这里想念什么?谢谢
forloop
:The resulting error
当然有意义,因为该应用程序不知道我们在AttributeError: 'function' object has no attribute 'id'
的Jinja2 forloop中引用的是哪个帖子。
这是home.html
中的Comments
数据库模型:
models.py
这是我在class Comments(db.Model):
comment_id = db.Column(db.Integer, primary_key=True)
user_id = db.Column(db.Integer, nullable=True, primary_key=False)
post_id = db.Column(db.Integer, nullable=True, primary_key=False)
comment = db.Column(db.String(2000), unique=False, nullable=True)
comment_date = db.Column(db.DateTime, nullable=False, default=datetime.utcnow)
class Meta:
database = db
def fetch_post_comments(self, post_id):
comments = Comments.query.filter(Comments.post_id==post_id)
return comments
def fetch_user(self, user_id):
user = User.query.filter(User.id==user_id).first_or_404()
return user.username
def __repr__(self):
return f"Comments ('{self.user_id}', '{self.post_id}', '{self.comment}', '{self.comment_date}')"
中的home
函数:
routes.py
这是我的@app.route("/")
@app.route("/home", methods=['GET', 'POST'])
@login_required
def home():
page = request.args.get('page', 1, type=int)
posts = Post.query.order_by(Post.date_posted.desc()).paginate(page=page, per_page=5)
comment_form = CommentForm()
def add_comment(post_id):
if comment_form.validate_on_submit():
new_comment = Comments(user_id=current_user.id,
post_id=post_id,
comment=comment_form.comment_string.data)
db.session.add(new_comment)
db.session.commit()
flash('HOT TAKE! Posted your comment.', 'success')
# return redirect(url_for('post', post_id=post.id))
def get_upvote_count(post_id):
count = Vote.query.filter(Vote.post_id==post_id).count()
return count
def get_flag_count(post_id):
count = Flag.query.filter(Flag.post_id == post_id).count()
return count
def get_comment_count(post_id):
count = Comments.query.filter(Comments.post_id == post_id).count()
return count
def get_favorite_count(post_id):
count = Favorites.query.filter(Favorites.post_id == post_id).count()
return count
def get_youtube_id_from_url(url):
video_id = url.split('v=')[1]
if '&' in video_id:
video_id = video_id.split('&')[0]
base_url = "https://www.youtube.com/embed/"
return base_url + video_id
def get_spotify_embed_url(url):
track_or_playlist = url.split('https://open.spotify.com/')[1].split('/')[0]
base_url = f"https://open.spotify.com/embed/{track_or_playlist}/"
spotify_id = url.split('https://open.spotify.com/')[1].split('/')[1]
embed_url = base_url + spotify_id
return embed_url
return base_url + video_id
return render_template('home.html',
posts=posts,
get_upvote_count=get_upvote_count,
get_comment_count=get_comment_count,
get_flag_count=get_flag_count,
get_favorite_count=get_favorite_count,
comment_form=comment_form,
add_comment=add_comment,
get_youtube_id_from_url=get_youtube_id_from_url,
get_spotify_embed_url=get_spotify_embed_url)
home.html
答案 0 :(得分:2)
几个选项:
post.id
作为参数或arg添加到url中,这是arg方法:将网址添加到表单中,并将post.id设置为arg:
<form method="POST" action="{{url_for('home', post_id=post.id)}}" enctype="multipart/form-data">
在路线中:
new_comment = Comments(user_id=current_user.id,
post_id=request.args.get('post_id', type=int),
comment=comment_form.comment_string.data)
OR
post.id
:在表单上添加一个隐藏字段:
post_id = HiddenField()
您需要替换CSRF渲染(hidden_tag()
),以防止自动渲染post_id字段:
{{ comment_form.csrf_token }}
接下来,设置您的隐藏字段数据的值(此功能的积分为this答案):
{% set p = comment_form.post_id.process_data(post.id) %}
{{ comment_form.post_id() }}
最后,在路由中,(删除add_comment声明):
def home():
# Omitted ...
if comment_form.validate_on_submit():
new_comment = Comments(user_id=current_user.id,
post_id=comment_form.post_id.data,
comment=comment_form.comment_string.data)
db.session.add(new_comment)
# etc...
希望这会有所帮助,请注意,它尚未经过测试